}
/**
- * \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) {
}
/**
- * \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: ... */
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);
* - 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)
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;
}
}
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;
}
{
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 */
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;
}
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;
}
* 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;
}
}
}
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);
/* simgrid.task mt */
lua_pop(L, 2);
/* -- */
+
+ /* set up MSG to copy Lua tasks between states */
+ MSG_task_set_copy_callback(task_copy_callback);
}
/**