+/* ********************************************************************************* */
+/* simgrid.comm API */
+/* ********************************************************************************* */
+
+/**
+ * \brief Ensures that a value in the stack is a comm and returns it.
+ * \param L a Lua state
+ * \param index an index in the Lua stack
+ * \return the C 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;
+}
+
+/**
+ * \brief Blocks the current process until a communication is finished.
+ * \param L a Lua state
+ * \return number of values returned to Lua
+ *
+ * - Argument 1 (comm): a comm (previously created by isend or irecv)
+ * - Argument 2 (number, optional): timeout (default is no timeout)
+ * - Return values (task or nil + string): in case of success, returns the task
+ * received if you are the receiver and nil if you are the sender. In case of
+ * failure, returns nil plus an error string.
+ */
+static int l_comm_wait(lua_State* L) {
+
+ msg_comm_t comm = sglua_checkcomm(L, 1);
+ double timeout = -1;
+ if (lua_gettop(L) >= 2) {
+ timeout = luaL_checknumber(L, 2);
+ }
+ /* comm ... */
+ MSG_error_t res = MSG_comm_wait(comm, timeout);
+
+ if (res == MSG_OK) {
+ m_task_t task = MSG_comm_get_task(comm);
+ if (MSG_task_get_sender(task) == MSG_process_self()) {
+ /* I'm the sender */
+ return 0;
+ }
+ else {
+ /* I'm the receiver: copy the Lua task from the sender */
+ task_copy(L, task);
+ /* comm ... task */
+ return 1;
+ }
+ }
+ else {
+ /* the communication has failed */
+ lua_pushnil(L);
+ /* comm ... nil */
+ lua_pushstring(L, msg_errors[res]);
+ /* comm ... nil error */
+ return 2;
+ }
+}
+
+/**
+ * @brief Returns whether a communication is finished.
+ *
+ * Unlike wait(), This function always returns immediately.
+ *
+ * - Argument 1 (comm): a comm (previously created by isend or irecv)
+ * - 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)) {
+ /* 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) {
+ 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 ... task */
+ return 1;
+ }
+ }
+ else {
+ /* the communication has failed */
+ lua_pushnil(L);
+ /* comm ... nil */
+ lua_pushstring(L, msg_errors[res]);
+ /* comm ... nil error */
+ return 2;
+ }
+ }
+}
+
+static const luaL_reg comm_functions[] = {
+ {"wait", l_comm_wait},
+ {"test", l_comm_test},
+ /* TODO waitany, testany */
+ {NULL, NULL}
+};
+
+/**
+ * \brief Finalizes a comm userdata.
+ * \param L a Lua state
+ * \return number of values returned to Lua
+ *
+ * - Argument 1 (userdata): a comm
+ */
+static int l_comm_gc(lua_State* L)
+{
+ /* ctask */
+ msg_comm_t comm = *((msg_comm_t*) luaL_checkudata(L, 1, COMM_MODULE_NAME));
+ MSG_comm_destroy(comm);
+ return 0;
+}
+
+/**
+ * \brief Metamethods of the comm userdata.
+ */
+static const luaL_reg comm_meta[] = {
+ {"__gc", l_comm_gc},
+ {NULL, NULL}
+};
+