Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Lua: add support of closures to the state cloner
authorChristophe Thiéry <christopho128@gmail.com>
Thu, 6 Oct 2011 14:26:52 +0000 (16:26 +0200)
committerChristophe Thiéry <christopho128@gmail.com>
Thu, 6 Oct 2011 14:26:52 +0000 (16:26 +0200)
examples/lua/masterslave/slave.lua
src/bindings/lua/lua_state_cloner.c
src/bindings/lua/simgrid_lua.c

index 9c257c4..9ecddc6 100644 (file)
@@ -6,6 +6,7 @@ function Slave(...)
 local my_mailbox="slave "..arg[1]
 simgrid.info("Hello from lua, I'm a poor slave with mbox: "..my_mailbox)
 
 local my_mailbox="slave "..arg[1]
 simgrid.info("Hello from lua, I'm a poor slave with mbox: "..my_mailbox)
 
+
 while true do
 
   local tk = simgrid.Task.recv(my_mailbox);
 while true do
 
   local tk = simgrid.Task.recv(my_mailbox);
index e5789ec..4e35f18 100644 (file)
@@ -126,10 +126,10 @@ static void sglua_get_table_by_ptr(lua_State* L, void* maestro_table_ptr) {
 /**
  * @brief Pops a value from the stack of a source state and pushes it on the
  * stack of another state.
 /**
  * @brief Pops a value from the stack of a source state and pushes it on the
  * stack of another state.
- *
  * If the value is a table, its content is copied recursively.
  *
  * If the value is a table, its content is copied recursively.
  *
- * TODO: add support of closures
+ * This function is similar to lua_xmove() but it allows to move a value
+ * between two different global states.
  *
  * @param src the source state (not necessarily maestro)
  * @param dst the destination state
  *
  * @param src the source state (not necessarily maestro)
  * @param dst the destination state
@@ -377,9 +377,33 @@ static void sglua_copy_table(lua_State* src, lua_State* dst) {
 static void sglua_copy_function(lua_State* src, lua_State* dst) {
 
   if (lua_iscfunction(src, -1)) {
 static void sglua_copy_function(lua_State* src, lua_State* dst) {
 
   if (lua_iscfunction(src, -1)) {
-    /* it's a C function: just copy the pointer */
-    lua_CFunction f = lua_tocfunction(src, -1);
-    lua_pushcfunction(dst, f);
+    /* it's a C function */
+
+    XBT_DEBUG("It's a C function");
+    sglua_stack_dump("src before copying upvalues: ", src);
+
+    /* get the function pointer */
+    int function_index = lua_gettop(src);
+    lua_CFunction f = lua_tocfunction(src, function_index);
+
+    /* copy the upvalues */
+    int i = 0;
+    const char* upvalue_name = NULL;
+    do {
+      i++;
+      upvalue_name = lua_getupvalue(src, function_index, i);
+
+      if (upvalue_name != NULL) {
+        XBT_DEBUG("Upvalue %s", upvalue_name);
+        sglua_move_value(src, dst);
+      }
+    } while (upvalue_name != NULL);
+
+    sglua_stack_dump("src before copying pointer: ", src);
+
+    /* set the function */
+    lua_pushcclosure(dst, f, i - 1);
+    XBT_DEBUG("Function pointer copied");
   }
   else {
     /* it's a Lua function: dump it from src */
   }
   else {
     /* it's a Lua function: dump it from src */
@@ -584,11 +608,9 @@ lua_State* sglua_clone_maestro(void) {
   lua_rawset(L, LUA_REGISTRYINDEX);
                                             /* -- */
 
   lua_rawset(L, LUA_REGISTRYINDEX);
                                             /* -- */
 
-  /* open the standard libs (theoretically, this is not necessary as they can
-   * be inherited like any global values, but without a proper support of
-   * closures, iterators like ipairs don't work). */
-  XBT_DEBUG("Metatable of globals and registry set, opening standard libraries now");
-  luaL_openlibs(L);
+  /* opening the standard libs is not necessary as they are
+   * be inherited like any global values */
+  /* luaL_openlibs(L); */
 
   XBT_DEBUG("New state created");
 
 
   XBT_DEBUG("New state created");
 
index 611b475..5fdd7c1 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "simgrid_lua.h"
 #include "lua_state_cloner.h"
 
 #include "simgrid_lua.h"
 #include "lua_state_cloner.h"
+#include "lua_utils.h"
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(lua, "Lua Bindings");
 
 
 XBT_LOG_NEW_DEFAULT_CATEGORY(lua, "Lua Bindings");
 
@@ -23,24 +24,26 @@ static lua_State *lua_maestro_state;
 
 static void register_c_functions(lua_State *L);
 
 
 static void register_c_functions(lua_State *L);
 
-/*
 static void *my_checkudata (lua_State *L, int ud, const char *tname) {
 static void *my_checkudata (lua_State *L, int ud, const char *tname) {
+
+  XBT_DEBUG("Checking the task: ud = %d", ud);
+  sglua_stack_dump("my_checkudata: ", L);
   void *p = lua_touserdata(L, ud);
   lua_getfield(L, LUA_REGISTRYINDEX, tname);
   const void* correct_mt = lua_topointer(L, -1);
 
   int has_mt = lua_getmetatable(L, ud);
   void *p = lua_touserdata(L, ud);
   lua_getfield(L, LUA_REGISTRYINDEX, tname);
   const void* correct_mt = lua_topointer(L, -1);
 
   int has_mt = lua_getmetatable(L, ud);
+  XBT_DEBUG("Checking the task: has metatable ? %d", has_mt);
   const void* actual_mt = NULL;
   if (has_mt) { actual_mt = lua_topointer(L, -1); lua_pop(L, 1); }
   XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
   const void* actual_mt = NULL;
   if (has_mt) { actual_mt = lua_topointer(L, -1); lua_pop(L, 1); }
   XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
-  stack_dump("my_checkudata: ", L);
+  sglua_stack_dump("my_checkudata: ", L);
 
   if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
     luaL_typerror(L, ud, tname);
   lua_pop(L, 2);
   return p;
 }
 
   if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
     luaL_typerror(L, ud, tname);
   lua_pop(L, 2);
   return p;
 }
-*/
 
 /**
  * @brief Ensures that a userdata on the stack is a task
 
 /**
  * @brief Ensures that a userdata on the stack is a task
@@ -52,6 +55,7 @@ static void *my_checkudata (lua_State *L, int ud, const char *tname) {
 static m_task_t checkTask(lua_State * L, int index)
 {
   m_task_t *pi, tk;
 static m_task_t checkTask(lua_State * L, int index)
 {
   m_task_t *pi, tk;
+  XBT_DEBUG("Lua task: %s", sglua_tostring(L, index));
   luaL_checktype(L, index, LUA_TTABLE);
   lua_getfield(L, index, "__simgrid_task");
 
   luaL_checktype(L, index, LUA_TTABLE);
   lua_getfield(L, index, "__simgrid_task");