-
- /* pop the value from src */
- lua_pop(src, 1);
-
- stack_dump("src after copying a value (should be ...): ", src);
- stack_dump("dst after copying a value (should be visited ... value): ", dst);
-}
-
-/**
- * @brief Copies a global value from the father state.
- *
- * The state L must have a father, i.e. it should have been created by
- * clone_lua_state().
- * This function is meant to be an __index metamethod.
- * Consequently, it assumes that the stack has two elements:
- * a table (usually the environment of L) and the string key of a value
- * that does not exist yet in this table. It copies the corresponding global
- * value from the father state and pushes it on the stack of L.
- * If the global value does not exist in the father state either, nil is
- * pushed.
- *
- * TODO: make this function thread safe. If the simulation runs in parallel,
- * several simulated processes may trigger this __index metamethod at the same
- * time and get globals from maestro.
- *
- * @param L the current state
- * @return number of return values pushed (always 1)
- */
-static int l_get_from_father(lua_State *L) {
-
- /* retrieve the father */
- lua_getfield(L, LUA_REGISTRYINDEX, "simgrid.father_state");
- lua_State* father = lua_touserdata(L, -1);
- xbt_assert(father != NULL, "This Lua state has no father");
- lua_pop(L, 1);
-
- /* get the global from the father */
- const char* key = luaL_checkstring(L, 2); /* L: table key */
- lua_getglobal(father, key); /* father: ... value */
- XBT_DEBUG("__index of '%s' begins", key);
-
- /* push the value onto the stack of L */
- lua_newtable(L); /* L: table key visited */
- lua_insert(L, 1); /* L: visited table key */
- move_value(L, father, key); /* father: ...
- L: visited table key value */
- lua_remove(L, 1); /* L: table key value */
-
- /* prepare the return value of __index */
- lua_pushvalue(L, -1); /* L: table key value value */
- lua_insert(L, 1); /* L: value table key value */
-
- /* save the copied value in the table for subsequent accesses */
- lua_settable(L, -3); /* L: value table */
- lua_remove(L, 2); /* L: value */
-
- XBT_DEBUG("__index of '%s' returns %s", key, value_tostring(L, -1));
-
- return 1;
-}
-
-/**
- * @brief Creates a new Lua state and get its environment from an existing state.
- *
- * The state created is independent from the existing one and has its own
- * copies of global variables and functions.
- * However, the global variables and functions are not copied right now from
- * the original state; they are copied only the first time they are accessed.
- * This behavior saves time and memory, and is okay for Simgrid's needs.
- *
- * @param father an existing state
- * @return the state created
- */
-static lua_State* clone_lua_state(lua_State *father) {
-
- /* create the new state */
- lua_State *L = luaL_newstate();
-
- /* set its environment:
- * - create a table newenv
- * - create a metatable mt
- * - set mt.__index = a function that copies the global from the father state
- * - set mt as the metatable of newenv
- * - set newenv as the environment of the new state
- */
- lua_pushthread(L); /* thread */
- lua_newtable(L); /* thread newenv */
- lua_newtable(L); /* thread newenv mt */
- lua_pushcfunction(L, l_get_from_father); /* thread newenv mt f */
- lua_setfield(L, -2, "__index"); /* thread newenv mt */
- lua_setmetatable(L, -2); /* thread newenv */
- lua_setfenv(L, -2); /* thread */
- lua_pop(L, 1); /* -- */
-
- /* open the standard libs (theoretically, this is not necessary) */
- luaL_openlibs(L);
-
- /* put a pointer to the father */
- lua_pushlightuserdata(L, father);
- lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.father_state");
-
- XBT_DEBUG("New state created");
-
- return L;