1 /* Copyright (c) 2010, 2012. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "lua_private.h"
10 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua_comm, bindings, "Lua bindings (comm module)");
12 #define COMM_MODULE_NAME "simgrid.comm"
14 /* ********************************************************************************* */
15 /* simgrid.comm API */
16 /* ********************************************************************************* */
19 * \brief Ensures that a value in the stack is a comm and returns it.
20 * \param L a Lua state
21 * \param index an index in the Lua stack
24 msg_comm_t sglua_check_comm(lua_State* L, int index)
26 msg_comm_t comm = *((msg_comm_t*) luaL_checkudata(L, index, COMM_MODULE_NAME));
31 * \brief Pushes a comm onto the stack.
32 * \param L a Lua state
35 void sglua_push_comm(lua_State* L, msg_comm_t comm)
37 msg_comm_t* userdata = (msg_comm_t*) lua_newuserdata(L, sizeof(msg_comm_t));
40 luaL_getmetatable(L, COMM_MODULE_NAME);
42 lua_setmetatable(L, -2);
47 * \brief Blocks the current process until a communication is finished.
48 * \param L a Lua state
49 * \return number of values returned to Lua
51 * - Argument 1 (comm): a comm (previously created by isend or irecv)
52 * - Argument 2 (number, optional): timeout (default is no timeout)
53 * - Return values (task or nil + string): in case of success, returns the task
54 * received if you are the receiver and nil if you are the sender. In case of
55 * failure, returns nil plus an error string.
57 static int l_comm_wait(lua_State* L) {
59 msg_comm_t comm = sglua_check_comm(L, 1);
61 if (lua_gettop(L) >= 2) {
62 timeout = luaL_checknumber(L, 2);
65 msg_error_t res = MSG_comm_wait(comm, timeout);
68 msg_task_t task = MSG_comm_get_task(comm);
69 if (MSG_task_get_sender(task) == MSG_process_self()) {
74 /* I'm the receiver: find the Lua task from the C task */
75 sglua_task_unregister(L, task);
81 /* the communication has failed */
84 lua_pushstring(L, sglua_get_msg_error(res));
85 /* comm ... nil error */
91 * @brief Returns whether a communication is finished.
93 * Unlike wait(), This function always returns immediately.
95 * - Argument 1 (comm): a comm (previously created by isend or irecv)
96 * - Return values (task/boolean or nil + string): if the communication is not
97 * finished, return false. If the communication is finished and was successful,
98 * returns the task received if you are the receiver or true if you are the
99 * sender. If the communication is finished and has failed, returns nil
100 * plus an error string.
102 static int l_comm_test(lua_State* L) {
104 msg_comm_t comm = sglua_check_comm(L, 1);
106 if (!MSG_comm_test(comm)) {
107 /* not finished yet */
108 lua_pushboolean(L, 0);
113 /* finished but may have failed */
114 msg_error_t res = MSG_comm_get_status(comm);
117 msg_task_t task = MSG_comm_get_task(comm);
118 if (MSG_task_get_sender(task) == MSG_process_self()) {
120 lua_pushboolean(L, 1);
125 /* I'm the receiver: find the Lua task from the C task*/
126 sglua_task_unregister(L, task);
132 /* the communication has failed */
135 lua_pushstring(L, sglua_get_msg_error(res));
136 /* comm ... nil error */
142 static const luaL_reg comm_functions[] = {
143 {"wait", l_comm_wait},
144 {"test", l_comm_test},
145 /* TODO waitany, testany */
150 * \brief Finalizes a comm userdata.
151 * \param L a Lua state
152 * \return number of values returned to Lua
154 * - Argument 1 (userdata): a comm
156 static int l_comm_gc(lua_State* L)
159 msg_comm_t comm = *((msg_comm_t*) luaL_checkudata(L, 1, COMM_MODULE_NAME));
160 MSG_comm_destroy(comm);
165 * \brief Metamethods of the comm userdata.
167 static const luaL_reg comm_meta[] = {
173 * \brief Registers the comm functions into the table simgrid.comm.
175 * Also initialize the metatable of the comm userdata type.
177 * \param L a lua state
179 void sglua_register_comm_functions(lua_State* L)
181 /* create a table simgrid.com and fill it with com functions */
182 luaL_openlib(L, COMM_MODULE_NAME, comm_functions, 0);
185 /* create the metatable for comms, add it to the Lua registry */
186 luaL_newmetatable(L, COMM_MODULE_NAME);
187 /* simgrid.comm mt */
188 /* fill the metatable */
189 luaL_openlib(L, NULL, comm_meta, 0);
190 /* simgrid.comm mt */
191 lua_pushvalue(L, -2);
192 /* simgrid.comm mt simgrid.comm */
193 /* metatable.__index = simgrid.comm
194 * we put the comm functions inside the comm itself:
195 * this allows to write my_comm:method(args) for
196 * simgrid.comm.method(my_comm, args) */
197 lua_setfield(L, -2, "__index");
198 /* simgrid.comm mt */