diff options
Diffstat (limited to '')
-rw-r--r-- | src/state.cpp (renamed from src/state.c) | 253 |
1 files changed, 130 insertions, 123 deletions
diff --git a/src/state.c b/src/state.cpp index 32e5b47..4a5f995 100644 --- a/src/state.c +++ b/src/state.cpp | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * STATE.C | 2 | * STATE.CPP |
3 | * | 3 | * |
4 | * Lua tools to support Lanes. | 4 | * Lua tools to support Lanes. |
5 | */ | 5 | */ |
@@ -8,7 +8,7 @@ | |||
8 | =============================================================================== | 8 | =============================================================================== |
9 | 9 | ||
10 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> | 10 | Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> |
11 | 2011-21 benoit Germain <bnt.germain@gmail.com> | 11 | 2011-24 benoit Germain <bnt.germain@gmail.com> |
12 | 12 | ||
13 | Permission is hereby granted, free of charge, to any person obtaining a copy | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy |
14 | of this software and associated documentation files (the "Software"), to deal | 14 | of this software and associated documentation files (the "Software"), to deal |
@@ -31,20 +31,11 @@ THE SOFTWARE. | |||
31 | =============================================================================== | 31 | =============================================================================== |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include <stdio.h> | 34 | #include "state.h" |
35 | #include <assert.h> | 35 | |
36 | #include <string.h> | ||
37 | #include <ctype.h> | ||
38 | #include <stdlib.h> | ||
39 | #if !defined(__APPLE__) | ||
40 | #include <malloc.h> | ||
41 | #endif // __APPLE__ | ||
42 | |||
43 | #include "compat.h" | ||
44 | #include "macros_and_utils.h" | ||
45 | #include "universe.h" | ||
46 | #include "tools.h" | ||
47 | #include "lanes.h" | 36 | #include "lanes.h" |
37 | #include "tools.h" | ||
38 | #include "universe.h" | ||
48 | 39 | ||
49 | // ################################################################################################ | 40 | // ################################################################################################ |
50 | 41 | ||
@@ -58,7 +49,7 @@ THE SOFTWARE. | |||
58 | // | 49 | // |
59 | // Upvalues: [1]: original 'require' function | 50 | // Upvalues: [1]: original 'require' function |
60 | // | 51 | // |
61 | static int luaG_new_require( lua_State* L) | 52 | [[nodiscard]] static int luaG_new_require(lua_State* L) |
62 | { | 53 | { |
63 | int rc; | 54 | int rc; |
64 | int const args = lua_gettop( L); // args | 55 | int const args = lua_gettop( L); // args |
@@ -72,62 +63,65 @@ static int luaG_new_require( lua_State* L) | |||
72 | 63 | ||
73 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would | 64 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would |
74 | // leave us locked, blocking any future 'require' calls from other lanes. | 65 | // leave us locked, blocking any future 'require' calls from other lanes. |
75 | 66 | ||
76 | MUTEX_LOCK( &U->require_cs); | 67 | U->require_cs.lock(); |
77 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET | 68 | // starting with Lua 5.4, require may return a second optional value, so we need LUA_MULTRET |
78 | rc = lua_pcall( L, args, LUA_MULTRET, 0 /*errfunc*/ ); // err|result(s) | 69 | rc = lua_pcall( L, args, LUA_MULTRET, 0 /*errfunc*/ ); // err|result(s) |
79 | MUTEX_UNLOCK( &U->require_cs); | 70 | U->require_cs.unlock(); |
80 | 71 | ||
81 | // the required module (or an error message) is left on the stack as returned value by original require function | 72 | // the required module (or an error message) is left on the stack as returned value by original require function |
82 | 73 | ||
83 | if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? | 74 | if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? |
84 | { | 75 | { |
85 | return lua_error( L); | 76 | raise_lua_error(L); |
86 | } | 77 | } |
87 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 | 78 | // should be 1 for Lua <= 5.3, 1 or 2 starting with Lua 5.4 |
88 | return lua_gettop(L); // result(s) | 79 | return lua_gettop(L); // result(s) |
89 | } | 80 | } |
90 | 81 | ||
82 | // ################################################################################################# | ||
83 | |||
91 | /* | 84 | /* |
92 | * Serialize calls to 'require', if it exists | 85 | * Serialize calls to 'require', if it exists |
93 | */ | 86 | */ |
94 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | 87 | void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) |
95 | { | 88 | { |
96 | STACK_GROW( L, 1); | 89 | STACK_GROW(L, 1); |
97 | STACK_CHECK( L, 0); | 90 | STACK_CHECK_START_REL(L, 0); |
98 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); | 91 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); |
99 | 92 | ||
100 | // Check 'require' is there and not already wrapped; if not, do nothing | 93 | // Check 'require' is there and not already wrapped; if not, do nothing |
101 | // | 94 | // |
102 | lua_getglobal( L, "require"); | 95 | lua_getglobal(L, "require"); |
103 | if( lua_isfunction( L, -1) && lua_tocfunction( L, -1) != luaG_new_require) | 96 | if (lua_isfunction(L, -1) && lua_tocfunction(L, -1) != luaG_new_require) |
104 | { | 97 | { |
105 | // [-1]: original 'require' function | 98 | // [-1]: original 'require' function |
106 | lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/); | 99 | lua_pushcclosure(L, luaG_new_require, 1 /*upvalues*/); |
107 | lua_setglobal( L, "require"); | 100 | lua_setglobal(L, "require"); |
108 | } | 101 | } |
109 | else | 102 | else |
110 | { | 103 | { |
111 | // [-1]: nil | 104 | // [-1]: nil |
112 | lua_pop( L, 1); | 105 | lua_pop(L, 1); |
113 | } | 106 | } |
114 | 107 | ||
115 | STACK_END( L, 0); | 108 | STACK_CHECK(L, 0); |
116 | } | 109 | } |
117 | 110 | ||
118 | // ################################################################################################ | 111 | // ################################################################################################ |
119 | 112 | ||
120 | /*---=== luaG_newstate ===---*/ | 113 | /*---=== luaG_newstate ===---*/ |
121 | 114 | ||
122 | static int require_lanes_core( lua_State* L) | 115 | [[nodiscard]] static int require_lanes_core(lua_State* L) |
123 | { | 116 | { |
124 | // leaves a copy of 'lanes.core' module table on the stack | 117 | // leaves a copy of 'lanes.core' module table on the stack |
125 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); | 118 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); |
126 | return 1; | 119 | return 1; |
127 | } | 120 | } |
128 | 121 | ||
122 | // ################################################################################################# | ||
129 | 123 | ||
130 | static const luaL_Reg libs[] = | 124 | static luaL_Reg const libs[] = |
131 | { | 125 | { |
132 | { LUA_LOADLIBNAME, luaopen_package}, | 126 | { LUA_LOADLIBNAME, luaopen_package}, |
133 | { LUA_TABLIBNAME, luaopen_table}, | 127 | { LUA_TABLIBNAME, luaopen_table}, |
@@ -146,7 +140,7 @@ static const luaL_Reg libs[] = | |||
146 | #endif | 140 | #endif |
147 | { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! | 141 | { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! |
148 | #else // LUA_VERSION_NUM | 142 | #else // LUA_VERSION_NUM |
149 | { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package | 143 | { LUA_COLIBNAME, nullptr }, // Lua 5.1: part of base package |
150 | #endif // LUA_VERSION_NUM | 144 | #endif // LUA_VERSION_NUM |
151 | { LUA_DBLIBNAME, luaopen_debug}, | 145 | { LUA_DBLIBNAME, luaopen_debug}, |
152 | #if LUAJIT_FLAVOR() != 0 // building against LuaJIT headers, add some LuaJIT-specific libs | 146 | #if LUAJIT_FLAVOR() != 0 // building against LuaJIT headers, add some LuaJIT-specific libs |
@@ -156,14 +150,16 @@ static const luaL_Reg libs[] = | |||
156 | { LUA_FFILIBNAME, luaopen_ffi}, | 150 | { LUA_FFILIBNAME, luaopen_ffi}, |
157 | #endif // LUAJIT_FLAVOR() | 151 | #endif // LUAJIT_FLAVOR() |
158 | 152 | ||
159 | { LUA_DBLIBNAME, luaopen_debug}, | 153 | { LUA_DBLIBNAME, luaopen_debug}, |
160 | { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) | 154 | { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) |
161 | // | 155 | // |
162 | { "base", NULL}, // ignore "base" (already acquired it) | 156 | { "base", nullptr }, // ignore "base" (already acquired it) |
163 | { NULL, NULL } | 157 | { nullptr, nullptr } |
164 | }; | 158 | }; |
165 | 159 | ||
166 | static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char const* name_, size_t len_) | 160 | // ################################################################################################# |
161 | |||
162 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, char const* name_, size_t len_) | ||
167 | { | 163 | { |
168 | int i; | 164 | int i; |
169 | for( i = 0; libs[i].name; ++ i) | 165 | for( i = 0; libs[i].name; ++ i) |
@@ -172,70 +168,73 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con | |||
172 | { | 168 | { |
173 | lua_CFunction libfunc = libs[i].func; | 169 | lua_CFunction libfunc = libs[i].func; |
174 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ | 170 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ |
175 | if( libfunc != NULL) | 171 | if (libfunc != nullptr) |
176 | { | 172 | { |
177 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" | 173 | bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" |
178 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); | 174 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); |
179 | STACK_CHECK( L, 0); | 175 | STACK_CHECK_START_REL(L, 0); |
180 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 176 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
181 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 177 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
182 | // lanes.core doesn't declare a global, so scan it here and now | 178 | // lanes.core doesn't declare a global, so scan it here and now |
183 | if( isLanesCore == TRUE) | 179 | if( isLanesCore == true) |
184 | { | 180 | { |
185 | populate_func_lookup_table( L, -1, name_); | 181 | populate_func_lookup_table( L, -1, name_); |
186 | } | 182 | } |
187 | lua_pop( L, 1); | 183 | lua_pop( L, 1); |
188 | STACK_END( L, 0); | 184 | STACK_CHECK( L, 0); |
189 | } | 185 | } |
190 | break; | 186 | break; |
191 | } | 187 | } |
192 | } | 188 | } |
193 | } | 189 | } |
194 | 190 | ||
191 | // ################################################################################################# | ||
195 | 192 | ||
196 | // just like lua_xmove, args are (from, to) | 193 | // just like lua_xmove, args are (from, to) |
197 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | 194 | static void copy_one_time_settings(Universe* U, Source L, Dest L2) |
198 | { | 195 | { |
199 | STACK_GROW( L, 2); | 196 | STACK_GROW(L, 2); |
200 | STACK_CHECK( L, 0); | 197 | STACK_CHECK_START_REL(L, 0); |
201 | STACK_CHECK( L2, 0); | 198 | STACK_CHECK_START_REL(L2, 0); |
202 | 199 | ||
203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 200 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 201 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
205 | 202 | ||
206 | REGISTRY_GET( L, CONFIG_REGKEY); // config | 203 | CONFIG_REGKEY.pushValue(L); // config |
207 | // copy settings from from source to destination registry | 204 | // copy settings from from source to destination registry |
208 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) != eICR_Success) // // config | 205 | if (luaG_inter_move(U, L, L2, 1, LookupMode::LaneBody) != InterCopyResult::Success) // // config |
209 | { | 206 | { |
210 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); | 207 | luaL_error( L, "failed to copy settings when loading lanes.core"); // doesn't return |
211 | } | 208 | } |
212 | // set L2:_R[CONFIG_REGKEY] = settings | 209 | // set L2:_R[CONFIG_REGKEY] = settings |
213 | REGISTRY_SET( L2, CONFIG_REGKEY, lua_insert( L2, -2)); // | 210 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config |
214 | STACK_END( L2, 0); | 211 | STACK_CHECK(L2, 0); |
215 | STACK_END( L, 0); | 212 | STACK_CHECK(L, 0); |
216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 213 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
217 | } | 214 | } |
218 | 215 | ||
216 | // ################################################################################################# | ||
217 | |||
219 | void initialize_on_state_create( Universe* U, lua_State* L) | 218 | void initialize_on_state_create( Universe* U, lua_State* L) |
220 | { | 219 | { |
221 | STACK_CHECK( L, 0); | 220 | STACK_CHECK_START_REL(L, 1); // settings |
222 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 221 | lua_getfield(L, -1, "on_state_create"); // settings on_state_create|nil |
223 | if( !lua_isnil( L, -1)) | 222 | if( !lua_isnil(L, -1)) |
224 | { | 223 | { |
225 | // store C function pointer in an internal variable | 224 | // store C function pointer in an internal variable |
226 | U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create | 225 | U->on_state_create_func = lua_tocfunction(L, -1); // settings on_state_create |
227 | if( U->on_state_create_func != NULL) | 226 | if (U->on_state_create_func != nullptr) |
228 | { | 227 | { |
229 | // make sure the function doesn't have upvalues | 228 | // make sure the function doesn't have upvalues |
230 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? | 229 | char const* upname = lua_getupvalue(L, -1, 1); // settings on_state_create upval? |
231 | if( upname != NULL) // should be "" for C functions with upvalues if any | 230 | if (upname != nullptr) // should be "" for C functions with upvalues if any |
232 | { | 231 | { |
233 | (void) luaL_error( L, "on_state_create shouldn't have upvalues"); | 232 | (void) luaL_error(L, "on_state_create shouldn't have upvalues"); |
234 | } | 233 | } |
235 | // remove this C function from the config table so that it doesn't cause problems | 234 | // remove this C function from the config table so that it doesn't cause problems |
236 | // when we transfer the config table in newly created Lua states | 235 | // when we transfer the config table in newly created Lua states |
237 | lua_pushnil( L); // settings on_state_create nil | 236 | lua_pushnil(L); // settings on_state_create nil |
238 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create | 237 | lua_setfield(L, -3, "on_state_create"); // settings on_state_create |
239 | } | 238 | } |
240 | else | 239 | else |
241 | { | 240 | { |
@@ -243,113 +242,120 @@ void initialize_on_state_create( Universe* U, lua_State* L) | |||
243 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; | 242 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; |
244 | } | 243 | } |
245 | } | 244 | } |
246 | lua_pop( L, 1); // settings | 245 | lua_pop(L, 1); // settings |
247 | STACK_END( L, 0); | 246 | STACK_CHECK(L, 1); |
248 | } | 247 | } |
249 | 248 | ||
250 | lua_State* create_state( Universe* U, lua_State* from_) | 249 | // ################################################################################################# |
250 | |||
251 | lua_State* create_state(Universe* U, lua_State* from_) | ||
251 | { | 252 | { |
252 | lua_State* L; | 253 | lua_State* L; |
253 | #if LUAJIT_FLAVOR() == 64 | 254 | #if LUAJIT_FLAVOR() == 64 |
254 | // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... | 255 | // for some reason, LuaJIT 64 bits does not support creating a state with lua_newstate... |
255 | L = luaL_newstate(); | 256 | L = luaL_newstate(); |
256 | #else // LUAJIT_FLAVOR() == 64 | 257 | #else // LUAJIT_FLAVOR() == 64 |
257 | if( U->provide_allocator != NULL) // we have a function we can call to obtain an allocator | 258 | if (U->provide_allocator != nullptr) // we have a function we can call to obtain an allocator |
258 | { | 259 | { |
259 | lua_pushcclosure( from_, U->provide_allocator, 0); | 260 | lua_pushcclosure( from_, U->provide_allocator, 0); |
260 | lua_call( from_, 0, 1); | 261 | lua_call( from_, 0, 1); |
261 | { | 262 | { |
262 | AllocatorDefinition* const def = lua_touserdata( from_, -1); | 263 | AllocatorDefinition* const def{ lua_tofulluserdata<AllocatorDefinition>(from_, -1) }; |
263 | L = lua_newstate( def->allocF, def->allocUD); | 264 | L = lua_newstate( def->m_allocF, def->m_allocUD); |
264 | } | 265 | } |
265 | lua_pop( from_, 1); | 266 | lua_pop( from_, 1); |
266 | } | 267 | } |
267 | else | 268 | else |
268 | { | 269 | { |
269 | // reuse the allocator provided when the master state was created | 270 | // reuse the allocator provided when the master state was created |
270 | L = lua_newstate( U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD); | 271 | L = lua_newstate(U->protected_allocator.m_allocF, U->protected_allocator.m_allocUD); |
271 | } | 272 | } |
272 | #endif // LUAJIT_FLAVOR() == 64 | 273 | #endif // LUAJIT_FLAVOR() == 64 |
273 | 274 | ||
274 | if( L == NULL) | 275 | if (L == nullptr) |
275 | { | 276 | { |
276 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | 277 | luaL_error(from_, "luaG_newstate() failed while creating state; out of memory"); // doesn't return |
277 | } | 278 | } |
278 | return L; | 279 | return L; |
279 | } | 280 | } |
280 | 281 | ||
281 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) | 282 | // ################################################################################################# |
283 | |||
284 | void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) | ||
282 | { | 285 | { |
283 | if( U->on_state_create_func != NULL) | 286 | if (U->on_state_create_func != nullptr) |
284 | { | 287 | { |
285 | STACK_CHECK( L, 0); | 288 | STACK_CHECK_START_REL(L, 0); |
286 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 289 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
287 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) | 290 | if (U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
288 | { | 291 | { |
289 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 292 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
290 | lua_pushcfunction( L, U->on_state_create_func); // on_state_create() | 293 | lua_pushcfunction(L, U->on_state_create_func); // on_state_create() |
291 | } | 294 | } |
292 | else // Lua function located in the config table, copied when we opened "lanes.core" | 295 | else // Lua function located in the config table, copied when we opened "lanes.core" |
293 | { | 296 | { |
294 | if( mode_ != eLM_LaneBody) | 297 | if (mode_ != LookupMode::LaneBody) |
295 | { | 298 | { |
296 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there | 299 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there |
297 | // this doesn't count as an error though | 300 | // this doesn't count as an error though |
301 | STACK_CHECK(L, 0); | ||
298 | return; | 302 | return; |
299 | } | 303 | } |
300 | REGISTRY_GET( L, CONFIG_REGKEY); // {} | 304 | CONFIG_REGKEY.pushValue(L); // {} |
301 | STACK_MID( L, 1); | 305 | STACK_CHECK(L, 1); |
302 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() | 306 | lua_getfield(L, -1, "on_state_create"); // {} on_state_create() |
303 | lua_remove( L, -2); // on_state_create() | 307 | lua_remove(L, -2); // on_state_create() |
304 | } | 308 | } |
305 | STACK_MID( L, 1); | 309 | STACK_CHECK(L, 1); |
306 | // capture error and raise it in caller state | 310 | // capture error and raise it in caller state |
307 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 311 | if (lua_pcall(L, 0, 0, 0) != LUA_OK) |
308 | { | 312 | { |
309 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 313 | luaL_error(from_, "on_state_create failed: \"%s\"", lua_isstring(L, -1) ? lua_tostring(L, -1) : lua_typename(L, lua_type(L, -1))); |
310 | } | 314 | } |
311 | STACK_END( L, 0); | 315 | STACK_CHECK(L, 0); |
312 | } | 316 | } |
313 | } | 317 | } |
314 | 318 | ||
319 | // ################################################################################################# | ||
320 | |||
315 | /* | 321 | /* |
316 | * Like 'luaL_openlibs()' but allows the set of libraries be selected | 322 | * Like 'luaL_openlibs()' but allows the set of libraries be selected |
317 | * | 323 | * |
318 | * NULL no libraries, not even base | 324 | * nullptr no libraries, not even base |
319 | * "" base library only | 325 | * "" base library only |
320 | * "io,string" named libraries | 326 | * "io,string" named libraries |
321 | * "*" all libraries | 327 | * "*" all libraries |
322 | * | 328 | * |
323 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. | 329 | * Base ("unpack", "print" etc.) is always added, unless 'libs' is nullptr. |
324 | * | 330 | * |
325 | * *NOT* called for keeper states! | 331 | * *NOT* called for keeper states! |
326 | * | 332 | * |
327 | */ | 333 | */ |
328 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | 334 | lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) |
329 | { | 335 | { |
330 | lua_State* L = create_state( U, from_); | 336 | Dest const L{ create_state(U, from_) }; |
331 | 337 | ||
332 | STACK_GROW( L, 2); | 338 | STACK_GROW(L, 2); |
333 | STACK_CHECK_ABS( L, 0); | 339 | STACK_CHECK_START_ABS(L, 0); |
334 | 340 | ||
335 | // copy the universe as a light userdata (only the master state holds the full userdata) | 341 | // copy the universe as a light userdata (only the master state holds the full userdata) |
336 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | 342 | // that way, if Lanes is required in this new state, we'll know we are part of this universe |
337 | universe_store( L, U); | 343 | universe_store( L, U); |
338 | STACK_MID( L, 0); | 344 | STACK_CHECK(L, 0); |
339 | 345 | ||
340 | // we'll need this every time we transfer some C function from/to this state | 346 | // we'll need this every time we transfer some C function from/to this state |
341 | REGISTRY_SET( L, LOOKUP_REGKEY, lua_newtable( L)); | 347 | LOOKUP_REGKEY.setValue(L, [](lua_State* L) { lua_newtable(L); }); |
342 | STACK_MID( L, 0); | 348 | STACK_CHECK(L, 0); |
343 | 349 | ||
344 | // neither libs (not even 'base') nor special init func: we are done | 350 | // neither libs (not even 'base') nor special init func: we are done |
345 | if( libs_ == NULL && U->on_state_create_func == NULL) | 351 | if (libs_ == nullptr && U->on_state_create_func == nullptr) |
346 | { | 352 | { |
347 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); | 353 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(nullptr)\n" INDENT_END)); |
348 | return L; | 354 | return L; |
349 | } | 355 | } |
350 | 356 | ||
351 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 357 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
352 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 358 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); |
353 | 359 | ||
354 | // copy settings (for example because it may contain a Lua on_state_create function) | 360 | // copy settings (for example because it may contain a Lua on_state_create function) |
355 | copy_one_time_settings( U, from_, L); | 361 | copy_one_time_settings( U, from_, L); |
@@ -360,7 +366,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
360 | 366 | ||
361 | // Anything causes 'base' to be taken in | 367 | // Anything causes 'base' to be taken in |
362 | // | 368 | // |
363 | if( libs_ != NULL) | 369 | if (libs_ != nullptr) |
364 | { | 370 | { |
365 | // special "*" case (mainly to help with LuaJIT compatibility) | 371 | // special "*" case (mainly to help with LuaJIT compatibility) |
366 | // as we are called from luaopen_lanes_core() already, and that would deadlock | 372 | // as we are called from luaopen_lanes_core() already, and that would deadlock |
@@ -370,7 +376,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
370 | luaL_openlibs( L); | 376 | luaL_openlibs( L); |
371 | // don't forget lanes.core for regular lane states | 377 | // don't forget lanes.core for regular lane states |
372 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); | 378 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); |
373 | libs_ = NULL; // done with libs | 379 | libs_ = nullptr; // done with libs |
374 | } | 380 | } |
375 | else | 381 | else |
376 | { | 382 | { |
@@ -386,7 +392,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
386 | #endif // LUA_VERSION_NUM | 392 | #endif // LUA_VERSION_NUM |
387 | } | 393 | } |
388 | } | 394 | } |
389 | STACK_END( L, 0); | 395 | STACK_CHECK(L, 0); |
390 | 396 | ||
391 | // scan all libraries, open them one by one | 397 | // scan all libraries, open them one by one |
392 | if( libs_) | 398 | if( libs_) |
@@ -412,31 +418,32 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
412 | 418 | ||
413 | // call this after the base libraries are loaded and GC is restarted | 419 | // call this after the base libraries are loaded and GC is restarted |
414 | // will raise an error in from_ in case of problem | 420 | // will raise an error in from_ in case of problem |
415 | call_on_state_create( U, L, from_, eLM_LaneBody); | 421 | call_on_state_create(U, L, from_, LookupMode::LaneBody); |
416 | 422 | ||
417 | STACK_CHECK( L, 0); | 423 | STACK_CHECK(L, 0); |
418 | // after all this, register everything we find in our name<->function database | 424 | // after all this, register everything we find in our name<->function database |
419 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 425 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
420 | populate_func_lookup_table( L, -1, NULL); | 426 | STACK_CHECK(L, 1); |
427 | populate_func_lookup_table(L, -1, nullptr); | ||
421 | 428 | ||
422 | #if 0 && USE_DEBUG_SPEW() | 429 | #if 0 && USE_DEBUG_SPEW() |
423 | // dump the lookup database contents | 430 | // dump the lookup database contents |
424 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 431 | lua_getfield(L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
425 | lua_pushnil( L); // {} nil | 432 | lua_pushnil(L); // {} nil |
426 | while( lua_next( L, -2)) // {} k v | 433 | while (lua_next(L, -2)) // {} k v |
427 | { | 434 | { |
428 | lua_getglobal( L, "print"); // {} k v print | 435 | lua_getglobal(L, "print"); // {} k v print |
429 | lua_pushlstring( L, debugspew_indent, U->debugspew_indent_depth); // {} k v print " " | 436 | lua_pushlstring(L, debugspew_indent, U->debugspew_indent_depth.load(std::memory_order_relaxed)); // {} k v print " " |
430 | lua_pushvalue( L, -4); // {} k v print " " k | 437 | lua_pushvalue(L, -4); // {} k v print " " k |
431 | lua_pushvalue( L, -4); // {} k v print " " k v | 438 | lua_pushvalue(L, -4); // {} k v print " " k v |
432 | lua_call( L, 3, 0); // {} k v | 439 | lua_call(L, 3, 0); // {} k v |
433 | lua_pop( L, 1); // {} k | 440 | lua_pop(L, 1); // {} k |
434 | } | 441 | } |
435 | lua_pop( L, 1); // {} | 442 | lua_pop(L, 1); // {} |
436 | #endif // USE_DEBUG_SPEW() | 443 | #endif // USE_DEBUG_SPEW() |
437 | 444 | ||
438 | lua_pop( L, 1); | 445 | lua_pop(L, 1); |
439 | STACK_END( L, 0); | 446 | STACK_CHECK(L, 0); |
440 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 447 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); |
441 | return L; | 448 | return L; |
442 | } | 449 | } |