Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Lua: copy the Lua task right after the C task using an MSG callback
[simgrid.git] / src / bindings / lua / simgrid_lua.c
index 90310d3..b2d541a 100644 (file)
@@ -163,12 +163,8 @@ static int l_task_execute(lua_State* L)
 }
 
 /**
- * \brief Pops the Lua task on top of the stack and registers it so that a
- * receiver can retrieve it later knowing the C task.
- *
- * After calling this function, you can send the C task to someone and he
- * will be able to also get the corresponding Lua task.
- *
+ * \brief Pops the Lua task from the stack and registers it so that the
+ * process can retrieve it later knowing the C task.
  * \param L a lua state
  */
 static void task_register(lua_State* L) {
@@ -202,18 +198,19 @@ static void task_unregister(lua_State* L, m_task_t task) {
 }
 
 /**
- * \brief When a C task has been received, retrieves the corresponding Lua
- * task from the sender and pushes it onto the receiver's stack.
+ * \brief This function is called when a C task has just been copied.
  *
- * This function should be called from the receiver process.
+ * This callback is used to copy the corresponding Lua task.
  *
- * \param dst the receiver
- * \param task the task just received
+ * \param task the task copied
+ * \param src_process the sender
+ * \param dst_process the receiver
  */
-static void task_copy(lua_State* dst, m_task_t task) {
+static void task_copy_callback(m_task_t task, m_process_t src_process,
+    m_process_t dst_process) {
 
-  m_process_t src_proc = MSG_task_get_sender(task);
-  lua_State* src = MSG_process_get_data(src_proc);
+  lua_State* src = MSG_process_get_data(src_process);
+  lua_State* dst = MSG_process_get_data(dst_process);
 
                                   /* src: ...
                                      dst: ... */
@@ -222,10 +219,10 @@ static void task_copy(lua_State* dst, m_task_t task) {
   sglua_copy_value(src, dst);
                                   /* src: ... task
                                      dst: ... task */
+  task_register(dst);             /* dst: ... */
 
-  /* the receiver is the owner of the task and may destroy it:
-   * make the C task NULL on the sender side so that it doesn't garbage
-   * collect it */
+  /* the receiver is now the owner of the task and may destroy it:
+   * make the sender forget the C task so that it doesn't garbage */
   lua_getfield(src, -1, "__simgrid_task");
                                   /* src: ... task ctask */
   m_task_t* udata = (m_task_t*) luaL_checkudata(src, -1, TASK_MODULE_NAME);
@@ -242,8 +239,8 @@ static void task_copy(lua_State* dst, m_task_t task) {
  * - Argument 1 (task): the task to send
  * - Argument 2 (string or compatible): mailbox name, as a real string or any
  * type convertible to string (numbers always are)
- * - Return values (nil or string): nil if the communication was successful,
- * or an error string in case of failure, which may be "timeout",
+ * - Return values (boolean + string): true if the communication was successful,
+ * or false plus an error string in case of failure, which may be "timeout",
  * "host failure" or "transfer failure"
  */
 static int l_task_send(lua_State* L)
@@ -258,15 +255,19 @@ static int l_task_send(lua_State* L)
   MSG_error_t res = MSG_task_send(task, mailbox);
 
   if (res == MSG_OK) {
-    return 0;
+    lua_pushboolean(L, 1);
+                                  /* true */
+    return 1;
   }
   else {
     /* the communication has failed, I'm still the owner of the task */
     task_unregister(L, task);
                                   /* task */
+    lua_pushboolean(L, 0);
+                                  /* task false */
     lua_pushstring(L, msg_errors[res]);
-                                  /* task error */
-    return 1;
+                                  /* task false error */
+    return 2;
   }
 }
 
@@ -361,7 +362,7 @@ static int l_task_recv(lua_State* L)
   MSG_error_t res = MSG_task_receive_with_timeout(&task, mailbox, timeout);
 
   if (res == MSG_OK) {
-    task_copy(L, task);
+    task_unregister(L, task);
                                   /* mailbox ... task */
     return 1;
   }
@@ -392,8 +393,8 @@ static int l_task_irecv(lua_State* L)
 {
   const char* mailbox = luaL_checkstring(L, 1);
                                   /* mailbox ... */
-  m_task_t task;
-  msg_comm_t comm = MSG_task_irecv(&task, mailbox);
+  m_task_t* task = xbt_new0(m_task_t, 1); // FIXME fix this leak
+  msg_comm_t comm = MSG_task_irecv(task, mailbox);
 
   msg_comm_t* userdata = (msg_comm_t*) lua_newuserdata(L, sizeof(msg_comm_t));
                                   /* mailbox ... comm */
@@ -474,7 +475,6 @@ static const luaL_reg task_meta[] = {
 static msg_comm_t sglua_checkcomm(lua_State* L, int index)
 {
   msg_comm_t comm = *((msg_comm_t*) luaL_checkudata(L, index, COMM_MODULE_NAME));
-  lua_pop(L, 1);
   return comm;
 }
 
@@ -506,8 +506,8 @@ static int l_comm_wait(lua_State* L) {
       return 0;
     }
     else {
-      /* I'm the receiver: copy the Lua task from the sender */
-      task_copy(L, task);
+      /* I'm the receiver: find the Lua task from the C task */
+      task_unregister(L, task);
                                   /* comm ... task */
       return 1;
     }
@@ -528,44 +528,48 @@ static int l_comm_wait(lua_State* L) {
  * Unlike wait(), This function always returns immediately.
  *
  * - Argument 1 (comm): a comm (previously created by isend or irecv)
- * - Return value 1 (boolean): indicates whether the comm is finished
- * (note that a finished comm may have failed)
- * - Return value 2 (task): if you are the receiver, returns the task received
- * in case of success, or nil if the comm has failed
- * - Return value 3 (string): if the comm has failed, returns an error string
+ * - Return values (task/boolean or nil + string): if the communication is not
+ * finished, return false. If the communication is finished and was successful,
+ * returns the task received if you are the receiver or true if you are the
+ * sender. If the communication is finished and has failed, returns nil
+ * plus an error string.
  */
 static int l_comm_test(lua_State* L) {
 
   msg_comm_t comm = sglua_checkcomm(L, 1);
                                   /* comm ... */
   if (!MSG_comm_test(comm)) {
-    return 0;
+    /* not finished yet */
+    lua_pushboolean(L, 0);
+                                  /* comm ... false */
+    return 1;
   }
   else {
+    /* finished but may have failed */
     MSG_error_t res = MSG_comm_get_status(comm);
 
     if (res == MSG_OK) {
-      lua_pushboolean(L, 1);
-                                  /* comm ... true */
       m_task_t task = MSG_comm_get_task(comm);
       if (MSG_task_get_sender(task) == MSG_process_self()) {
         /* I'm the sender */
+        lua_pushboolean(L, 1);
+                                  /* comm ... true */
         return 1;
       }
       else {
-        /* I'm the receiver: copy the Lua task from the sender */
-        task_copy(L, task);
-                                    /* comm ... true task */
-        return 2;
+        /* I'm the receiver: find the Lua task from the C task*/
+        task_unregister(L, task);
+                                  /* comm ... task */
+        return 1;
       }
     }
     else {
       /* the communication has failed */
       lua_pushnil(L);
-                                    /* comm ... true nil */
+                                  /* comm ... nil */
       lua_pushstring(L, msg_errors[res]);
-                                    /* comm ... true nil error */
-      return 3;
+                                  /* comm ... nil error */
+      return 2;
     }
   }
 }
@@ -873,9 +877,9 @@ static int gras_add_process_function(lua_State * L)
   if (xbt_dict_is_empty(machine_set)
       || xbt_dict_is_empty(process_function_set)
       || xbt_dynar_is_empty(process_list)) {
-    process_function_set = xbt_dict_new();
+    process_function_set = xbt_dict_new_homogeneous(NULL);
     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
-    machine_set = xbt_dict_new();
+    machine_set = xbt_dict_new_homogeneous(NULL);
   }
 
   xbt_dict_set(machine_set, process_host, NULL, NULL);
@@ -1216,6 +1220,9 @@ static void register_task_functions(lua_State* L)
                                   /* simgrid.task mt */
   lua_pop(L, 2);
                                   /* -- */
+
+  /* set up MSG to copy Lua tasks between states */
+  MSG_task_set_copy_callback(task_copy_callback);
 }
 
 /**