diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-16 18:06:02 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-16 18:06:02 +0200 |
commit | bbb4f99918d00308b52af3289c29624bfeb0066b (patch) | |
tree | aebfba19ae4bb2bddc2beaa18f80a64d254b4ae6 /src | |
parent | d6f5a7795360e3c2a6fc2d424904b6daa1f2accd (diff) | |
download | lanes-bbb4f99918d00308b52af3289c29624bfeb0066b.tar.gz lanes-bbb4f99918d00308b52af3289c29624bfeb0066b.tar.bz2 lanes-bbb4f99918d00308b52af3289c29624bfeb0066b.zip |
some dead code elimination and other trifles
Diffstat (limited to 'src')
-rw-r--r-- | src/cancel.cpp | 38 | ||||
-rw-r--r-- | src/cancel.h | 12 | ||||
-rw-r--r-- | src/compat.cpp | 39 | ||||
-rw-r--r-- | src/deep.cpp | 56 | ||||
-rw-r--r-- | src/deep.h | 2 | ||||
-rw-r--r-- | src/keeper.cpp | 60 | ||||
-rw-r--r-- | src/lanes.cpp | 329 | ||||
-rw-r--r-- | src/lanes_private.h | 2 | ||||
-rw-r--r-- | src/macros_and_utils.h | 4 | ||||
-rw-r--r-- | src/state.cpp | 36 | ||||
-rw-r--r-- | src/state.h | 4 | ||||
-rw-r--r-- | src/threading.cpp | 20 | ||||
-rw-r--r-- | src/threading.h | 18 | ||||
-rw-r--r-- | src/tools.cpp | 669 | ||||
-rw-r--r-- | src/tools.h | 48 | ||||
-rw-r--r-- | src/uniquekey.h | 2 | ||||
-rw-r--r-- | src/universe.cpp | 10 | ||||
-rw-r--r-- | src/universe.h | 13 |
18 files changed, 634 insertions, 728 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index b3e52b6..fe1f3e6 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -39,8 +39,8 @@ THE SOFTWARE. | |||
39 | #include "threading.h" | 39 | #include "threading.h" |
40 | #include "tools.h" | 40 | #include "tools.h" |
41 | 41 | ||
42 | // ################################################################################################ | 42 | // ################################################################################################# |
43 | // ################################################################################################ | 43 | // ################################################################################################# |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Check if the thread in question ('L') has been signalled for cancel. | 46 | * Check if the thread in question ('L') has been signalled for cancel. |
@@ -58,7 +58,7 @@ THE SOFTWARE. | |||
58 | return lane ? lane->cancel_request : CancelRequest::None; | 58 | return lane ? lane->cancel_request : CancelRequest::None; |
59 | } | 59 | } |
60 | 60 | ||
61 | // ################################################################################################ | 61 | // ################################################################################################# |
62 | 62 | ||
63 | //--- | 63 | //--- |
64 | // bool = cancel_test() | 64 | // bool = cancel_test() |
@@ -66,15 +66,15 @@ THE SOFTWARE. | |||
66 | // Available inside the global namespace of lanes | 66 | // Available inside the global namespace of lanes |
67 | // returns a boolean saying if a cancel request is pending | 67 | // returns a boolean saying if a cancel request is pending |
68 | // | 68 | // |
69 | LUAG_FUNC( cancel_test) | 69 | LUAG_FUNC(cancel_test) |
70 | { | 70 | { |
71 | CancelRequest test{ cancel_test(L) }; | 71 | CancelRequest test{ cancel_test(L) }; |
72 | lua_pushboolean(L, test != CancelRequest::None); | 72 | lua_pushboolean(L, test != CancelRequest::None); |
73 | return 1; | 73 | return 1; |
74 | } | 74 | } |
75 | 75 | ||
76 | // ################################################################################################ | 76 | // ################################################################################################# |
77 | // ################################################################################################ | 77 | // ################################################################################################# |
78 | 78 | ||
79 | [[nodiscard]] static void cancel_hook(lua_State* L, [[maybe_unused]] lua_Debug* ar) | 79 | [[nodiscard]] static void cancel_hook(lua_State* L, [[maybe_unused]] lua_Debug* ar) |
80 | { | 80 | { |
@@ -86,8 +86,8 @@ LUAG_FUNC( cancel_test) | |||
86 | } | 86 | } |
87 | } | 87 | } |
88 | 88 | ||
89 | // ################################################################################################ | 89 | // ################################################################################################# |
90 | // ################################################################################################ | 90 | // ################################################################################################# |
91 | 91 | ||
92 | //--- | 92 | //--- |
93 | // = thread_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] ) | 93 | // = thread_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] ) |
@@ -106,7 +106,7 @@ LUAG_FUNC( cancel_test) | |||
106 | // false if the cancellation timed out, or a kill was needed. | 106 | // false if the cancellation timed out, or a kill was needed. |
107 | // | 107 | // |
108 | 108 | ||
109 | // ################################################################################################ | 109 | // ################################################################################################# |
110 | 110 | ||
111 | [[nodiscard]] static CancelResult thread_cancel_soft(Lane* lane_, lua_Duration duration_, bool wake_lane_) | 111 | [[nodiscard]] static CancelResult thread_cancel_soft(Lane* lane_, lua_Duration duration_, bool wake_lane_) |
112 | { | 112 | { |
@@ -124,7 +124,7 @@ LUAG_FUNC( cancel_test) | |||
124 | return lane_->waitForCompletion(duration_) ? CancelResult::Cancelled : CancelResult::Timeout; | 124 | return lane_->waitForCompletion(duration_) ? CancelResult::Cancelled : CancelResult::Timeout; |
125 | } | 125 | } |
126 | 126 | ||
127 | // ################################################################################################ | 127 | // ################################################################################################# |
128 | 128 | ||
129 | [[nodiscard]] static CancelResult thread_cancel_hard(Lane* lane_, lua_Duration duration_, bool wake_lane_) | 129 | [[nodiscard]] static CancelResult thread_cancel_hard(Lane* lane_, lua_Duration duration_, bool wake_lane_) |
130 | { | 130 | { |
@@ -143,7 +143,7 @@ LUAG_FUNC( cancel_test) | |||
143 | return result; | 143 | return result; |
144 | } | 144 | } |
145 | 145 | ||
146 | // ################################################################################################ | 146 | // ################################################################################################# |
147 | 147 | ||
148 | CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hook_count_, lua_Duration duration_, bool wake_lane_) | 148 | CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hook_count_, lua_Duration duration_, bool wake_lane_) |
149 | { | 149 | { |
@@ -169,8 +169,8 @@ CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hook_count_, lua_Durat | |||
169 | return thread_cancel_hard(lane_, duration_, wake_lane_); | 169 | return thread_cancel_hard(lane_, duration_, wake_lane_); |
170 | } | 170 | } |
171 | 171 | ||
172 | // ################################################################################################ | 172 | // ################################################################################################# |
173 | // ################################################################################################ | 173 | // ################################################################################################# |
174 | 174 | ||
175 | CancelOp which_cancel_op(char const* op_string_) | 175 | CancelOp which_cancel_op(char const* op_string_) |
176 | { | 176 | { |
@@ -202,7 +202,7 @@ CancelOp which_cancel_op(char const* op_string_) | |||
202 | return op; | 202 | return op; |
203 | } | 203 | } |
204 | 204 | ||
205 | // ################################################################################################ | 205 | // ################################################################################################# |
206 | 206 | ||
207 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L, int idx_) | 207 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L, int idx_) |
208 | { | 208 | { |
@@ -220,12 +220,12 @@ CancelOp which_cancel_op(char const* op_string_) | |||
220 | return CancelOp::Hard; | 220 | return CancelOp::Hard; |
221 | } | 221 | } |
222 | 222 | ||
223 | // ################################################################################################ | 223 | // ################################################################################################# |
224 | 224 | ||
225 | // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, wake_lindas]) | 225 | // bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, wake_lindas]) |
226 | LUAG_FUNC(thread_cancel) | 226 | LUAG_FUNC(thread_cancel) |
227 | { | 227 | { |
228 | Lane* const lane{ lua_toLane(L, 1) }; | 228 | Lane* const lane{ ToLane(L, 1) }; |
229 | CancelOp const op{ which_cancel_op(L, 2) }; // this removes the op string from the stack | 229 | CancelOp const op{ which_cancel_op(L, 2) }; // this removes the op string from the stack |
230 | 230 | ||
231 | int hook_count{ 0 }; | 231 | int hook_count{ 0 }; |
@@ -235,7 +235,7 @@ LUAG_FUNC(thread_cancel) | |||
235 | lua_remove(L, 2); // argument is processed, remove it | 235 | lua_remove(L, 2); // argument is processed, remove it |
236 | if (hook_count < 1) | 236 | if (hook_count < 1) |
237 | { | 237 | { |
238 | return luaL_error(L, "hook count cannot be < 1"); | 238 | return luaL_error(L, "hook count cannot be < 1"); // doesn't return |
239 | } | 239 | } |
240 | } | 240 | } |
241 | 241 | ||
@@ -246,7 +246,7 @@ LUAG_FUNC(thread_cancel) | |||
246 | lua_remove(L, 2); // argument is processed, remove it | 246 | lua_remove(L, 2); // argument is processed, remove it |
247 | if (wait_timeout.count() < 0.0) | 247 | if (wait_timeout.count() < 0.0) |
248 | { | 248 | { |
249 | return luaL_error(L, "cancel timeout cannot be < 0"); | 249 | return luaL_error(L, "cancel timeout cannot be < 0"); // doesn't return |
250 | } | 250 | } |
251 | } | 251 | } |
252 | // we wake by default in "hard" mode (remember that hook is hard too), but this can be turned off if desired | 252 | // we wake by default in "hard" mode (remember that hook is hard too), but this can be turned off if desired |
@@ -255,7 +255,7 @@ LUAG_FUNC(thread_cancel) | |||
255 | { | 255 | { |
256 | if (!lua_isboolean(L, 2)) | 256 | if (!lua_isboolean(L, 2)) |
257 | { | 257 | { |
258 | return luaL_error(L, "wake_lindas parameter is not a boolean"); | 258 | return luaL_error(L, "wake_lindas parameter is not a boolean"); // doesn't return |
259 | } | 259 | } |
260 | wake_lane = lua_toboolean(L, 2); | 260 | wake_lane = lua_toboolean(L, 2); |
261 | lua_remove(L, 2); // argument is processed, remove it | 261 | lua_remove(L, 2); // argument is processed, remove it |
diff --git a/src/cancel.h b/src/cancel.h index 10a9804..8cff1c9 100644 --- a/src/cancel.h +++ b/src/cancel.h | |||
@@ -10,12 +10,10 @@ extern "C" { | |||
10 | } | 10 | } |
11 | #endif // __cplusplus | 11 | #endif // __cplusplus |
12 | 12 | ||
13 | #include "uniquekey.h" | ||
14 | #include "macros_and_utils.h" | 13 | #include "macros_and_utils.h" |
14 | #include "uniquekey.h" | ||
15 | 15 | ||
16 | #include <chrono> | 16 | // ################################################################################################# |
17 | |||
18 | // ################################################################################################ | ||
19 | 17 | ||
20 | class Lane; // forward | 18 | class Lane; // forward |
21 | 19 | ||
@@ -59,10 +57,10 @@ static constexpr UniqueKey CANCEL_ERROR{ 0xe97d41626cc97577ull, "lanes.cancel_er | |||
59 | raise_lua_error(L); // doesn't return | 57 | raise_lua_error(L); // doesn't return |
60 | } | 58 | } |
61 | 59 | ||
62 | // ################################################################################################ | 60 | // ################################################################################################# |
63 | // ################################################################################################ | 61 | // ################################################################################################# |
64 | 62 | ||
65 | LUAG_FUNC(cancel_test); | 63 | LUAG_FUNC(cancel_test); |
66 | LUAG_FUNC(thread_cancel); | 64 | LUAG_FUNC(thread_cancel); |
67 | 65 | ||
68 | // ################################################################################################ | 66 | // ################################################################################################# |
diff --git a/src/compat.cpp b/src/compat.cpp index 73d0f6b..9f652a7 100644 --- a/src/compat.cpp +++ b/src/compat.cpp | |||
@@ -1,20 +1,17 @@ | |||
1 | /* | 1 | // ################################################################################################# |
2 | * ############################################################################################### | 2 | // ###################################### Lua 5.1 / 5.2 / 5.3 ###################################### |
3 | * ####################################### Lua 5.1/5.2/5.3 ####################################### | 3 | // ################################################################################################# |
4 | * ############################################################################################### | 4 | |
5 | */ | ||
6 | #include "compat.h" | 5 | #include "compat.h" |
7 | #include "macros_and_utils.h" | 6 | #include "macros_and_utils.h" |
8 | 7 | ||
9 | /* | 8 | // ################################################################################################# |
10 | ** Copied from Lua 5.2 loadlib.c | 9 | // ################################################################################################# |
11 | */ | ||
12 | // ################################################################################################ | ||
13 | // ################################################################################################ | ||
14 | #if LUA_VERSION_NUM == 501 | 10 | #if LUA_VERSION_NUM == 501 |
15 | // ################################################################################################ | 11 | // ################################################################################################# |
16 | // ################################################################################################ | 12 | // ################################################################################################# |
17 | 13 | ||
14 | // Copied from Lua 5.2 loadlib.c | ||
18 | static int luaL_getsubtable(lua_State* L, int idx, const char* fname) | 15 | static int luaL_getsubtable(lua_State* L, int idx, const char* fname) |
19 | { | 16 | { |
20 | lua_getfield(L, idx, fname); | 17 | lua_getfield(L, idx, fname); |
@@ -31,7 +28,7 @@ static int luaL_getsubtable(lua_State* L, int idx, const char* fname) | |||
31 | } | 28 | } |
32 | } | 29 | } |
33 | 30 | ||
34 | // ################################################################################################ | 31 | // ################################################################################################# |
35 | 32 | ||
36 | void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) | 33 | void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) |
37 | { | 34 | { |
@@ -50,11 +47,11 @@ void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int g | |||
50 | } | 47 | } |
51 | #endif // LUA_VERSION_NUM | 48 | #endif // LUA_VERSION_NUM |
52 | 49 | ||
53 | // ################################################################################################ | 50 | // ################################################################################################# |
54 | // ################################################################################################ | 51 | // ################################################################################################# |
55 | #if LUA_VERSION_NUM < 504 | 52 | #if LUA_VERSION_NUM < 504 |
56 | // ################################################################################################ | 53 | // ################################################################################################# |
57 | // ################################################################################################ | 54 | // ################################################################################################# |
58 | 55 | ||
59 | void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue) | 56 | void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue) |
60 | { | 57 | { |
@@ -62,13 +59,13 @@ void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue) | |||
62 | return lua_newuserdata(L, sz); | 59 | return lua_newuserdata(L, sz); |
63 | } | 60 | } |
64 | 61 | ||
65 | // ################################################################################################ | 62 | // ################################################################################################# |
66 | 63 | ||
67 | // push on stack uservalue #n of full userdata at idx | 64 | // push on stack uservalue #n of full userdata at idx |
68 | int lua_getiuservalue(lua_State* L, int idx, int n) | 65 | int lua_getiuservalue(lua_State* L, int idx, int n) |
69 | { | 66 | { |
70 | // full userdata can have only 1 uservalue before 5.4 | 67 | // full userdata can have only 1 uservalue before 5.4 |
71 | if( n > 1) | 68 | if (n > 1) |
72 | { | 69 | { |
73 | lua_pushnil(L); | 70 | lua_pushnil(L); |
74 | return LUA_TNONE; | 71 | return LUA_TNONE; |
@@ -91,13 +88,13 @@ int lua_getiuservalue(lua_State* L, int idx, int n) | |||
91 | return lua_type(L, -1); | 88 | return lua_type(L, -1); |
92 | } | 89 | } |
93 | 90 | ||
94 | // ################################################################################################ | 91 | // ################################################################################################# |
95 | 92 | ||
96 | // Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index. | 93 | // Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index. |
97 | // Returns 0 if the userdata does not have that value. | 94 | // Returns 0 if the userdata does not have that value. |
98 | int lua_setiuservalue(lua_State* L, int idx, int n) | 95 | int lua_setiuservalue(lua_State* L, int idx, int n) |
99 | { | 96 | { |
100 | if( n > 1 | 97 | if (n > 1 |
101 | #if LUA_VERSION_NUM == 501 | 98 | #if LUA_VERSION_NUM == 501 |
102 | || lua_type(L, -1) != LUA_TTABLE | 99 | || lua_type(L, -1) != LUA_TTABLE |
103 | #endif | 100 | #endif |
diff --git a/src/deep.cpp b/src/deep.cpp index 3eb38dc..3326f98 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -81,7 +81,7 @@ static void set_deep_lookup(lua_State* L) | |||
81 | STACK_CHECK( L, 0); | 81 | STACK_CHECK( L, 0); |
82 | } | 82 | } |
83 | 83 | ||
84 | // ################################################################################################ | 84 | // ################################################################################################# |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * Pops the key (metatable or factory) off the stack, and replaces with the | 87 | * Pops the key (metatable or factory) off the stack, and replaces with the |
@@ -92,7 +92,7 @@ static void get_deep_lookup(lua_State* L) | |||
92 | STACK_GROW( L, 1); | 92 | STACK_GROW( L, 1); |
93 | STACK_CHECK_START_REL(L, 1); // a | 93 | STACK_CHECK_START_REL(L, 1); // a |
94 | DEEP_LOOKUP_KEY.pushValue(L); // a {} | 94 | DEEP_LOOKUP_KEY.pushValue(L); // a {} |
95 | if( !lua_isnil( L, -1)) | 95 | if (!lua_isnil( L, -1)) |
96 | { | 96 | { |
97 | lua_insert( L, -2); // {} a | 97 | lua_insert( L, -2); // {} a |
98 | lua_rawget( L, -2); // {} b | 98 | lua_rawget( L, -2); // {} b |
@@ -101,7 +101,7 @@ static void get_deep_lookup(lua_State* L) | |||
101 | STACK_CHECK( L, 1); | 101 | STACK_CHECK( L, 1); |
102 | } | 102 | } |
103 | 103 | ||
104 | // ################################################################################################ | 104 | // ################################################################################################# |
105 | 105 | ||
106 | /* | 106 | /* |
107 | * Return the registered factory for 'index' (deep userdata proxy), | 107 | * Return the registered factory for 'index' (deep userdata proxy), |
@@ -124,7 +124,7 @@ static void get_deep_lookup(lua_State* L) | |||
124 | STACK_GROW( L, 1); | 124 | STACK_GROW( L, 1); |
125 | STACK_CHECK_START_REL(L, 0); | 125 | STACK_CHECK_START_REL(L, 0); |
126 | 126 | ||
127 | if( !lua_getmetatable( L, index)) // deep ... metatable? | 127 | if (!lua_getmetatable( L, index)) // deep ... metatable? |
128 | { | 128 | { |
129 | return nullptr; // no metatable: can't be a deep userdata object! | 129 | return nullptr; // no metatable: can't be a deep userdata object! |
130 | } | 130 | } |
@@ -139,7 +139,7 @@ static void get_deep_lookup(lua_State* L) | |||
139 | } | 139 | } |
140 | } | 140 | } |
141 | 141 | ||
142 | // ################################################################################################ | 142 | // ################################################################################################# |
143 | 143 | ||
144 | void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) | 144 | void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) |
145 | { | 145 | { |
@@ -148,7 +148,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) | |||
148 | STACK_CHECK(L, 0); | 148 | STACK_CHECK(L, 0); |
149 | } | 149 | } |
150 | 150 | ||
151 | // ################################################################################################ | 151 | // ################################################################################################# |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * void= mt.__gc( proxy_ud ) | 154 | * void= mt.__gc( proxy_ud ) |
@@ -169,7 +169,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) | |||
169 | { | 169 | { |
170 | // retrieve wrapped __gc | 170 | // retrieve wrapped __gc |
171 | lua_pushvalue( L, lua_upvalueindex( 1)); // self __gc? | 171 | lua_pushvalue( L, lua_upvalueindex( 1)); // self __gc? |
172 | if( !lua_isnil( L, -1)) | 172 | if (!lua_isnil( L, -1)) |
173 | { | 173 | { |
174 | lua_insert( L, -2); // __gc self | 174 | lua_insert( L, -2); // __gc self |
175 | lua_call( L, 1, 0); // | 175 | lua_call( L, 1, 0); // |
@@ -180,7 +180,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) | |||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
183 | // ################################################################################################ | 183 | // ################################################################################################# |
184 | 184 | ||
185 | /* | 185 | /* |
186 | * Push a proxy userdata on the stack. | 186 | * Push a proxy userdata on the stack. |
@@ -194,25 +194,25 @@ void DeepFactory::DeleteDeepObject(lua_State* L, DeepPrelude* o_) | |||
194 | char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, LookupMode mode_) | 194 | char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, LookupMode mode_) |
195 | { | 195 | { |
196 | // Check if a proxy already exists | 196 | // Check if a proxy already exists |
197 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC | 197 | push_registry_subtable_mode(L, DEEP_PROXY_CACHE_KEY, "v"); // DPC |
198 | lua_pushlightuserdata( L, prelude); // DPC deep | 198 | lua_pushlightuserdata(L, prelude); // DPC deep |
199 | lua_rawget( L, -2); // DPC proxy | 199 | lua_rawget(L, -2); // DPC proxy |
200 | if ( !lua_isnil( L, -1)) | 200 | if (!lua_isnil(L, -1)) |
201 | { | 201 | { |
202 | lua_remove( L, -2); // proxy | 202 | lua_remove(L, -2); // proxy |
203 | return nullptr; | 203 | return nullptr; |
204 | } | 204 | } |
205 | else | 205 | else |
206 | { | 206 | { |
207 | lua_pop( L, 1); // DPC | 207 | lua_pop(L, 1); // DPC |
208 | } | 208 | } |
209 | 209 | ||
210 | STACK_GROW( L, 7); | 210 | STACK_GROW(L, 7); |
211 | STACK_CHECK_START_REL(L, 0); | 211 | STACK_CHECK_START_REL(L, 0); |
212 | 212 | ||
213 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 213 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
214 | DeepPrelude** proxy = (DeepPrelude**) lua_newuserdatauv(L, sizeof(DeepPrelude*), nuv_); // DPC proxy | 214 | DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L, nuv_) }; // DPC proxy |
215 | ASSERT_L( proxy); | 215 | ASSERT_L(proxy); |
216 | *proxy = prelude; | 216 | *proxy = prelude; |
217 | prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data | 217 | prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data |
218 | 218 | ||
@@ -221,7 +221,7 @@ char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, L | |||
221 | lua_pushlightuserdata( L, std::bit_cast<void*>(&factory)); // DPC proxy factory | 221 | lua_pushlightuserdata( L, std::bit_cast<void*>(&factory)); // DPC proxy factory |
222 | get_deep_lookup( L); // DPC proxy metatable? | 222 | get_deep_lookup( L); // DPC proxy metatable? |
223 | 223 | ||
224 | if( lua_isnil( L, -1)) // // No metatable yet. | 224 | if (lua_isnil( L, -1)) // // No metatable yet. |
225 | { | 225 | { |
226 | lua_pop(L, 1); // DPC proxy | 226 | lua_pop(L, 1); // DPC proxy |
227 | int const oldtop{ lua_gettop(L) }; | 227 | int const oldtop{ lua_gettop(L) }; |
@@ -245,7 +245,7 @@ char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, L | |||
245 | lua_newtable( L); // DPC proxy metatable | 245 | lua_newtable( L); // DPC proxy metatable |
246 | lua_pushnil( L); // DPC proxy metatable nil | 246 | lua_pushnil( L); // DPC proxy metatable nil |
247 | } | 247 | } |
248 | if( lua_isnil( L, -1)) | 248 | if (lua_isnil( L, -1)) |
249 | { | 249 | { |
250 | // Add our own '__gc' method | 250 | // Add our own '__gc' method |
251 | lua_pop( L, 1); // DPC proxy metatable | 251 | lua_pop( L, 1); // DPC proxy metatable |
@@ -269,22 +269,22 @@ char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, L | |||
269 | // L.registry._LOADED exists without having registered the 'package' library. | 269 | // L.registry._LOADED exists without having registered the 'package' library. |
270 | lua_getglobal( L, "require"); // DPC proxy metatable require() | 270 | lua_getglobal( L, "require"); // DPC proxy metatable require() |
271 | // check that the module is already loaded (or being loaded, we are happy either way) | 271 | // check that the module is already loaded (or being loaded, we are happy either way) |
272 | if( lua_isfunction( L, -1)) | 272 | if (lua_isfunction( L, -1)) |
273 | { | 273 | { |
274 | lua_pushstring( L, modname); // DPC proxy metatable require() "module" | 274 | lua_pushstring( L, modname); // DPC proxy metatable require() "module" |
275 | lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED | 275 | lua_getfield( L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // DPC proxy metatable require() "module" _R._LOADED |
276 | if( lua_istable( L, -1)) | 276 | if (lua_istable( L, -1)) |
277 | { | 277 | { |
278 | lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" | 278 | lua_pushvalue( L, -2); // DPC proxy metatable require() "module" _R._LOADED "module" |
279 | lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module | 279 | lua_rawget( L, -2); // DPC proxy metatable require() "module" _R._LOADED module |
280 | int const alreadyloaded = lua_toboolean( L, -1); | 280 | int const alreadyloaded = lua_toboolean( L, -1); |
281 | if( !alreadyloaded) // not loaded | 281 | if (!alreadyloaded) // not loaded |
282 | { | 282 | { |
283 | int require_result; | 283 | int require_result; |
284 | lua_pop( L, 2); // DPC proxy metatable require() "module" | 284 | lua_pop( L, 2); // DPC proxy metatable require() "module" |
285 | // require "modname" | 285 | // require "modname" |
286 | require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? | 286 | require_result = lua_pcall( L, 1, 0, 0); // DPC proxy metatable error? |
287 | if( require_result != LUA_OK) | 287 | if (require_result != LUA_OK) |
288 | { | 288 | { |
289 | // failed, return the error message | 289 | // failed, return the error message |
290 | lua_pushfstring( L, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); | 290 | lua_pushfstring( L, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); |
@@ -326,7 +326,7 @@ char const* DeepFactory::PushDeepProxy(Dest L, DeepPrelude* prelude, int nuv_, L | |||
326 | return nullptr; | 326 | return nullptr; |
327 | } | 327 | } |
328 | 328 | ||
329 | // ################################################################################################ | 329 | // ################################################################################################# |
330 | 330 | ||
331 | /* | 331 | /* |
332 | * Create a deep userdata | 332 | * Create a deep userdata |
@@ -354,7 +354,7 @@ int DeepFactory::pushDeepUserdata(Dest L, int nuv_) const | |||
354 | return luaL_error( L, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); | 354 | return luaL_error( L, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); |
355 | } | 355 | } |
356 | 356 | ||
357 | if( prelude->m_magic != DEEP_VERSION) | 357 | if (prelude->m_magic != DEEP_VERSION) |
358 | { | 358 | { |
359 | // just in case, don't leak the newly allocated deep userdata object | 359 | // just in case, don't leak the newly allocated deep userdata object |
360 | deleteDeepObjectInternal(L, prelude); | 360 | deleteDeepObjectInternal(L, prelude); |
@@ -364,7 +364,7 @@ int DeepFactory::pushDeepUserdata(Dest L, int nuv_) const | |||
364 | ASSERT_L(prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 | 364 | ASSERT_L(prelude->m_refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 |
365 | ASSERT_L(&prelude->m_factory == this); | 365 | ASSERT_L(&prelude->m_factory == this); |
366 | 366 | ||
367 | if( lua_gettop( L) - oldtop != 0) | 367 | if (lua_gettop( L) - oldtop != 0) |
368 | { | 368 | { |
369 | // just in case, don't leak the newly allocated deep userdata object | 369 | // just in case, don't leak the newly allocated deep userdata object |
370 | deleteDeepObjectInternal(L, prelude); | 370 | deleteDeepObjectInternal(L, prelude); |
@@ -380,7 +380,7 @@ int DeepFactory::pushDeepUserdata(Dest L, int nuv_) const | |||
380 | return 1; | 380 | return 1; |
381 | } | 381 | } |
382 | 382 | ||
383 | // ################################################################################################ | 383 | // ################################################################################################# |
384 | 384 | ||
385 | /* | 385 | /* |
386 | * Access deep userdata through a proxy. | 386 | * Access deep userdata through a proxy. |
@@ -402,7 +402,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L, int index) const | |||
402 | return *proxy; | 402 | return *proxy; |
403 | } | 403 | } |
404 | 404 | ||
405 | // ################################################################################################ | 405 | // ################################################################################################# |
406 | 406 | ||
407 | /* | 407 | /* |
408 | * Copy deep userdata between two separate Lua states (from L to L2) | 408 | * Copy deep userdata between two separate Lua states (from L to L2) |
@@ -28,7 +28,7 @@ enum class LookupMode | |||
28 | FromKeeper // send a function from a keeper state to a lane | 28 | FromKeeper // send a function from a keeper state to a lane |
29 | }; | 29 | }; |
30 | 30 | ||
31 | // ################################################################################################ | 31 | // ################################################################################################# |
32 | 32 | ||
33 | // xxh64 of string "DEEP_VERSION_3" generated at https://www.pelock.com/products/hash-calculator | 33 | // xxh64 of string "DEEP_VERSION_3" generated at https://www.pelock.com/products/hash-calculator |
34 | static constexpr UniqueKey DEEP_VERSION{ 0xB2CC0FD9C0AE9674ull, "DEEP_VERSION_3" }; | 34 | static constexpr UniqueKey DEEP_VERSION{ 0xB2CC0FD9C0AE9674ull, "DEEP_VERSION_3" }; |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 3e26d5e..5d94944 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -48,9 +48,9 @@ | |||
48 | #include <algorithm> | 48 | #include <algorithm> |
49 | #include <cassert> | 49 | #include <cassert> |
50 | 50 | ||
51 | // ################################################################################### | 51 | // ################################################################################################# |
52 | // Keeper implementation | 52 | // Keeper implementation |
53 | // ################################################################################### | 53 | // ################################################################################################# |
54 | 54 | ||
55 | class keeper_fifo | 55 | class keeper_fifo |
56 | { | 56 | { |
@@ -74,7 +74,7 @@ class keeper_fifo | |||
74 | 74 | ||
75 | static constexpr int CONTENTS_TABLE{ 1 }; | 75 | static constexpr int CONTENTS_TABLE{ 1 }; |
76 | 76 | ||
77 | // ################################################################################################## | 77 | // ################################################################################################# |
78 | 78 | ||
79 | // replaces the fifo ud by its uservalue on the stack | 79 | // replaces the fifo ud by its uservalue on the stack |
80 | [[nodiscard]] static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) | 80 | [[nodiscard]] static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) |
@@ -91,7 +91,7 @@ static constexpr int CONTENTS_TABLE{ 1 }; | |||
91 | return fifo; | 91 | return fifo; |
92 | } | 92 | } |
93 | 93 | ||
94 | // ################################################################################################## | 94 | // ################################################################################################# |
95 | 95 | ||
96 | // in: nothing | 96 | // in: nothing |
97 | // out: { first = 1, count = 0, limit = -1} | 97 | // out: { first = 1, count = 0, limit = -1} |
@@ -107,7 +107,7 @@ static constexpr int CONTENTS_TABLE{ 1 }; | |||
107 | return fifo; | 107 | return fifo; |
108 | } | 108 | } |
109 | 109 | ||
110 | // ################################################################################################## | 110 | // ################################################################################################# |
111 | 111 | ||
112 | // in: expect fifo ... on top of the stack | 112 | // in: expect fifo ... on top of the stack |
113 | // out: nothing, removes all pushed values from the stack | 113 | // out: nothing, removes all pushed values from the stack |
@@ -124,7 +124,7 @@ static void fifo_push(lua_State* L, keeper_fifo* fifo_, int count_) | |||
124 | fifo_->count += count_; | 124 | fifo_->count += count_; |
125 | } | 125 | } |
126 | 126 | ||
127 | // ################################################################################################## | 127 | // ################################################################################################# |
128 | 128 | ||
129 | // in: fifo | 129 | // in: fifo |
130 | // out: ...|nothing | 130 | // out: ...|nothing |
@@ -140,7 +140,7 @@ static void fifo_peek(lua_State* L, keeper_fifo* fifo_, int count_) | |||
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | // ################################################################################################## | 143 | // ################################################################################################# |
144 | 144 | ||
145 | // in: fifo | 145 | // in: fifo |
146 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) | 146 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
@@ -177,7 +177,7 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) | |||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
180 | // ################################################################################################## | 180 | // ################################################################################################# |
181 | 181 | ||
182 | // in: linda_ud expected at stack slot idx | 182 | // in: linda_ud expected at stack slot idx |
183 | // out: fifos[ud] | 183 | // out: fifos[ud] |
@@ -205,7 +205,7 @@ static void push_table(lua_State* L, int idx_) | |||
205 | STACK_CHECK(L, 1); | 205 | STACK_CHECK(L, 1); |
206 | } | 206 | } |
207 | 207 | ||
208 | // ################################################################################################## | 208 | // ################################################################################################# |
209 | 209 | ||
210 | int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) | 210 | int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) |
211 | { | 211 | { |
@@ -258,7 +258,7 @@ int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) | |||
258 | return 1; | 258 | return 1; |
259 | } | 259 | } |
260 | 260 | ||
261 | // ################################################################################################## | 261 | // ################################################################################################# |
262 | 262 | ||
263 | // in: linda_ud | 263 | // in: linda_ud |
264 | int keepercall_clear(lua_State* L) | 264 | int keepercall_clear(lua_State* L) |
@@ -274,7 +274,7 @@ int keepercall_clear(lua_State* L) | |||
274 | return 0; | 274 | return 0; |
275 | } | 275 | } |
276 | 276 | ||
277 | // ################################################################################################## | 277 | // ################################################################################################# |
278 | 278 | ||
279 | // in: linda_ud, key, ... | 279 | // in: linda_ud, key, ... |
280 | // out: true|false | 280 | // out: true|false |
@@ -285,7 +285,7 @@ int keepercall_send(lua_State* L) | |||
285 | // get the fifo associated to this key in this linda, create it if it doesn't exist | 285 | // get the fifo associated to this key in this linda, create it if it doesn't exist |
286 | lua_pushvalue(L, 2); // ud key ... fifos key | 286 | lua_pushvalue(L, 2); // ud key ... fifos key |
287 | lua_rawget(L, -2); // ud key ... fifos fifo | 287 | lua_rawget(L, -2); // ud key ... fifos fifo |
288 | if( lua_isnil(L, -1)) | 288 | if (lua_isnil(L, -1)) |
289 | { | 289 | { |
290 | lua_pop(L, 1); // ud key ... fifos | 290 | lua_pop(L, 1); // ud key ... fifos |
291 | std::ignore = fifo_new(L); // ud key ... fifos fifo | 291 | std::ignore = fifo_new(L); // ud key ... fifos fifo |
@@ -311,7 +311,7 @@ int keepercall_send(lua_State* L) | |||
311 | return 1; | 311 | return 1; |
312 | } | 312 | } |
313 | 313 | ||
314 | // ################################################################################################## | 314 | // ################################################################################################# |
315 | 315 | ||
316 | // in: linda_ud, key [, key]? | 316 | // in: linda_ud, key [, key]? |
317 | // out: (key, val) or nothing | 317 | // out: (key, val) or nothing |
@@ -347,13 +347,13 @@ int keepercall_receive(lua_State* L) | |||
347 | return 0; | 347 | return 0; |
348 | } | 348 | } |
349 | 349 | ||
350 | // ################################################################################################## | 350 | // ################################################################################################# |
351 | 351 | ||
352 | // in: linda_ud key mincount [maxcount] | 352 | // in: linda_ud key mincount [maxcount] |
353 | int keepercall_receive_batched(lua_State* L) | 353 | int keepercall_receive_batched(lua_State* L) |
354 | { | 354 | { |
355 | int const min_count{ static_cast<int>(lua_tointeger(L, 3)) }; | 355 | int const min_count{ static_cast<int>(lua_tointeger(L, 3)) }; |
356 | if( min_count > 0) | 356 | if (min_count > 0) |
357 | { | 357 | { |
358 | int const max_count{ static_cast<int>(luaL_optinteger(L, 4, min_count)) }; | 358 | int const max_count{ static_cast<int>(luaL_optinteger(L, 4, min_count)) }; |
359 | lua_settop(L, 2); // ud key | 359 | lua_settop(L, 2); // ud key |
@@ -364,7 +364,7 @@ int keepercall_receive_batched(lua_State* L) | |||
364 | lua_rawget(L, 2); // key fifos fifo | 364 | lua_rawget(L, 2); // key fifos fifo |
365 | lua_remove(L, 2); // key fifo | 365 | lua_remove(L, 2); // key fifo |
366 | keeper_fifo* const fifo{ prepare_fifo_access(L, 2) }; // key fifotbl | 366 | keeper_fifo* const fifo{ prepare_fifo_access(L, 2) }; // key fifotbl |
367 | if( fifo != nullptr && fifo->count >= min_count) | 367 | if (fifo != nullptr && fifo->count >= min_count) |
368 | { | 368 | { |
369 | fifo_pop(L, fifo, std::min( max_count, fifo->count)); // key ... | 369 | fifo_pop(L, fifo, std::min( max_count, fifo->count)); // key ... |
370 | } | 370 | } |
@@ -380,7 +380,7 @@ int keepercall_receive_batched(lua_State* L) | |||
380 | } | 380 | } |
381 | } | 381 | } |
382 | 382 | ||
383 | // ################################################################################################## | 383 | // ################################################################################################# |
384 | 384 | ||
385 | // in: linda_ud key n | 385 | // in: linda_ud key n |
386 | // out: true or nil | 386 | // out: true or nil |
@@ -403,7 +403,7 @@ int keepercall_limit(lua_State* L) | |||
403 | lua_settop(L, 0); | 403 | lua_settop(L, 0); |
404 | // return true if we decide that blocked threads waiting to write on that key should be awakened | 404 | // return true if we decide that blocked threads waiting to write on that key should be awakened |
405 | // this is the case if we detect the key was full but it is no longer the case | 405 | // this is the case if we detect the key was full but it is no longer the case |
406 | if( | 406 | if ( |
407 | ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit | 407 | ((fifo->limit >= 0) && (fifo->count >= fifo->limit)) // the key was full if limited and count exceeded the previous limit |
408 | && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit | 408 | && ((limit < 0) || (fifo->count < limit)) // the key is not full if unlimited or count is lower than the new limit |
409 | ) | 409 | ) |
@@ -416,7 +416,7 @@ int keepercall_limit(lua_State* L) | |||
416 | return lua_gettop(L); | 416 | return lua_gettop(L); |
417 | } | 417 | } |
418 | 418 | ||
419 | // ################################################################################################## | 419 | // ################################################################################################# |
420 | 420 | ||
421 | // in: linda_ud key [[val] ...] | 421 | // in: linda_ud key [[val] ...] |
422 | //out: true if the linda was full but it's no longer the case, else nothing | 422 | //out: true if the linda was full but it's no longer the case, else nothing |
@@ -462,7 +462,7 @@ int keepercall_set(lua_State* L) | |||
462 | lua_pushvalue(L, 2); // fifos key [val [, ...]] key | 462 | lua_pushvalue(L, 2); // fifos key [val [, ...]] key |
463 | lua_rawget(L, 1); // fifos key [val [, ...]] fifo|nil | 463 | lua_rawget(L, 1); // fifos key [val [, ...]] fifo|nil |
464 | keeper_fifo* fifo{ keeper_fifo::getPtr(L, -1) }; | 464 | keeper_fifo* fifo{ keeper_fifo::getPtr(L, -1) }; |
465 | if( fifo == nullptr) // can be nullptr if we store a value at a new key | 465 | if (fifo == nullptr) // can be nullptr if we store a value at a new key |
466 | { // fifos key [val [, ...]] nil | 466 | { // fifos key [val [, ...]] nil |
467 | // no need to wake writers in that case, because a writer can't wait on an inexistent key | 467 | // no need to wake writers in that case, because a writer can't wait on an inexistent key |
468 | lua_pop(L, 1); // fifos key [val [, ...]] | 468 | lua_pop(L, 1); // fifos key [val [, ...]] |
@@ -489,7 +489,7 @@ int keepercall_set(lua_State* L) | |||
489 | return should_wake_writers ? (lua_pushboolean(L, 1), 1) : 0; | 489 | return should_wake_writers ? (lua_pushboolean(L, 1), 1) : 0; |
490 | } | 490 | } |
491 | 491 | ||
492 | // ################################################################################################## | 492 | // ################################################################################################# |
493 | 493 | ||
494 | // in: linda_ud key [count] | 494 | // in: linda_ud key [count] |
495 | // out: at most <count> values | 495 | // out: at most <count> values |
@@ -517,7 +517,7 @@ int keepercall_get(lua_State* L) | |||
517 | return 0; | 517 | return 0; |
518 | } | 518 | } |
519 | 519 | ||
520 | // ################################################################################################## | 520 | // ################################################################################################# |
521 | 521 | ||
522 | // in: linda_ud [, key [, ...]] | 522 | // in: linda_ud [, key [, ...]] |
523 | int keepercall_count(lua_State* L) | 523 | int keepercall_count(lua_State* L) |
@@ -586,9 +586,9 @@ int keepercall_count(lua_State* L) | |||
586 | return 1; | 586 | return 1; |
587 | } | 587 | } |
588 | 588 | ||
589 | //################################################################################### | 589 | // ################################################################################################# |
590 | // Keeper API, accessed from linda methods | 590 | // Keeper API, accessed from linda methods |
591 | //################################################################################### | 591 | // ################################################################################################# |
592 | 592 | ||
593 | /*---=== Keeper states ===--- | 593 | /*---=== Keeper states ===--- |
594 | */ | 594 | */ |
@@ -636,7 +636,7 @@ void close_keepers(Universe* U) | |||
636 | } | 636 | } |
637 | } | 637 | } |
638 | 638 | ||
639 | // ################################################################################################## | 639 | // ################################################################################################# |
640 | 640 | ||
641 | /* | 641 | /* |
642 | * Initialize keeper states | 642 | * Initialize keeper states |
@@ -746,7 +746,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
746 | STACK_CHECK(L, 0); | 746 | STACK_CHECK(L, 0); |
747 | } | 747 | } |
748 | 748 | ||
749 | // ################################################################################################## | 749 | // ################################################################################################# |
750 | 750 | ||
751 | // should be called only when inside a keeper_acquire/keeper_release pair (see Linda::ProtectedCall) | 751 | // should be called only when inside a keeper_acquire/keeper_release pair (see Linda::ProtectedCall) |
752 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) | 752 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) |
@@ -760,7 +760,7 @@ Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) | |||
760 | return nullptr; | 760 | return nullptr; |
761 | } | 761 | } |
762 | 762 | ||
763 | // ################################################################################################## | 763 | // ################################################################################################# |
764 | 764 | ||
765 | Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | 765 | Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) |
766 | { | 766 | { |
@@ -784,7 +784,7 @@ Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | |||
784 | return nullptr; | 784 | return nullptr; |
785 | } | 785 | } |
786 | 786 | ||
787 | // ################################################################################################## | 787 | // ################################################################################################# |
788 | 788 | ||
789 | void keeper_release(Keeper* K) | 789 | void keeper_release(Keeper* K) |
790 | { | 790 | { |
@@ -795,7 +795,7 @@ void keeper_release(Keeper* K) | |||
795 | } | 795 | } |
796 | } | 796 | } |
797 | 797 | ||
798 | // ################################################################################################## | 798 | // ################################################################################################# |
799 | 799 | ||
800 | void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode_) | 800 | void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode_) |
801 | { | 801 | { |
@@ -821,7 +821,7 @@ void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode | |||
821 | } | 821 | } |
822 | } | 822 | } |
823 | 823 | ||
824 | // ################################################################################################## | 824 | // ################################################################################################# |
825 | 825 | ||
826 | /* | 826 | /* |
827 | * Call a function ('func_name') in the keeper state, and pass on the returned | 827 | * Call a function ('func_name') in the keeper state, and pass on the returned |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 17d4f67..3aa3365 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -101,8 +101,63 @@ THE SOFTWARE. | |||
101 | 101 | ||
102 | #include <atomic> | 102 | #include <atomic> |
103 | 103 | ||
104 | // forwarding (will do things better later) | 104 | // ################################################################################################# |
105 | static void tracking_add(Lane* lane_); | 105 | |
106 | #if HAVE_LANE_TRACKING() | ||
107 | |||
108 | // The chain is ended by '(Lane*)(-1)', not nullptr: | ||
109 | // 'tracking_first -> ... -> ... -> (-1)' | ||
110 | #define TRACKING_END ((Lane *)(-1)) | ||
111 | |||
112 | /* | ||
113 | * Add the lane to tracking chain; the ones still running at the end of the | ||
114 | * whole process will be cancelled. | ||
115 | */ | ||
116 | static void tracking_add(Lane* lane_) | ||
117 | { | ||
118 | std::lock_guard<std::mutex> guard{ lane_->U->tracking_cs }; | ||
119 | assert(lane_->tracking_next == nullptr); | ||
120 | |||
121 | lane_->tracking_next = lane_->U->tracking_first; | ||
122 | lane_->U->tracking_first = lane_; | ||
123 | } | ||
124 | |||
125 | // ################################################################################################# | ||
126 | |||
127 | /* | ||
128 | * A free-running lane has ended; remove it from tracking chain | ||
129 | */ | ||
130 | [[nodiscard]] static bool tracking_remove(Lane* lane_) | ||
131 | { | ||
132 | bool found{ false }; | ||
133 | std::lock_guard<std::mutex> guard{ lane_->U->tracking_cs }; | ||
134 | // Make sure (within the MUTEX) that we actually are in the chain | ||
135 | // still (at process exit they will remove us from chain and then | ||
136 | // cancel/kill). | ||
137 | // | ||
138 | if (lane_->tracking_next != nullptr) | ||
139 | { | ||
140 | Lane** ref = (Lane**) &lane_->U->tracking_first; | ||
141 | |||
142 | while( *ref != TRACKING_END) | ||
143 | { | ||
144 | if (*ref == lane_) | ||
145 | { | ||
146 | *ref = lane_->tracking_next; | ||
147 | lane_->tracking_next = nullptr; | ||
148 | found = true; | ||
149 | break; | ||
150 | } | ||
151 | ref = (Lane**) &((*ref)->tracking_next); | ||
152 | } | ||
153 | assert( found); | ||
154 | } | ||
155 | return found; | ||
156 | } | ||
157 | |||
158 | #endif // HAVE_LANE_TRACKING() | ||
159 | |||
160 | // ################################################################################################# | ||
106 | 161 | ||
107 | Lane::Lane(Universe* U_, lua_State* L_) | 162 | Lane::Lane(Universe* U_, lua_State* L_) |
108 | : U{ U_ } | 163 | : U{ U_ } |
@@ -180,114 +235,44 @@ static constexpr UniqueKey FINALIZER_REGKEY{ 0x188fccb8bf348e09ull }; | |||
180 | 235 | ||
181 | // ################################################################################################# | 236 | // ################################################################################################# |
182 | 237 | ||
183 | /* | 238 | Lane::~Lane() |
184 | * Push a table stored in registry onto Lua stack. | ||
185 | * | ||
186 | * If there is no existing table, create one if 'create' is true. | ||
187 | * | ||
188 | * Returns: true if a table was pushed | ||
189 | * false if no table found, not created, and nothing pushed | ||
190 | */ | ||
191 | [[nodiscard]] static bool push_registry_table(lua_State* L, UniqueKey key, bool create) | ||
192 | { | 239 | { |
193 | STACK_GROW(L, 3); | 240 | // Clean up after a (finished) thread |
194 | STACK_CHECK_START_REL(L, 0); | 241 | // |
195 | 242 | #if HAVE_LANE_TRACKING() | |
196 | key.pushValue(L); // ? | 243 | if (U->tracking_first != nullptr) |
197 | if (lua_isnil(L, -1)) // nil? | ||
198 | { | 244 | { |
199 | lua_pop(L, 1); // | 245 | // Lane was cleaned up, no need to handle at process termination |
200 | STACK_CHECK(L, 0); | 246 | std::ignore = tracking_remove(this); |
201 | |||
202 | if (!create) | ||
203 | { | ||
204 | return false; | ||
205 | } | ||
206 | |||
207 | lua_newtable(L); // t | ||
208 | key.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | ||
209 | } | 247 | } |
210 | STACK_CHECK(L, 1); | 248 | #endif // HAVE_LANE_TRACKING() |
211 | return true; // table pushed | ||
212 | } | 249 | } |
213 | 250 | ||
214 | // ################################################################################################# | 251 | // ################################################################################################# |
252 | // ########################################## Finalizer ############################################ | ||
253 | // ################################################################################################# | ||
215 | 254 | ||
216 | #if HAVE_LANE_TRACKING() | ||
217 | 255 | ||
218 | // The chain is ended by '(Lane*)(-1)', not nullptr: | 256 | // Push the finalizers table on the stack. |
219 | // 'tracking_first -> ... -> ... -> (-1)' | 257 | // If there is no existing table, create ti. |
220 | #define TRACKING_END ((Lane *)(-1)) | 258 | static void push_finalizers_table(lua_State* L) |
221 | |||
222 | /* | ||
223 | * Add the lane to tracking chain; the ones still running at the end of the | ||
224 | * whole process will be cancelled. | ||
225 | */ | ||
226 | static void tracking_add(Lane* lane_) | ||
227 | { | 259 | { |
228 | std::lock_guard<std::mutex> guard{ lane_->U->tracking_cs }; | 260 | STACK_GROW(L, 3); |
229 | assert(lane_->tracking_next == nullptr); | 261 | STACK_CHECK_START_REL(L, 0); |
230 | |||
231 | lane_->tracking_next = lane_->U->tracking_first; | ||
232 | lane_->U->tracking_first = lane_; | ||
233 | } | ||
234 | |||
235 | // ################################################################################################# | ||
236 | 262 | ||
237 | /* | 263 | FINALIZER_REGKEY.pushValue(L); // ? |
238 | * A free-running lane has ended; remove it from tracking chain | 264 | if (lua_isnil(L, -1)) // nil? |
239 | */ | ||
240 | [[nodiscard]] static bool tracking_remove(Lane* lane_) | ||
241 | { | ||
242 | bool found{ false }; | ||
243 | std::lock_guard<std::mutex> guard{ lane_->U->tracking_cs }; | ||
244 | // Make sure (within the MUTEX) that we actually are in the chain | ||
245 | // still (at process exit they will remove us from chain and then | ||
246 | // cancel/kill). | ||
247 | // | ||
248 | if (lane_->tracking_next != nullptr) | ||
249 | { | 265 | { |
250 | Lane** ref = (Lane**) &lane_->U->tracking_first; | 266 | lua_pop(L, 1); // |
251 | 267 | // store a newly created table in the registry, but leave it on the stack too | |
252 | while( *ref != TRACKING_END) | 268 | lua_newtable(L); // t |
253 | { | 269 | FINALIZER_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // t |
254 | if (*ref == lane_) | ||
255 | { | ||
256 | *ref = lane_->tracking_next; | ||
257 | lane_->tracking_next = nullptr; | ||
258 | found = true; | ||
259 | break; | ||
260 | } | ||
261 | ref = (Lane**) &((*ref)->tracking_next); | ||
262 | } | ||
263 | assert( found); | ||
264 | } | 270 | } |
265 | return found; | 271 | STACK_CHECK(L, 1); |
266 | } | 272 | } |
267 | 273 | ||
268 | #endif // HAVE_LANE_TRACKING() | ||
269 | |||
270 | // ################################################################################################# | 274 | // ################################################################################################# |
271 | 275 | ||
272 | Lane::~Lane() | ||
273 | { | ||
274 | // Clean up after a (finished) thread | ||
275 | // | ||
276 | #if HAVE_LANE_TRACKING() | ||
277 | if (U->tracking_first != nullptr) | ||
278 | { | ||
279 | // Lane was cleaned up, no need to handle at process termination | ||
280 | std::ignore = tracking_remove(this); | ||
281 | } | ||
282 | #endif // HAVE_LANE_TRACKING() | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * ############################################################################################### | ||
287 | * ########################################## Finalizer ########################################## | ||
288 | * ############################################################################################### | ||
289 | */ | ||
290 | |||
291 | //--- | 276 | //--- |
292 | // void= finalizer( finalizer_func ) | 277 | // void= finalizer( finalizer_func ) |
293 | // | 278 | // |
@@ -296,12 +281,12 @@ Lane::~Lane() | |||
296 | // Add a function that will be called when exiting the lane, either via | 281 | // Add a function that will be called when exiting the lane, either via |
297 | // normal return or an error. | 282 | // normal return or an error. |
298 | // | 283 | // |
299 | LUAG_FUNC( set_finalizer) | 284 | LUAG_FUNC(set_finalizer) |
300 | { | 285 | { |
301 | luaL_argcheck(L, lua_isfunction(L, 1), 1, "finalizer should be a function"); | 286 | luaL_argcheck(L, lua_isfunction(L, 1), 1, "finalizer should be a function"); |
302 | luaL_argcheck(L, lua_gettop( L) == 1, 1, "too many arguments"); | 287 | luaL_argcheck(L, lua_gettop( L) == 1, 1, "too many arguments"); |
303 | // Get the current finalizer table (if any), create one if it doesn't exist | 288 | // Get the current finalizer table (if any), create one if it doesn't exist |
304 | std::ignore = push_registry_table(L, FINALIZER_REGKEY, true); // finalizer {finalisers} | 289 | push_finalizers_table(L); // finalizer {finalisers} |
305 | STACK_GROW(L, 2); | 290 | STACK_GROW(L, 2); |
306 | lua_pushinteger(L, lua_rawlen(L, -1) + 1); // finalizer {finalisers} idx | 291 | lua_pushinteger(L, lua_rawlen(L, -1) + 1); // finalizer {finalisers} idx |
307 | lua_pushvalue(L, 1); // finalizer {finalisers} idx finalizer | 292 | lua_pushvalue(L, 1); // finalizer {finalisers} idx finalizer |
@@ -310,7 +295,44 @@ LUAG_FUNC( set_finalizer) | |||
310 | return 0; | 295 | return 0; |
311 | } | 296 | } |
312 | 297 | ||
298 | // ################################################################################################# | ||
299 | |||
300 | static void push_stack_trace(lua_State* L, int rc_, int stk_base_) | ||
301 | { | ||
302 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry | ||
303 | switch(rc_) | ||
304 | { | ||
305 | case LUA_OK: // no error, body return values are on the stack | ||
306 | break; | ||
313 | 307 | ||
308 | case LUA_ERRRUN: // cancellation or a runtime error | ||
309 | #if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler | ||
310 | { | ||
311 | STACK_CHECK_START_REL(L, 0); | ||
312 | // fetch the call stack table from the registry where the handler stored it | ||
313 | STACK_GROW(L, 1); | ||
314 | // yields nil if no stack was generated (in case of cancellation for example) | ||
315 | STACKTRACE_REGKEY.pushValue(L); // err trace|nil | ||
316 | STACK_CHECK(L, 1); | ||
317 | |||
318 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed | ||
319 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | ||
320 | ASSERT_L(lua_type(L, 1 + stk_base_) == (CANCEL_ERROR.equals(L, stk_base_) ? LUA_TNIL : LUA_TTABLE)); | ||
321 | // Just leaving the stack trace table on the stack is enough to get it through to the master. | ||
322 | break; | ||
323 | } | ||
324 | #endif // fall through if not ERROR_FULL_STACK | ||
325 | |||
326 | case LUA_ERRMEM: // memory allocation error (handler not called) | ||
327 | case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) | ||
328 | default: | ||
329 | // we should have a single value which is either a string (the error message) or CANCEL_ERROR | ||
330 | ASSERT_L((lua_gettop(L) == stk_base_) && ((lua_type(L, stk_base_) == LUA_TSTRING) || CANCEL_ERROR.equals(L, stk_base_))); | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | // ################################################################################################# | ||
314 | //--- | 336 | //--- |
315 | // Run finalizers - if any - with the given parameters | 337 | // Run finalizers - if any - with the given parameters |
316 | // | 338 | // |
@@ -324,43 +346,37 @@ LUAG_FUNC( set_finalizer) | |||
324 | // | 346 | // |
325 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. | 347 | // TBD: should we add stack trace on failing finalizer, wouldn't be hard.. |
326 | // | 348 | // |
327 | static void push_stack_trace( lua_State* L, int rc_, int stk_base_); | ||
328 | 349 | ||
329 | [[nodiscard]] static int run_finalizers(lua_State* L, int lua_rc) | 350 | [[nodiscard]] static int run_finalizers(lua_State* L, int lua_rc_) |
330 | { | 351 | { |
331 | int finalizers_index; | 352 | FINALIZER_REGKEY.pushValue(L); // ... finalizers? |
332 | int n; | 353 | if (lua_isnil(L, -1)) |
333 | int err_handler_index = 0; | ||
334 | int rc = LUA_OK; // ... | ||
335 | if (!push_registry_table(L, FINALIZER_REGKEY, false)) // ... finalizers? | ||
336 | { | 354 | { |
355 | lua_pop(L, 1); | ||
337 | return 0; // no finalizers | 356 | return 0; // no finalizers |
338 | } | 357 | } |
339 | 358 | ||
340 | STACK_GROW(L, 5); | 359 | STACK_GROW(L, 5); |
341 | 360 | ||
342 | finalizers_index = lua_gettop( L); | 361 | int const finalizers_index{ lua_gettop(L) }; |
343 | 362 | int const err_handler_index{ ERROR_FULL_STACK ? (lua_pushcfunction(L, lane_error), lua_gettop(L)) : 0 }; | |
344 | #if ERROR_FULL_STACK | ||
345 | lua_pushcfunction(L, lane_error); // ... finalizers lane_error | ||
346 | err_handler_index = lua_gettop( L); | ||
347 | #endif // ERROR_FULL_STACK | ||
348 | 363 | ||
349 | for( n = (int) lua_rawlen(L, finalizers_index); n > 0; -- n) | 364 | int rc{ LUA_OK }; |
365 | for (int n = static_cast<int>(lua_rawlen(L, finalizers_index)); n > 0; --n) | ||
350 | { | 366 | { |
351 | int args = 0; | 367 | int args = 0; |
352 | lua_pushinteger(L, n); // ... finalizers lane_error n | 368 | lua_pushinteger(L, n); // ... finalizers lane_error n |
353 | lua_rawget(L, finalizers_index); // ... finalizers lane_error finalizer | 369 | lua_rawget(L, finalizers_index); // ... finalizers lane_error finalizer |
354 | ASSERT_L( lua_isfunction(L, -1)); | 370 | ASSERT_L(lua_isfunction(L, -1)); |
355 | if (lua_rc != LUA_OK) // we have an error message and an optional stack trace at the bottom of the stack | 371 | if (lua_rc_ != LUA_OK) // we have an error message and an optional stack trace at the bottom of the stack |
356 | { | 372 | { |
357 | ASSERT_L( finalizers_index == 2 || finalizers_index == 3); | 373 | ASSERT_L( finalizers_index == 2 || finalizers_index == 3); |
358 | //char const* err_msg = lua_tostring(L, 1); | 374 | //char const* err_msg = lua_tostring(L, 1); |
359 | lua_pushvalue(L, 1); // ... finalizers lane_error finalizer err_msg | 375 | lua_pushvalue(L, 1); // ... finalizers lane_error finalizer err_msg |
360 | // note we don't always have a stack trace for example when CANCEL_ERROR, or when we got an error that doesn't call our handler, such as LUA_ERRMEM | 376 | // note we don't always have a stack trace for example when CANCEL_ERROR, or when we got an error that doesn't call our handler, such as LUA_ERRMEM |
361 | if (finalizers_index == 3) | 377 | if (finalizers_index == 3) |
362 | { | 378 | { |
363 | lua_pushvalue(L, 2); // ... finalizers lane_error finalizer err_msg stack_trace | 379 | lua_pushvalue(L, 2); // ... finalizers lane_error finalizer err_msg stack_trace |
364 | } | 380 | } |
365 | args = finalizers_index - 1; | 381 | args = finalizers_index - 1; |
366 | } | 382 | } |
@@ -369,21 +385,21 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_); | |||
369 | rc = lua_pcall(L, args, 0, err_handler_index); // ... finalizers lane_error err_msg2? | 385 | rc = lua_pcall(L, args, 0, err_handler_index); // ... finalizers lane_error err_msg2? |
370 | if (rc != LUA_OK) | 386 | if (rc != LUA_OK) |
371 | { | 387 | { |
372 | push_stack_trace(L, rc, lua_gettop( L)); | 388 | push_stack_trace(L, rc, lua_gettop(L)); |
373 | // If one finalizer fails, don't run the others. Return this | 389 | // If one finalizer fails, don't run the others. Return this |
374 | // as the 'real' error, replacing what we could have had (or not) | 390 | // as the 'real' error, replacing what we could have had (or not) |
375 | // from the actual code. | 391 | // from the actual code. |
376 | break; | 392 | break; |
377 | } | 393 | } |
378 | // no error, proceed to next finalizer // ... finalizers lane_error | 394 | // no error, proceed to next finalizer // ... finalizers lane_error |
379 | } | 395 | } |
380 | 396 | ||
381 | if (rc != LUA_OK) | 397 | if (rc != LUA_OK) |
382 | { | 398 | { |
383 | // ERROR_FULL_STACK accounts for the presence of lane_error on the stack | 399 | // ERROR_FULL_STACK accounts for the presence of lane_error on the stack |
384 | int nb_err_slots = lua_gettop( L) - finalizers_index - ERROR_FULL_STACK; | 400 | int const nb_err_slots{ lua_gettop(L) - finalizers_index - ERROR_FULL_STACK }; |
385 | // a finalizer generated an error, this is what we leave of the stack | 401 | // a finalizer generated an error, this is what we leave of the stack |
386 | for( n = nb_err_slots; n > 0; -- n) | 402 | for (int n = nb_err_slots; n > 0; --n) |
387 | { | 403 | { |
388 | lua_replace(L, n); | 404 | lua_replace(L, n); |
389 | } | 405 | } |
@@ -399,9 +415,9 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_); | |||
399 | } | 415 | } |
400 | 416 | ||
401 | /* | 417 | /* |
402 | * ############################################################################################### | 418 | * ################################################################################################ |
403 | * ########################################### Threads ########################################### | 419 | * ########################################### Threads ############################################ |
404 | * ############################################################################################### | 420 | * ################################################################################################ |
405 | */ | 421 | */ |
406 | 422 | ||
407 | // | 423 | // |
@@ -425,7 +441,7 @@ static void selfdestruct_add(Lane* lane_) | |||
425 | lane_->U->selfdestruct_first = lane_; | 441 | lane_->U->selfdestruct_first = lane_; |
426 | } | 442 | } |
427 | 443 | ||
428 | // ############################################################################################### | 444 | // ################################################################################################# |
429 | 445 | ||
430 | /* | 446 | /* |
431 | * A free-running lane has ended; remove it from selfdestruct chain | 447 | * A free-running lane has ended; remove it from selfdestruct chain |
@@ -460,7 +476,7 @@ static void selfdestruct_add(Lane* lane_) | |||
460 | return found; | 476 | return found; |
461 | } | 477 | } |
462 | 478 | ||
463 | // ############################################################################################### | 479 | // ################################################################################################# |
464 | 480 | ||
465 | /* | 481 | /* |
466 | * Process end; cancel any still free-running threads | 482 | * Process end; cancel any still free-running threads |
@@ -567,7 +583,7 @@ static void selfdestruct_add(Lane* lane_) | |||
567 | return 0; | 583 | return 0; |
568 | } | 584 | } |
569 | 585 | ||
570 | // ############################################################################################### | 586 | // ################################################################################################# |
571 | 587 | ||
572 | //--- | 588 | //--- |
573 | // = _single( [cores_uint=1] ) | 589 | // = _single( [cores_uint=1] ) |
@@ -597,7 +613,7 @@ LUAG_FUNC( set_singlethreaded) | |||
597 | #endif | 613 | #endif |
598 | } | 614 | } |
599 | 615 | ||
600 | // ############################################################################################### | 616 | // ################################################################################################# |
601 | 617 | ||
602 | /* | 618 | /* |
603 | * str= lane_error( error_val|str ) | 619 | * str= lane_error( error_val|str ) |
@@ -710,41 +726,6 @@ LUAG_FUNC( set_error_reporting) | |||
710 | } | 726 | } |
711 | #endif // ERROR_FULL_STACK | 727 | #endif // ERROR_FULL_STACK |
712 | 728 | ||
713 | static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | ||
714 | { | ||
715 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry | ||
716 | switch( rc_) | ||
717 | { | ||
718 | case LUA_OK: // no error, body return values are on the stack | ||
719 | break; | ||
720 | |||
721 | case LUA_ERRRUN: // cancellation or a runtime error | ||
722 | #if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler | ||
723 | { | ||
724 | STACK_CHECK_START_REL(L, 0); | ||
725 | // fetch the call stack table from the registry where the handler stored it | ||
726 | STACK_GROW(L, 1); | ||
727 | // yields nil if no stack was generated (in case of cancellation for example) | ||
728 | STACKTRACE_REGKEY.pushValue(L); // err trace|nil | ||
729 | STACK_CHECK(L, 1); | ||
730 | |||
731 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed | ||
732 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | ||
733 | ASSERT_L(lua_type(L, 1 + stk_base_) == (CANCEL_ERROR.equals(L, stk_base_) ? LUA_TNIL : LUA_TTABLE)); | ||
734 | // Just leaving the stack trace table on the stack is enough to get it through to the master. | ||
735 | break; | ||
736 | } | ||
737 | #endif // fall through if not ERROR_FULL_STACK | ||
738 | |||
739 | case LUA_ERRMEM: // memory allocation error (handler not called) | ||
740 | case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) | ||
741 | default: | ||
742 | // we should have a single value which is either a string (the error message) or CANCEL_ERROR | ||
743 | ASSERT_L((lua_gettop(L) == stk_base_) && ((lua_type(L, stk_base_) == LUA_TSTRING) || CANCEL_ERROR.equals(L, stk_base_))); | ||
744 | break; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | // ################################################################################################# | 729 | // ################################################################################################# |
749 | 730 | ||
750 | LUAG_FUNC(set_debug_threadname) | 731 | LUAG_FUNC(set_debug_threadname) |
@@ -772,7 +753,7 @@ LUAG_FUNC(set_debug_threadname) | |||
772 | 753 | ||
773 | LUAG_FUNC(get_debug_threadname) | 754 | LUAG_FUNC(get_debug_threadname) |
774 | { | 755 | { |
775 | Lane* const lane{ lua_toLane(L, 1) }; | 756 | Lane* const lane{ ToLane(L, 1) }; |
776 | luaL_argcheck(L, lua_gettop(L) == 1, 2, "too many arguments"); | 757 | luaL_argcheck(L, lua_gettop(L) == 1, 2, "too many arguments"); |
777 | lua_pushstring(L, lane->debug_name); | 758 | lua_pushstring(L, lane->debug_name); |
778 | return 1; | 759 | return 1; |
@@ -828,8 +809,7 @@ static struct errcode_name s_errcodes[] = | |||
828 | }; | 809 | }; |
829 | static char const* get_errcode_name( int _code) | 810 | static char const* get_errcode_name( int _code) |
830 | { | 811 | { |
831 | int i; | 812 | for (int i{ 0 }; i < 7; ++i) |
832 | for( i = 0; i < 7; ++ i) | ||
833 | { | 813 | { |
834 | if (s_errcodes[i].code == _code) | 814 | if (s_errcodes[i].code == _code) |
835 | { | 815 | { |
@@ -891,7 +871,6 @@ static void lane_main(Lane* lane) | |||
891 | push_stack_trace(L, rc, 1); // retvals|error [trace] | 871 | push_stack_trace(L, rc, 1); // retvals|error [trace] |
892 | 872 | ||
893 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name(rc), CANCEL_ERROR.equals(L, 1) ? "cancelled" : lua_typename(L, lua_type(L, 1)))); | 873 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name(rc), CANCEL_ERROR.equals(L, 1) ? "cancelled" : lua_typename(L, lua_type(L, 1)))); |
894 | // STACK_DUMP(L); | ||
895 | // Call finalizers, if the script has set them up. | 874 | // Call finalizers, if the script has set them up. |
896 | // | 875 | // |
897 | int rc2{ run_finalizers(L, rc) }; | 876 | int rc2{ run_finalizers(L, rc) }; |
@@ -1295,7 +1274,7 @@ LUAG_FUNC(lane_new) | |||
1295 | [[nodiscard]] static int lane_gc(lua_State* L) | 1274 | [[nodiscard]] static int lane_gc(lua_State* L) |
1296 | { | 1275 | { |
1297 | bool have_gc_cb{ false }; | 1276 | bool have_gc_cb{ false }; |
1298 | Lane* const lane{ lua_toLane(L, 1) }; // ud | 1277 | Lane* const lane{ ToLane(L, 1) }; // ud |
1299 | 1278 | ||
1300 | // if there a gc callback? | 1279 | // if there a gc callback? |
1301 | lua_getiuservalue(L, 1, 1); // ud uservalue | 1280 | lua_getiuservalue(L, 1, 1); // ud uservalue |
@@ -1393,7 +1372,7 @@ void push_thread_status(lua_State* L, Lane* lane_) | |||
1393 | // | 1372 | // |
1394 | LUAG_FUNC(thread_join) | 1373 | LUAG_FUNC(thread_join) |
1395 | { | 1374 | { |
1396 | Lane* const lane{ lua_toLane(L, 1) }; | 1375 | Lane* const lane{ ToLane(L, 1) }; |
1397 | lua_Duration const duration{ luaL_optnumber(L, 2, -1.0) }; | 1376 | lua_Duration const duration{ luaL_optnumber(L, 2, -1.0) }; |
1398 | lua_State* const L2{ lane->L }; | 1377 | lua_State* const L2{ lane->L }; |
1399 | 1378 | ||
@@ -1474,7 +1453,7 @@ LUAG_FUNC(thread_index) | |||
1474 | static constexpr int UD{ 1 }; | 1453 | static constexpr int UD{ 1 }; |
1475 | static constexpr int KEY{ 2 }; | 1454 | static constexpr int KEY{ 2 }; |
1476 | static constexpr int USR{ 3 }; | 1455 | static constexpr int USR{ 3 }; |
1477 | Lane* const lane{ lua_toLane(L, UD) }; | 1456 | Lane* const lane{ ToLane(L, UD) }; |
1478 | ASSERT_L(lua_gettop(L) == 2); | 1457 | ASSERT_L(lua_gettop(L) == 2); |
1479 | 1458 | ||
1480 | STACK_GROW(L, 8); // up to 8 positions are needed in case of error propagation | 1459 | STACK_GROW(L, 8); // up to 8 positions are needed in case of error propagation |
@@ -1647,11 +1626,9 @@ LUAG_FUNC(threads) | |||
1647 | } | 1626 | } |
1648 | #endif // HAVE_LANE_TRACKING() | 1627 | #endif // HAVE_LANE_TRACKING() |
1649 | 1628 | ||
1650 | /* | 1629 | // ################################################################################################# |
1651 | * ############################################################################################### | 1630 | // ######################################## Timer support ########################################## |
1652 | * ######################################## Timer support ######################################## | 1631 | // ################################################################################################# |
1653 | * ############################################################################################### | ||
1654 | */ | ||
1655 | 1632 | ||
1656 | /* | 1633 | /* |
1657 | * secs = now_secs() | 1634 | * secs = now_secs() |
@@ -1722,11 +1699,9 @@ LUAG_FUNC(wakeup_conv) | |||
1722 | return 1; | 1699 | return 1; |
1723 | } | 1700 | } |
1724 | 1701 | ||
1725 | /* | 1702 | // ################################################################################################# |
1726 | * ############################################################################################### | 1703 | // ######################################## Module linkage ######################################### |
1727 | * ######################################## Module linkage ####################################### | 1704 | // ################################################################################################# |
1728 | * ############################################################################################### | ||
1729 | */ | ||
1730 | 1705 | ||
1731 | extern int LG_linda(lua_State* L); | 1706 | extern int LG_linda(lua_State* L); |
1732 | static struct luaL_Reg const lanes_functions[] = | 1707 | static struct luaL_Reg const lanes_functions[] = |
diff --git a/src/lanes_private.h b/src/lanes_private.h index 18e55fd..5e6160d 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h | |||
@@ -98,7 +98,7 @@ static constexpr UniqueKey LANE_POINTER_REGKEY{ 0xB3022205633743BCull }; // used | |||
98 | // 'Lane' are malloc/free'd and the handle only carries a pointer. | 98 | // 'Lane' are malloc/free'd and the handle only carries a pointer. |
99 | // This is not deep userdata since the handle's not portable among lanes. | 99 | // This is not deep userdata since the handle's not portable among lanes. |
100 | // | 100 | // |
101 | [[nodiscard]] inline Lane* lua_toLane(lua_State* L, int i_) | 101 | [[nodiscard]] inline Lane* ToLane(lua_State* L, int i_) |
102 | { | 102 | { |
103 | return *(static_cast<Lane**>(luaL_checkudata(L, i_, "Lane"))); | 103 | return *(static_cast<Lane**>(luaL_checkudata(L, i_, "Lane"))); |
104 | } | 104 | } |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 073e940..c01363a 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -35,7 +35,6 @@ using namespace std::chrono_literals; | |||
35 | #ifdef NDEBUG | 35 | #ifdef NDEBUG |
36 | 36 | ||
37 | #define _ASSERT_L(lua,c) //nothing | 37 | #define _ASSERT_L(lua,c) //nothing |
38 | #define STACK_DUMP(L) //nothing | ||
39 | 38 | ||
40 | #define STACK_CHECK_START_REL(L, offset_) | 39 | #define STACK_CHECK_START_REL(L, offset_) |
41 | #define STACK_CHECK_START_ABS(L, offset_) | 40 | #define STACK_CHECK_START_ABS(L, offset_) |
@@ -45,8 +44,7 @@ using namespace std::chrono_literals; | |||
45 | 44 | ||
46 | #else // NDEBUG | 45 | #else // NDEBUG |
47 | 46 | ||
48 | #define _ASSERT_L(L, cond_) if( (cond_) == 0) { (void) luaL_error(L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} | 47 | #define _ASSERT_L(L, cond_) if ((cond_) == 0) { (void) luaL_error(L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} |
49 | #define STACK_DUMP(L) luaG_dump(L) | ||
50 | 48 | ||
51 | class StackChecker | 49 | class StackChecker |
52 | { | 50 | { |
diff --git a/src/state.cpp b/src/state.cpp index 1ba5a77..9ad237d 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -37,7 +37,7 @@ THE SOFTWARE. | |||
37 | #include "tools.h" | 37 | #include "tools.h" |
38 | #include "universe.h" | 38 | #include "universe.h" |
39 | 39 | ||
40 | // ################################################################################################ | 40 | // ################################################################################################# |
41 | 41 | ||
42 | /*---=== Serialize require ===--- | 42 | /*---=== Serialize require ===--- |
43 | */ | 43 | */ |
@@ -71,7 +71,7 @@ THE SOFTWARE. | |||
71 | 71 | ||
72 | // 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 |
73 | 73 | ||
74 | if( rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? | 74 | if (rc != LUA_OK) // LUA_ERRRUN / LUA_ERRMEM ? |
75 | { | 75 | { |
76 | raise_lua_error(L); | 76 | raise_lua_error(L); |
77 | } | 77 | } |
@@ -108,7 +108,7 @@ void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | |||
108 | STACK_CHECK(L, 0); | 108 | STACK_CHECK(L, 0); |
109 | } | 109 | } |
110 | 110 | ||
111 | // ################################################################################################ | 111 | // ################################################################################################# |
112 | 112 | ||
113 | /*---=== luaG_newstate ===---*/ | 113 | /*---=== luaG_newstate ===---*/ |
114 | 114 | ||
@@ -161,10 +161,9 @@ static luaL_Reg const libs[] = | |||
161 | 161 | ||
162 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, char const* name_, size_t len_) | 162 | static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, char const* name_, size_t len_) |
163 | { | 163 | { |
164 | int i; | 164 | for (int i{ 0 }; libs[i].name; ++i) |
165 | for( i = 0; libs[i].name; ++ i) | ||
166 | { | 165 | { |
167 | if( strncmp( name_, libs[i].name, len_) == 0) | 166 | if (strncmp( name_, libs[i].name, len_) == 0) |
168 | { | 167 | { |
169 | lua_CFunction libfunc = libs[i].func; | 168 | lua_CFunction libfunc = libs[i].func; |
170 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ | 169 | name_ = libs[i].name; // note that the provided name_ doesn't necessarily ends with '\0', hence len_ |
@@ -176,7 +175,7 @@ static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, char const | |||
176 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 175 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
177 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 176 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
178 | // lanes.core doesn't declare a global, so scan it here and now | 177 | // lanes.core doesn't declare a global, so scan it here and now |
179 | if( isLanesCore == true) | 178 | if (isLanesCore == true) |
180 | { | 179 | { |
181 | populate_func_lookup_table( L, -1, name_); | 180 | populate_func_lookup_table( L, -1, name_); |
182 | } | 181 | } |
@@ -220,7 +219,7 @@ void initialize_on_state_create( Universe* U, lua_State* L) | |||
220 | { | 219 | { |
221 | STACK_CHECK_START_REL(L, 1); // settings | 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 |
@@ -371,7 +370,7 @@ lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) | |||
371 | { | 370 | { |
372 | // special "*" case (mainly to help with LuaJIT compatibility) | 371 | // special "*" case (mainly to help with LuaJIT compatibility) |
373 | // 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 |
374 | if( libs_[0] == '*' && libs_[1] == 0) | 373 | if (libs_[0] == '*' && libs_[1] == 0) |
375 | { | 374 | { |
376 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); | 375 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
377 | luaL_openlibs( L); | 376 | luaL_openlibs( L); |
@@ -396,26 +395,25 @@ lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) | |||
396 | STACK_CHECK(L, 0); | 395 | STACK_CHECK(L, 0); |
397 | 396 | ||
398 | // scan all libraries, open them one by one | 397 | // scan all libraries, open them one by one |
399 | if( libs_) | 398 | if (libs_) |
400 | { | 399 | { |
401 | char const* p; | 400 | unsigned int len{ 0 }; |
402 | unsigned int len = 0; | 401 | for (char const* p{ libs_ }; *p; p += len) |
403 | for( p = libs_; *p; p += len) | ||
404 | { | 402 | { |
405 | // skip delimiters ('.' can be part of name for "lanes.core") | 403 | // skip delimiters ('.' can be part of name for "lanes.core") |
406 | while( *p && !isalnum( *p) && *p != '.') | 404 | while( *p && !isalnum(*p) && *p != '.') |
407 | ++ p; | 405 | ++ p; |
408 | // skip name | 406 | // skip name |
409 | len = 0; | 407 | len = 0; |
410 | while( isalnum( p[len]) || p[len] == '.') | 408 | while( isalnum(p[len]) || p[len] == '.') |
411 | ++ len; | 409 | ++ len; |
412 | // open library | 410 | // open library |
413 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, p, len); | 411 | open1lib(DEBUGSPEW_PARAM_COMMA( U) L, p, len); |
414 | } | 412 | } |
415 | } | 413 | } |
416 | lua_gc( L, LUA_GCRESTART, 0); | 414 | lua_gc(L, LUA_GCRESTART, 0); |
417 | 415 | ||
418 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); | 416 | serialize_require(DEBUGSPEW_PARAM_COMMA( U) L); |
419 | 417 | ||
420 | // call this after the base libraries are loaded and GC is restarted | 418 | // call this after the base libraries are loaded and GC is restarted |
421 | // will raise an error in from_ in case of problem | 419 | // will raise an error in from_ in case of problem |
@@ -423,7 +421,7 @@ lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) | |||
423 | 421 | ||
424 | STACK_CHECK(L, 0); | 422 | STACK_CHECK(L, 0); |
425 | // after all this, register everything we find in our name<->function database | 423 | // after all this, register everything we find in our name<->function database |
426 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 424 | lua_pushglobaltable(L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
427 | STACK_CHECK(L, 1); | 425 | STACK_CHECK(L, 1); |
428 | populate_func_lookup_table(L, -1, nullptr); | 426 | populate_func_lookup_table(L, -1, nullptr); |
429 | 427 | ||
diff --git a/src/state.h b/src/state.h index e1c311a..059e163 100644 --- a/src/state.h +++ b/src/state.h | |||
@@ -8,12 +8,12 @@ class Universe; | |||
8 | 8 | ||
9 | void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L); | 9 | void serialize_require(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L); |
10 | 10 | ||
11 | // ################################################################################################ | 11 | // ################################################################################################# |
12 | 12 | ||
13 | [[nodiscard]] lua_State* create_state(Universe* U, lua_State* from_); | 13 | [[nodiscard]] lua_State* create_state(Universe* U, lua_State* from_); |
14 | [[nodiscard]] lua_State* luaG_newstate(Universe* U, Source _from, char const* libs); | 14 | [[nodiscard]] lua_State* luaG_newstate(Universe* U, Source _from, char const* libs); |
15 | 15 | ||
16 | // ################################################################################################ | 16 | // ################################################################################################# |
17 | 17 | ||
18 | void initialize_on_state_create(Universe* U, lua_State* L); | 18 | void initialize_on_state_create(Universe* U, lua_State* L); |
19 | void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMode mode_); | 19 | void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMode mode_); |
diff --git a/src/threading.cpp b/src/threading.cpp index 259693a..c7928c1 100644 --- a/src/threading.cpp +++ b/src/threading.cpp | |||
@@ -105,8 +105,8 @@ THE SOFTWARE. | |||
105 | 105 | ||
106 | /*---=== Threading ===---*/ | 106 | /*---=== Threading ===---*/ |
107 | 107 | ||
108 | // ################################################################################################## | 108 | // ################################################################################################# |
109 | // ################################################################################################## | 109 | // ################################################################################################# |
110 | #if THREADAPI == THREADAPI_WINDOWS | 110 | #if THREADAPI == THREADAPI_WINDOWS |
111 | 111 | ||
112 | static int const gs_prio_remap[] = | 112 | static int const gs_prio_remap[] = |
@@ -120,7 +120,7 @@ static int const gs_prio_remap[] = | |||
120 | THREAD_PRIORITY_TIME_CRITICAL | 120 | THREAD_PRIORITY_TIME_CRITICAL |
121 | }; | 121 | }; |
122 | 122 | ||
123 | // ############################################################################################### | 123 | // ################################################################################################# |
124 | 124 | ||
125 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) | 125 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) |
126 | { | 126 | { |
@@ -131,7 +131,7 @@ void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) | |||
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | // ############################################################################################### | 134 | // ################################################################################################# |
135 | 135 | ||
136 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, [[maybe_unused]] bool sudo_) | 136 | void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, [[maybe_unused]] bool sudo_) |
137 | { | 137 | { |
@@ -142,7 +142,7 @@ void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_, [[maybe_unused]] boo | |||
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | // ############################################################################################### | 145 | // ################################################################################################# |
146 | 146 | ||
147 | void THREAD_SET_AFFINITY(unsigned int aff) | 147 | void THREAD_SET_AFFINITY(unsigned int aff) |
148 | { | 148 | { |
@@ -152,7 +152,7 @@ void THREAD_SET_AFFINITY(unsigned int aff) | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | 154 | ||
155 | // ############################################################################################### | 155 | // ################################################################################################# |
156 | 156 | ||
157 | #if !defined __GNUC__ | 157 | #if !defined __GNUC__ |
158 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx | 158 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx |
@@ -187,11 +187,11 @@ void THREAD_SETNAME(char const* _name) | |||
187 | #endif // !__GNUC__ | 187 | #endif // !__GNUC__ |
188 | } | 188 | } |
189 | 189 | ||
190 | // ################################################################################################## | 190 | // ################################################################################################# |
191 | // ################################################################################################## | 191 | // ################################################################################################# |
192 | #else // THREADAPI == THREADAPI_PTHREAD | 192 | #else // THREADAPI == THREADAPI_PTHREAD |
193 | // ################################################################################################## | 193 | // ################################################################################################# |
194 | // ################################################################################################## | 194 | // ################################################################################################# |
195 | 195 | ||
196 | // PThread (Linux, OS X, ...) | 196 | // PThread (Linux, OS X, ...) |
197 | // | 197 | // |
diff --git a/src/threading.h b/src/threading.h index fc35730..e13932b 100644 --- a/src/threading.h +++ b/src/threading.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #define THREADAPI_WINDOWS 1 | 7 | #define THREADAPI_WINDOWS 1 |
8 | #define THREADAPI_PTHREAD 2 | 8 | #define THREADAPI_PTHREAD 2 |
9 | 9 | ||
10 | #if( defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) | 10 | #if (defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) |
11 | //#pragma message ( "THREADAPI_WINDOWS" ) | 11 | //#pragma message ( "THREADAPI_WINDOWS" ) |
12 | #define THREADAPI THREADAPI_WINDOWS | 12 | #define THREADAPI THREADAPI_WINDOWS |
13 | #else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 13 | #else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
@@ -17,8 +17,8 @@ | |||
17 | 17 | ||
18 | static constexpr int THREAD_PRIO_DEFAULT{ -999 }; | 18 | static constexpr int THREAD_PRIO_DEFAULT{ -999 }; |
19 | 19 | ||
20 | // ################################################################################################## | 20 | // ################################################################################################# |
21 | // ################################################################################################## | 21 | // ################################################################################################# |
22 | #if THREADAPI == THREADAPI_WINDOWS | 22 | #if THREADAPI == THREADAPI_WINDOWS |
23 | 23 | ||
24 | #if defined(PLATFORM_XBOX) | 24 | #if defined(PLATFORM_XBOX) |
@@ -43,11 +43,11 @@ static constexpr int THREAD_PRIO_DEFAULT{ -999 }; | |||
43 | static constexpr int THREAD_PRIO_MIN{ -3 }; | 43 | static constexpr int THREAD_PRIO_MIN{ -3 }; |
44 | static constexpr int THREAD_PRIO_MAX{ +3 }; | 44 | static constexpr int THREAD_PRIO_MAX{ +3 }; |
45 | 45 | ||
46 | // ################################################################################################## | 46 | // ################################################################################################# |
47 | // ################################################################################################## | 47 | // ################################################################################################# |
48 | #else // THREADAPI == THREADAPI_PTHREAD | 48 | #else // THREADAPI == THREADAPI_PTHREAD |
49 | // ################################################################################################## | 49 | // ################################################################################################# |
50 | // ################################################################################################## | 50 | // ################################################################################################# |
51 | 51 | ||
52 | // PThread (Linux, OS X, ...) | 52 | // PThread (Linux, OS X, ...) |
53 | 53 | ||
@@ -65,8 +65,8 @@ static constexpr int THREAD_PRIO_MIN{ -3 }; | |||
65 | static constexpr int THREAD_PRIO_MAX{ +3 }; | 65 | static constexpr int THREAD_PRIO_MAX{ +3 }; |
66 | 66 | ||
67 | #endif // THREADAPI == THREADAPI_PTHREAD | 67 | #endif // THREADAPI == THREADAPI_PTHREAD |
68 | // ################################################################################################## | 68 | // ################################################################################################# |
69 | // ################################################################################################## | 69 | // ################################################################################################# |
70 | 70 | ||
71 | void THREAD_SETNAME(char const* _name); | 71 | void THREAD_SETNAME(char const* _name); |
72 | void THREAD_SET_PRIORITY(int prio_, bool sudo_); | 72 | void THREAD_SET_PRIORITY(int prio_, bool sudo_); |
diff --git a/src/tools.cpp b/src/tools.cpp index ad706be..cd25eda 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -35,13 +35,12 @@ THE SOFTWARE. | |||
35 | 35 | ||
36 | #include "universe.h" | 36 | #include "universe.h" |
37 | 37 | ||
38 | // functions implemented in deep.c | ||
39 | extern void push_registry_subtable( lua_State* L, UniqueKey key_); | ||
40 | |||
41 | DEBUGSPEW_CODE(char const* const DebugSpewIndentScope::debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 38 | DEBUGSPEW_CODE(char const* const DebugSpewIndentScope::debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
42 | 39 | ||
40 | // crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | ||
41 | static constexpr UniqueKey LOOKUPCACHE_REGKEY{ 0x837a68dfc6fcb716ull }; | ||
43 | 42 | ||
44 | // ################################################################################################ | 43 | // ################################################################################################# |
45 | 44 | ||
46 | /* | 45 | /* |
47 | * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it | 46 | * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it |
@@ -76,7 +75,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode | |||
76 | ASSERT_L(lua_istable(L, -1)); | 75 | ASSERT_L(lua_istable(L, -1)); |
77 | } | 76 | } |
78 | 77 | ||
79 | // ################################################################################################ | 78 | // ################################################################################################# |
80 | 79 | ||
81 | /* | 80 | /* |
82 | * Push a registry subtable (keyed by unique 'key_') onto the stack. | 81 | * Push a registry subtable (keyed by unique 'key_') onto the stack. |
@@ -87,60 +86,7 @@ void push_registry_subtable( lua_State* L, UniqueKey key_) | |||
87 | push_registry_subtable_mode(L, key_, nullptr); | 86 | push_registry_subtable_mode(L, key_, nullptr); |
88 | } | 87 | } |
89 | 88 | ||
90 | // ################################################################################################ | 89 | // ################################################################################################# |
91 | |||
92 | /*---=== luaG_dump ===---*/ | ||
93 | #ifdef _DEBUG | ||
94 | void luaG_dump( lua_State* L) | ||
95 | { | ||
96 | int top = lua_gettop( L); | ||
97 | int i; | ||
98 | |||
99 | fprintf( stderr, "\n\tDEBUG STACK:\n"); | ||
100 | |||
101 | if( top == 0) | ||
102 | fprintf( stderr, "\t(none)\n"); | ||
103 | |||
104 | for( i = 1; i <= top; ++ i) | ||
105 | { | ||
106 | LuaType type{ lua_type_as_enum(L, i) }; | ||
107 | |||
108 | fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type)); | ||
109 | |||
110 | // Print item contents here... | ||
111 | // | ||
112 | // Note: this requires 'tostring()' to be defined. If it is NOT, | ||
113 | // enable it for more debugging. | ||
114 | // | ||
115 | STACK_CHECK_START_REL(L, 0); | ||
116 | STACK_GROW( L, 2); | ||
117 | |||
118 | lua_getglobal( L, "tostring"); | ||
119 | // | ||
120 | // [-1]: tostring function, or nil | ||
121 | |||
122 | if( !lua_isfunction( L, -1)) | ||
123 | { | ||
124 | fprintf( stderr, "('tostring' not available)"); | ||
125 | } | ||
126 | else | ||
127 | { | ||
128 | lua_pushvalue( L, i); | ||
129 | lua_call( L, 1 /*args*/, 1 /*retvals*/); | ||
130 | |||
131 | // Don't trust the string contents | ||
132 | // | ||
133 | fprintf( stderr, "%s", lua_tostring( L, -1)); | ||
134 | } | ||
135 | lua_pop( L, 1); | ||
136 | STACK_CHECK( L, 0); | ||
137 | fprintf( stderr, "\n"); | ||
138 | } | ||
139 | fprintf( stderr, "\n"); | ||
140 | } | ||
141 | #endif // _DEBUG | ||
142 | |||
143 | // ################################################################################################ | ||
144 | 90 | ||
145 | // same as PUC-Lua l_alloc | 91 | // same as PUC-Lua l_alloc |
146 | extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) | 92 | extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) |
@@ -231,7 +177,7 @@ void initialize_allocator_function(Universe* U, lua_State* L) | |||
231 | STACK_CHECK(L, 1); | 177 | STACK_CHECK(L, 1); |
232 | } | 178 | } |
233 | 179 | ||
234 | // ################################################################################################ | 180 | // ################################################################################################# |
235 | 181 | ||
236 | [[nodiscard]] static int dummy_writer(lua_State* L, void const* p, size_t sz, void* ud) | 182 | [[nodiscard]] static int dummy_writer(lua_State* L, void const* p, size_t sz, void* ud) |
237 | { | 183 | { |
@@ -239,7 +185,6 @@ void initialize_allocator_function(Universe* U, lua_State* L) | |||
239 | return 666; | 185 | return 666; |
240 | } | 186 | } |
241 | 187 | ||
242 | |||
243 | /* | 188 | /* |
244 | * differentiation between C, bytecode and JIT-fast functions | 189 | * differentiation between C, bytecode and JIT-fast functions |
245 | * | 190 | * |
@@ -262,25 +207,25 @@ enum FuncSubType | |||
262 | FST_FastJIT | 207 | FST_FastJIT |
263 | } ; | 208 | } ; |
264 | 209 | ||
265 | FuncSubType luaG_getfuncsubtype( lua_State *L, int _i) | 210 | FuncSubType luaG_getfuncsubtype(lua_State* L, int _i) |
266 | { | 211 | { |
267 | if( lua_tocfunction( L, _i)) | 212 | if (lua_tocfunction(L, _i)) // nullptr for LuaJIT-fast && bytecode functions |
268 | { | 213 | { |
269 | return FST_Native; | 214 | return FST_Native; |
270 | } | 215 | } |
271 | { | 216 | { |
272 | int mustpush = 0, dumpres; | 217 | int mustpush{ 0 }; |
273 | if( lua_absindex( L, _i) != lua_gettop( L)) | 218 | if (lua_absindex(L, _i) != lua_gettop(L)) |
274 | { | 219 | { |
275 | lua_pushvalue( L, _i); | 220 | lua_pushvalue(L, _i); |
276 | mustpush = 1; | 221 | mustpush = 1; |
277 | } | 222 | } |
278 | // the provided writer fails with code 666 | 223 | // the provided writer fails with code 666 |
279 | // therefore, anytime we get 666, this means that lua_dump() attempted a dump | 224 | // therefore, anytime we get 666, this means that lua_dump() attempted a dump |
280 | // all other cases mean this is either a C or LuaJIT-fast function | 225 | // all other cases mean this is either a C or LuaJIT-fast function |
281 | dumpres = lua504_dump(L, dummy_writer, nullptr, 0); | 226 | int const dumpres{ lua504_dump(L, dummy_writer, nullptr, 0) }; |
282 | lua_pop( L, mustpush); | 227 | lua_pop(L, mustpush); |
283 | if( dumpres == 666) | 228 | if (dumpres == 666) |
284 | { | 229 | { |
285 | return FST_Bytecode; | 230 | return FST_Bytecode; |
286 | } | 231 | } |
@@ -290,40 +235,28 @@ FuncSubType luaG_getfuncsubtype( lua_State *L, int _i) | |||
290 | 235 | ||
291 | // ################################################################################################# | 236 | // ################################################################################################# |
292 | 237 | ||
293 | [[nodiscard]] static lua_CFunction luaG_tocfunction(lua_State* L, int _i, FuncSubType* _out) | ||
294 | { | ||
295 | lua_CFunction p = lua_tocfunction( L, _i); | ||
296 | *_out = luaG_getfuncsubtype( L, _i); | ||
297 | return p; | ||
298 | } | ||
299 | |||
300 | // crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | ||
301 | static constexpr UniqueKey LOOKUPCACHE_REGKEY{ 0x837a68dfc6fcb716ull }; | ||
302 | |||
303 | // ################################################################################################# | ||
304 | |||
305 | // inspired from tconcat() in ltablib.c | 238 | // inspired from tconcat() in ltablib.c |
306 | [[nodiscard]] static char const* luaG_pushFQN(lua_State* L, int t, int last, size_t* length) | 239 | [[nodiscard]] static char const* luaG_pushFQN(lua_State* L, int t, int last, size_t* length) |
307 | { | 240 | { |
308 | int i = 1; | ||
309 | luaL_Buffer b; | 241 | luaL_Buffer b; |
310 | STACK_CHECK_START_REL(L, 0); | 242 | STACK_CHECK_START_REL(L, 0); |
311 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... | 243 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... |
312 | luaL_buffinit( L, &b); // ... {} ... &b? | 244 | luaL_buffinit(L, &b); // ... {} ... &b? |
313 | for( ; i < last; ++ i) | 245 | int i = 1; |
246 | for (; i < last; ++i) | ||
314 | { | 247 | { |
315 | lua_rawgeti( L, t, i); | 248 | lua_rawgeti( L, t, i); |
316 | luaL_addvalue( &b); | 249 | luaL_addvalue( &b); |
317 | luaL_addlstring(&b, "/", 1); | 250 | luaL_addlstring(&b, "/", 1); |
318 | } | 251 | } |
319 | if( i == last) // add last value (if interval was not empty) | 252 | if (i == last) // add last value (if interval was not empty) |
320 | { | 253 | { |
321 | lua_rawgeti( L, t, i); | 254 | lua_rawgeti(L, t, i); |
322 | luaL_addvalue( &b); | 255 | luaL_addvalue(&b); |
323 | } | 256 | } |
324 | // &b is popped at that point (-> replaced by the result) | 257 | // &b is popped at that point (-> replaced by the result) |
325 | luaL_pushresult( &b); // ... {} ... "<result>" | 258 | luaL_pushresult(&b); // ... {} ... "<result>" |
326 | STACK_CHECK( L, 1); | 259 | STACK_CHECK(L, 1); |
327 | return lua_tolstring( L, -1, length); | 260 | return lua_tolstring( L, -1, length); |
328 | } | 261 | } |
329 | 262 | ||
@@ -337,12 +270,12 @@ static constexpr UniqueKey LOOKUPCACHE_REGKEY{ 0x837a68dfc6fcb716ull }; | |||
337 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter | 270 | * if we already had an entry of type [o] = ..., replace the name if the new one is shorter |
338 | * pops the processed object from the stack | 271 | * pops the processed object from the stack |
339 | */ | 272 | */ |
340 | static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth) | 273 | static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, int _ctx_base, int _depth) |
341 | { | 274 | { |
342 | // slot 1 in the stack contains the table that receives everything we found | 275 | // slot 1 in the stack contains the table that receives everything we found |
343 | int const dest = _ctx_base; | 276 | int const dest{ _ctx_base }; |
344 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 277 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
345 | int const fqn = _ctx_base + 1; | 278 | int const fqn{ _ctx_base + 1 }; |
346 | 279 | ||
347 | size_t prevNameLength, newNameLength; | 280 | size_t prevNameLength, newNameLength; |
348 | char const* prevName; | 281 | char const* prevName; |
@@ -352,16 +285,16 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L | |||
352 | 285 | ||
353 | STACK_CHECK_START_REL(L, 0); | 286 | STACK_CHECK_START_REL(L, 0); |
354 | // first, raise an error if the function is already known | 287 | // first, raise an error if the function is already known |
355 | lua_pushvalue( L, -1); // ... {bfc} k o o | 288 | lua_pushvalue(L, -1); // ... {bfc} k o o |
356 | lua_rawget( L, dest); // ... {bfc} k o name? | 289 | lua_rawget(L, dest); // ... {bfc} k o name? |
357 | prevName = lua_tolstring( L, -1, &prevNameLength); // nullptr if we got nil (first encounter of this object) | 290 | prevName = lua_tolstring( L, -1, &prevNameLength); // nullptr if we got nil (first encounter of this object) |
358 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) | 291 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) |
359 | lua_pushvalue( L, -3); // ... {bfc} k o name? k | 292 | lua_pushvalue(L, -3); // ... {bfc} k o name? k |
360 | ASSERT_L( lua_type( L, -1) == LUA_TNUMBER || lua_type( L, -1) == LUA_TSTRING); | 293 | ASSERT_L(lua_type(L, -1) == LUA_TNUMBER || lua_type(L, -1) == LUA_TSTRING); |
361 | ++ _depth; | 294 | ++_depth; |
362 | lua_rawseti( L, fqn, _depth); // ... {bfc} k o name? | 295 | lua_rawseti(L, fqn, _depth); // ... {bfc} k o name? |
363 | // generate name | 296 | // generate name |
364 | DEBUGSPEW_OR_NOT(newName, std::ignore) = luaG_pushFQN(L, fqn, _depth, &newNameLength);// ... {bfc} k o name? "f.q.n" | 297 | DEBUGSPEW_OR_NOT(newName, std::ignore) = luaG_pushFQN(L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n" |
365 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order | 298 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order |
366 | // on different VMs even when the tables are populated the exact same way. | 299 | // on different VMs even when the tables are populated the exact same way. |
367 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), | 300 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), |
@@ -375,36 +308,36 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L | |||
375 | { | 308 | { |
376 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName)); | 309 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName)); |
377 | // the previous name is 'smaller' than the one we just generated: keep it! | 310 | // the previous name is 'smaller' than the one we just generated: keep it! |
378 | lua_pop( L, 3); // ... {bfc} k | 311 | lua_pop(L, 3); // ... {bfc} k |
379 | } | 312 | } |
380 | else | 313 | else |
381 | { | 314 | { |
382 | // the name we generated is either the first one, or a better fit for our purposes | 315 | // the name we generated is either the first one, or a better fit for our purposes |
383 | if( prevName) | 316 | if (prevName) |
384 | { | 317 | { |
385 | // clear the previous name for the database to avoid clutter | 318 | // clear the previous name for the database to avoid clutter |
386 | lua_insert( L, -2); // ... {bfc} k o "f.q.n" prevName | 319 | lua_insert(L, -2); // ... {bfc} k o "f.q.n" prevName |
387 | // t[prevName] = nil | 320 | // t[prevName] = nil |
388 | lua_pushnil( L); // ... {bfc} k o "f.q.n" prevName nil | 321 | lua_pushnil(L); // ... {bfc} k o "f.q.n" prevName nil |
389 | lua_rawset( L, dest); // ... {bfc} k o "f.q.n" | 322 | lua_rawset(L, dest); // ... {bfc} k o "f.q.n" |
390 | } | 323 | } |
391 | else | 324 | else |
392 | { | 325 | { |
393 | lua_remove( L, -2); // ... {bfc} k o "f.q.n" | 326 | lua_remove(L, -2); // ... {bfc} k o "f.q.n" |
394 | } | 327 | } |
395 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -2)), newName)); | 328 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename(L, lua_type( L, -2)), newName)); |
396 | // prepare the stack for database feed | 329 | // prepare the stack for database feed |
397 | lua_pushvalue( L, -1); // ... {bfc} k o "f.q.n" "f.q.n" | 330 | lua_pushvalue(L, -1); // ... {bfc} k o "f.q.n" "f.q.n" |
398 | lua_pushvalue( L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o | 331 | lua_pushvalue(L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o |
399 | ASSERT_L( lua_rawequal( L, -1, -4)); | 332 | ASSERT_L(lua_rawequal(L, -1, -4)); |
400 | ASSERT_L( lua_rawequal( L, -2, -3)); | 333 | ASSERT_L(lua_rawequal(L, -2, -3)); |
401 | // t["f.q.n"] = o | 334 | // t["f.q.n"] = o |
402 | lua_rawset( L, dest); // ... {bfc} k o "f.q.n" | 335 | lua_rawset(L, dest); // ... {bfc} k o "f.q.n" |
403 | // t[o] = "f.q.n" | 336 | // t[o] = "f.q.n" |
404 | lua_rawset( L, dest); // ... {bfc} k | 337 | lua_rawset(L, dest); // ... {bfc} k |
405 | // remove table name from fqn stack | 338 | // remove table name from fqn stack |
406 | lua_pushnil( L); // ... {bfc} k nil | 339 | lua_pushnil(L); // ... {bfc} k nil |
407 | lua_rawseti( L, fqn, _depth); // ... {bfc} k | 340 | lua_rawseti(L, fqn, _depth); // ... {bfc} k |
408 | } | 341 | } |
409 | -- _depth; | 342 | -- _depth; |
410 | STACK_CHECK(L, -1); | 343 | STACK_CHECK(L, -1); |
@@ -414,122 +347,121 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L | |||
414 | 347 | ||
415 | static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, int _ctx_base, int _i, int _depth) | 348 | static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, int _ctx_base, int _i, int _depth) |
416 | { | 349 | { |
417 | lua_Integer visit_count; | ||
418 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 350 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
419 | int const fqn = _ctx_base + 1; | 351 | int const fqn = _ctx_base + 1; |
420 | // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops | 352 | // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops |
421 | int const cache = _ctx_base + 2; | 353 | int const cache = _ctx_base + 2; |
422 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 354 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
423 | int const breadth_first_cache = lua_gettop( L) + 1; | 355 | int const breadth_first_cache = lua_gettop(L) + 1; |
424 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); | 356 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); |
425 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); | 357 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
426 | 358 | ||
427 | STACK_GROW( L, 6); | 359 | STACK_GROW(L, 6); |
428 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 360 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
429 | STACK_CHECK_START_REL(L, 0); // ... {_i} | 361 | STACK_CHECK_START_REL(L, 0); // ... {_i} |
430 | 362 | ||
431 | // if object is a userdata, replace it by its metatable | 363 | // if object is a userdata, replace it by its metatable |
432 | if( lua_type( L, _i) == LUA_TUSERDATA) | 364 | if (lua_type(L, _i) == LUA_TUSERDATA) |
433 | { | 365 | { |
434 | lua_getmetatable( L, _i); // ... {_i} mt | 366 | lua_getmetatable(L, _i); // ... {_i} mt |
435 | lua_replace( L, _i); // ... {_i} | 367 | lua_replace(L, _i); // ... {_i} |
436 | } | 368 | } |
437 | 369 | ||
438 | // if table is already visited, we are done | 370 | // if table is already visited, we are done |
439 | lua_pushvalue( L, _i); // ... {_i} {} | 371 | lua_pushvalue(L, _i); // ... {_i} {} |
440 | lua_rawget( L, cache); // ... {_i} nil|n | 372 | lua_rawget(L, cache); // ... {_i} nil|n |
441 | visit_count = lua_tointeger( L, -1); // 0 if nil, else n | 373 | lua_Integer visit_count{ lua_tointeger(L, -1) }; // 0 if nil, else n |
442 | lua_pop( L, 1); // ... {_i} | 374 | lua_pop(L, 1); // ... {_i} |
443 | STACK_CHECK( L, 0); | 375 | STACK_CHECK(L, 0); |
444 | if( visit_count > 0) | 376 | if (visit_count > 0) |
445 | { | 377 | { |
446 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); | 378 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); |
447 | return; | 379 | return; |
448 | } | 380 | } |
449 | 381 | ||
450 | // remember we visited this table (1-visit count) | 382 | // remember we visited this table (1-visit count) |
451 | lua_pushvalue( L, _i); // ... {_i} {} | 383 | lua_pushvalue(L, _i); // ... {_i} {} |
452 | lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 | 384 | lua_pushinteger(L, visit_count + 1); // ... {_i} {} 1 |
453 | lua_rawset( L, cache); // ... {_i} | 385 | lua_rawset(L, cache); // ... {_i} |
454 | STACK_CHECK( L, 0); | 386 | STACK_CHECK(L, 0); |
455 | 387 | ||
456 | // this table is at breadth_first_cache index | 388 | // this table is at breadth_first_cache index |
457 | lua_newtable( L); // ... {_i} {bfc} | 389 | lua_newtable(L); // ... {_i} {bfc} |
458 | ASSERT_L( lua_gettop( L) == breadth_first_cache); | 390 | ASSERT_L( lua_gettop(L) == breadth_first_cache); |
459 | // iterate over all entries in the processed table | 391 | // iterate over all entries in the processed table |
460 | lua_pushnil( L); // ... {_i} {bfc} nil | 392 | lua_pushnil(L); // ... {_i} {bfc} nil |
461 | while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v | 393 | while( lua_next(L, _i) != 0) // ... {_i} {bfc} k v |
462 | { | 394 | { |
463 | // just for debug, not actually needed | 395 | // just for debug, not actually needed |
464 | //char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"; | 396 | //char const* key = (lua_type(L, -2) == LUA_TSTRING) ? lua_tostring(L, -2) : "not a string"; |
465 | // subtable: process it recursively | 397 | // subtable: process it recursively |
466 | if( lua_istable( L, -1)) // ... {_i} {bfc} k {} | 398 | if (lua_istable(L, -1)) // ... {_i} {bfc} k {} |
467 | { | 399 | { |
468 | // increment visit count to make sure we will actually scan it at this recursive level | 400 | // increment visit count to make sure we will actually scan it at this recursive level |
469 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 401 | lua_pushvalue(L, -1); // ... {_i} {bfc} k {} {} |
470 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} {} | 402 | lua_pushvalue(L, -1); // ... {_i} {bfc} k {} {} {} |
471 | lua_rawget( L, cache); // ... {_i} {bfc} k {} {} n? | 403 | lua_rawget(L, cache); // ... {_i} {bfc} k {} {} n? |
472 | visit_count = lua_tointeger( L, -1) + 1; // 1 if we got nil, else n+1 | 404 | visit_count = lua_tointeger(L, -1) + 1; // 1 if we got nil, else n+1 |
473 | lua_pop( L, 1); // ... {_i} {bfc} k {} {} | 405 | lua_pop(L, 1); // ... {_i} {bfc} k {} {} |
474 | lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n | 406 | lua_pushinteger(L, visit_count); // ... {_i} {bfc} k {} {} n |
475 | lua_rawset( L, cache); // ... {_i} {bfc} k {} | 407 | lua_rawset(L, cache); // ... {_i} {bfc} k {} |
476 | // store the table in the breadth-first cache | 408 | // store the table in the breadth-first cache |
477 | lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k | 409 | lua_pushvalue(L, -2); // ... {_i} {bfc} k {} k |
478 | lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k {} | 410 | lua_pushvalue(L, -2); // ... {_i} {bfc} k {} k {} |
479 | lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k {} | 411 | lua_rawset(L, breadth_first_cache); // ... {_i} {bfc} k {} |
480 | // generate a name, and if we already had one name, keep whichever is the shorter | 412 | // generate a name, and if we already had one name, keep whichever is the shorter |
481 | update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k | 413 | update_lookup_entry( DEBUGSPEW_PARAM_COMMA(U) L, _ctx_base, _depth); // ... {_i} {bfc} k |
482 | } | 414 | } |
483 | else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func | 415 | else if (lua_isfunction(L, -1) && (luaG_getfuncsubtype(L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func |
484 | { | 416 | { |
485 | // generate a name, and if we already had one name, keep whichever is the shorter | 417 | // generate a name, and if we already had one name, keep whichever is the shorter |
486 | update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k | 418 | update_lookup_entry( DEBUGSPEW_PARAM_COMMA(U) L, _ctx_base, _depth); // ... {_i} {bfc} k |
487 | } | 419 | } |
488 | else | 420 | else |
489 | { | 421 | { |
490 | lua_pop( L, 1); // ... {_i} {bfc} k | 422 | lua_pop(L, 1); // ... {_i} {bfc} k |
491 | } | 423 | } |
492 | STACK_CHECK( L, 2); | 424 | STACK_CHECK(L, 2); |
493 | } | 425 | } |
494 | // now process the tables we encountered at that depth | 426 | // now process the tables we encountered at that depth |
495 | ++ _depth; | 427 | ++ _depth; |
496 | lua_pushnil( L); // ... {_i} {bfc} nil | 428 | lua_pushnil(L); // ... {_i} {bfc} nil |
497 | while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {} | 429 | while (lua_next(L, breadth_first_cache) != 0) // ... {_i} {bfc} k {} |
498 | { | 430 | { |
499 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); | 431 | DEBUGSPEW_CODE(char const* key = (lua_type(L, -2) == LUA_TSTRING) ? lua_tostring(L, -2) : "not a string"); |
500 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); | 432 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); |
501 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); | 433 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
502 | // un-visit this table in case we do need to process it | 434 | // un-visit this table in case we do need to process it |
503 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 435 | lua_pushvalue(L, -1); // ... {_i} {bfc} k {} {} |
504 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n | 436 | lua_rawget(L, cache); // ... {_i} {bfc} k {} n |
505 | ASSERT_L( lua_type( L, -1) == LUA_TNUMBER); | 437 | ASSERT_L(lua_type(L, -1) == LUA_TNUMBER); |
506 | visit_count = lua_tointeger( L, -1) - 1; | 438 | visit_count = lua_tointeger(L, -1) - 1; |
507 | lua_pop( L, 1); // ... {_i} {bfc} k {} | 439 | lua_pop(L, 1); // ... {_i} {bfc} k {} |
508 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 440 | lua_pushvalue(L, -1); // ... {_i} {bfc} k {} {} |
509 | if( visit_count > 0) | 441 | if (visit_count > 0) |
510 | { | 442 | { |
511 | lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n | 443 | lua_pushinteger(L, visit_count); // ... {_i} {bfc} k {} {} n |
512 | } | 444 | } |
513 | else | 445 | else |
514 | { | 446 | { |
515 | lua_pushnil( L); // ... {_i} {bfc} k {} {} nil | 447 | lua_pushnil(L); // ... {_i} {bfc} k {} {} nil |
516 | } | 448 | } |
517 | lua_rawset( L, cache); // ... {_i} {bfc} k {} | 449 | lua_rawset(L, cache); // ... {_i} {bfc} k {} |
518 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) | 450 | // push table name in fqn stack (note that concatenation will crash if name is a not string!) |
519 | lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k | 451 | lua_pushvalue(L, -2); // ... {_i} {bfc} k {} k |
520 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} | 452 | lua_rawseti(L, fqn, _depth); // ... {_i} {bfc} k {} |
521 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); | 453 | populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(U) L, _ctx_base, lua_gettop(L), _depth); |
522 | lua_pop( L, 1); // ... {_i} {bfc} k | 454 | lua_pop(L, 1); // ... {_i} {bfc} k |
523 | STACK_CHECK( L, 2); | 455 | STACK_CHECK(L, 2); |
524 | } | 456 | } |
525 | // remove table name from fqn stack | 457 | // remove table name from fqn stack |
526 | lua_pushnil( L); // ... {_i} {bfc} nil | 458 | lua_pushnil(L); // ... {_i} {bfc} nil |
527 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} | 459 | lua_rawseti(L, fqn, _depth); // ... {_i} {bfc} |
528 | -- _depth; | 460 | -- _depth; |
529 | // we are done with our cache | 461 | // we are done with our cache |
530 | lua_pop( L, 1); // ... {_i} | 462 | lua_pop(L, 1); // ... {_i} |
531 | STACK_CHECK( L, 0); | 463 | STACK_CHECK(L, 0); |
532 | // we are done // ... {_i} {bfc} | 464 | // we are done // ... {_i} {bfc} |
533 | } | 465 | } |
534 | 466 | ||
535 | // ################################################################################################# | 467 | // ################################################################################################# |
@@ -542,59 +474,59 @@ void populate_func_lookup_table(lua_State* L, int i_, char const* name_) | |||
542 | int const ctx_base = lua_gettop(L) + 1; | 474 | int const ctx_base = lua_gettop(L) + 1; |
543 | int const in_base = lua_absindex(L, i_); | 475 | int const in_base = lua_absindex(L, i_); |
544 | int start_depth = 0; | 476 | int start_depth = 0; |
545 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 477 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); |
546 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); | 478 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); |
547 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); | 479 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
548 | STACK_GROW(L, 3); | 480 | STACK_GROW(L, 3); |
549 | STACK_CHECK_START_REL(L, 0); | 481 | STACK_CHECK_START_REL(L, 0); |
550 | LOOKUP_REGKEY.pushValue(L); // {} | 482 | LOOKUP_REGKEY.pushValue(L); // {} |
551 | STACK_CHECK( L, 1); | 483 | STACK_CHECK(L, 1); |
552 | ASSERT_L( lua_istable( L, -1)); | 484 | ASSERT_L(lua_istable(L, -1)); |
553 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function | 485 | if (lua_type(L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function |
554 | { | 486 | { |
555 | name_ = name_ ? name_ : "nullptr"; | 487 | name_ = name_ ? name_ : "nullptr"; |
556 | lua_pushvalue( L, in_base); // {} f | 488 | lua_pushvalue(L, in_base); // {} f |
557 | lua_pushstring( L, name_); // {} f _name | 489 | lua_pushstring(L, name_); // {} f _name |
558 | lua_rawset( L, -3); // {} | 490 | lua_rawset(L, -3); // {} |
559 | lua_pushstring( L, name_); // {} _name | 491 | lua_pushstring(L, name_); // {} _name |
560 | lua_pushvalue( L, in_base); // {} _name f | 492 | lua_pushvalue(L, in_base); // {} _name f |
561 | lua_rawset( L, -3); // {} | 493 | lua_rawset(L, -3); // {} |
562 | lua_pop( L, 1); // | 494 | lua_pop(L, 1); // |
563 | } | 495 | } |
564 | else if( lua_type( L, in_base) == LUA_TTABLE) | 496 | else if (lua_type(L, in_base) == LUA_TTABLE) |
565 | { | 497 | { |
566 | lua_newtable(L); // {} {fqn} | 498 | lua_newtable(L); // {} {fqn} |
567 | if( name_) | 499 | if (name_) |
568 | { | 500 | { |
569 | STACK_CHECK( L, 2); | 501 | STACK_CHECK(L, 2); |
570 | lua_pushstring( L, name_); // {} {fqn} "name" | 502 | lua_pushstring(L, name_); // {} {fqn} "name" |
571 | // generate a name, and if we already had one name, keep whichever is the shorter | 503 | // generate a name, and if we already had one name, keep whichever is the shorter |
572 | lua_pushvalue( L, in_base); // {} {fqn} "name" t | 504 | lua_pushvalue(L, in_base); // {} {fqn} "name" t |
573 | update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, start_depth); // {} {fqn} "name" | 505 | update_lookup_entry(DEBUGSPEW_PARAM_COMMA(U) L, ctx_base, start_depth); // {} {fqn} "name" |
574 | // don't forget to store the name at the bottom of the fqn stack | 506 | // don't forget to store the name at the bottom of the fqn stack |
575 | ++ start_depth; | 507 | ++ start_depth; |
576 | lua_rawseti( L, -2, start_depth); // {} {fqn} | 508 | lua_rawseti(L, -2, start_depth); // {} {fqn} |
577 | STACK_CHECK( L, 2); | 509 | STACK_CHECK(L, 2); |
578 | } | 510 | } |
579 | // retrieve the cache, create it if we haven't done it yet | 511 | // retrieve the cache, create it if we haven't done it yet |
580 | LOOKUPCACHE_REGKEY.pushValue(L); // {} {fqn} {cache}? | 512 | LOOKUPCACHE_REGKEY.pushValue(L); // {} {fqn} {cache}? |
581 | if( lua_isnil( L, -1)) | 513 | if (lua_isnil(L, -1)) |
582 | { | 514 | { |
583 | lua_pop( L, 1); // {} {fqn} | 515 | lua_pop(L, 1); // {} {fqn} |
584 | lua_newtable( L); // {} {fqn} {cache} | 516 | lua_newtable(L); // {} {fqn} {cache} |
585 | LOOKUPCACHE_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 517 | LOOKUPCACHE_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
586 | STACK_CHECK( L, 3); | 518 | STACK_CHECK(L, 3); |
587 | } | 519 | } |
588 | // process everything we find in that table, filling in lookup data for all functions and tables we see there | 520 | // process everything we find in that table, filling in lookup data for all functions and tables we see there |
589 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth); | 521 | populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(U) L, ctx_base, in_base, start_depth); |
590 | lua_pop( L, 3); | 522 | lua_pop(L, 3); |
591 | } | 523 | } |
592 | else | 524 | else |
593 | { | 525 | { |
594 | lua_pop( L, 1); // | 526 | lua_pop(L, 1); // |
595 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); | 527 | luaL_error(L, "unsupported module type %s", lua_typename(L, lua_type(L, in_base))); // doesn't return |
596 | } | 528 | } |
597 | STACK_CHECK( L, 0); | 529 | STACK_CHECK(L, 0); |
598 | } | 530 | } |
599 | 531 | ||
600 | // ################################################################################################# | 532 | // ################################################################################################# |
@@ -609,38 +541,34 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
609 | */ | 541 | */ |
610 | [[nodiscard]] static lua_Integer get_mt_id(Universe* U, lua_State* L, int i) | 542 | [[nodiscard]] static lua_Integer get_mt_id(Universe* U, lua_State* L, int i) |
611 | { | 543 | { |
612 | lua_Integer id; | 544 | i = lua_absindex(L, i); |
613 | 545 | ||
614 | i = lua_absindex( L, i); | 546 | STACK_GROW(L, 3); |
615 | |||
616 | STACK_GROW( L, 3); | ||
617 | 547 | ||
618 | STACK_CHECK_START_REL(L, 0); | 548 | STACK_CHECK_START_REL(L, 0); |
619 | push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID] | 549 | push_registry_subtable(L, REG_MTID); // ... _R[REG_MTID] |
620 | lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} | 550 | lua_pushvalue(L, i); // ... _R[REG_MTID] {mt} |
621 | lua_rawget( L, -2); // ... _R[REG_MTID] mtk? | 551 | lua_rawget(L, -2); // ... _R[REG_MTID] mtk? |
622 | 552 | ||
623 | id = lua_tointeger( L, -1); // 0 for nil | 553 | lua_Integer id{ lua_tointeger(L, -1) }; // 0 for nil |
624 | lua_pop( L, 1); // ... _R[REG_MTID] | 554 | lua_pop(L, 1); // ... _R[REG_MTID] |
625 | STACK_CHECK( L, 1); | 555 | STACK_CHECK(L, 1); |
626 | 556 | ||
627 | if( id == 0) | 557 | if (id == 0) |
628 | { | 558 | { |
629 | id = U->next_mt_id.fetch_add(1, std::memory_order_relaxed); | 559 | id = U->next_mt_id.fetch_add(1, std::memory_order_relaxed); |
630 | 560 | ||
631 | /* Create two-way references: id_uint <-> table | 561 | // Create two-way references: id_uint <-> table |
632 | */ | 562 | lua_pushvalue(L, i); // ... _R[REG_MTID] {mt} |
633 | lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} | 563 | lua_pushinteger(L, id); // ... _R[REG_MTID] {mt} id |
634 | lua_pushinteger( L, id); // ... _R[REG_MTID] {mt} id | 564 | lua_rawset(L, -3); // ... _R[REG_MTID] |
635 | lua_rawset( L, -3); // ... _R[REG_MTID] | ||
636 | 565 | ||
637 | lua_pushinteger( L, id); // ... _R[REG_MTID] id | 566 | lua_pushinteger(L, id); // ... _R[REG_MTID] id |
638 | lua_pushvalue( L, i); // ... _R[REG_MTID] id {mt} | 567 | lua_pushvalue(L, i); // ... _R[REG_MTID] id {mt} |
639 | lua_rawset( L, -3); // ... _R[REG_MTID] | 568 | lua_rawset(L, -3); // ... _R[REG_MTID] |
640 | } | 569 | } |
641 | lua_pop( L, 1); // ... | 570 | lua_pop(L, 1); // ... |
642 | 571 | STACK_CHECK(L, 0); | |
643 | STACK_CHECK( L, 0); | ||
644 | 572 | ||
645 | return id; | 573 | return id; |
646 | } | 574 | } |
@@ -684,7 +612,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
684 | if (mode_ == LookupMode::FromKeeper) | 612 | if (mode_ == LookupMode::FromKeeper) |
685 | { | 613 | { |
686 | lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! | 614 | lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! |
687 | if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel) | 615 | if (f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel) |
688 | { | 616 | { |
689 | lua_getupvalue( L, i, 1); // ... v ... "f.q.n" | 617 | lua_getupvalue( L, i, 1); // ... v ... "f.q.n" |
690 | } | 618 | } |
@@ -722,7 +650,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
722 | typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2); | 650 | typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2); |
723 | // second return value can be nil if the table was not found | 651 | // second return value can be nil if the table was not found |
724 | // probable reason: the function was removed from the source Lua state before Lanes was required. | 652 | // probable reason: the function was removed from the source Lua state before Lanes was required. |
725 | if( lua_isnil( L, -1)) | 653 | if (lua_isnil( L, -1)) |
726 | { | 654 | { |
727 | gotchaA = " referenced by"; | 655 | gotchaA = " referenced by"; |
728 | gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; | 656 | gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; |
@@ -744,22 +672,20 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
744 | 672 | ||
745 | // ################################################################################################# | 673 | // ################################################################################################# |
746 | 674 | ||
747 | /* | 675 | // Push a looked-up table, or nothing if we found nothing |
748 | * Push a looked-up table, or nothing if we found nothing | 676 | [[nodiscard]] bool InterCopyContext::lookup_table() const |
749 | */ | ||
750 | [[nodiscard]] static bool lookup_table(Dest L2, Source L1, SourceIndex i_, LookupMode mode_, char const* upName_) | ||
751 | { | 677 | { |
752 | // get the name of the table we want to send | 678 | // get the name of the table we want to send |
753 | size_t len; | 679 | size_t len; |
754 | char const* fqn = find_lookup_name(L1, i_, mode_, upName_, &len); | 680 | char const* fqn = find_lookup_name(L1, L1_i, mode, name, &len); |
755 | if (nullptr == fqn) // name not found, it is some user-created table | 681 | if (nullptr == fqn) // name not found, it is some user-created table |
756 | { | 682 | { |
757 | return false; | 683 | return false; |
758 | } | 684 | } |
759 | // push the equivalent table in the destination's stack, retrieved from the lookup table | 685 | // push the equivalent table in the destination's stack, retrieved from the lookup table |
760 | STACK_CHECK_START_REL(L2, 0); // L // L2 | 686 | STACK_CHECK_START_REL(L2, 0); // L // L2 |
761 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 687 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
762 | switch( mode_) | 688 | switch (mode) |
763 | { | 689 | { |
764 | default: // shouldn't happen, in theory... | 690 | default: // shouldn't happen, in theory... |
765 | luaL_error(L1, "internal error: unknown lookup mode"); // doesn't return | 691 | luaL_error(L1, "internal error: unknown lookup mode"); // doesn't return |
@@ -780,7 +706,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
780 | lua_rawget(L2, -2); // {} t | 706 | lua_rawget(L2, -2); // {} t |
781 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) | 707 | // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) |
782 | // but not when we extract something out of a keeper, as there is nothing to clone! | 708 | // but not when we extract something out of a keeper, as there is nothing to clone! |
783 | if (lua_isnil(L2, -1) && mode_ == LookupMode::LaneBody) | 709 | if (lua_isnil(L2, -1) && mode == LookupMode::LaneBody) |
784 | { | 710 | { |
785 | lua_pop(L2, 2); // | 711 | lua_pop(L2, 2); // |
786 | STACK_CHECK(L2, 0); | 712 | STACK_CHECK(L2, 0); |
@@ -797,7 +723,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
797 | lua_pop(L2, 1); // {} t | 723 | lua_pop(L2, 1); // {} t |
798 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 724 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
799 | luaL_error( | 725 | luaL_error( |
800 | (mode_ == LookupMode::FromKeeper) ? L2 : L1 | 726 | (mode == LookupMode::FromKeeper) ? L2 : L1 |
801 | , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database." | 727 | , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database." |
802 | , from ? from : "main" | 728 | , from ? from : "main" |
803 | , fqn | 729 | , fqn |
@@ -808,7 +734,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
808 | lua_remove(L2, -2); // t | 734 | lua_remove(L2, -2); // t |
809 | break; | 735 | break; |
810 | } | 736 | } |
811 | STACK_CHECK( L2, 1); | 737 | STACK_CHECK(L2, 1); |
812 | return true; | 738 | return true; |
813 | } | 739 | } |
814 | 740 | ||
@@ -877,7 +803,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
877 | lua_pushvalue(L, -1); // o "r" {c} {fqn} ... {?} {?} | 803 | lua_pushvalue(L, -1); // o "r" {c} {fqn} ... {?} {?} |
878 | lua_rawget(L, cache); // o "r" {c} {fqn} ... {?} nil/1 | 804 | lua_rawget(L, cache); // o "r" {c} {fqn} ... {?} nil/1 |
879 | // if table is already visited, we are done | 805 | // if table is already visited, we are done |
880 | if( !lua_isnil(L, -1)) | 806 | if (!lua_isnil(L, -1)) |
881 | { | 807 | { |
882 | lua_pop(L, 1); // o "r" {c} {fqn} ... {?} | 808 | lua_pop(L, 1); // o "r" {c} {fqn} ... {?} |
883 | return shortest_; | 809 | return shortest_; |
@@ -902,7 +828,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
902 | { | 828 | { |
903 | STACK_CHECK(L, 2); | 829 | STACK_CHECK(L, 2); |
904 | // update shortest name | 830 | // update shortest name |
905 | if( depth_ < shortest_) | 831 | if (depth_ < shortest_) |
906 | { | 832 | { |
907 | shortest_ = depth_; | 833 | shortest_ = depth_; |
908 | std::ignore = luaG_pushFQN(L, fqn, depth_, nullptr); // o "r" {c} {fqn} ... {?} k v "fqn" | 834 | std::ignore = luaG_pushFQN(L, fqn, depth_, nullptr); // o "r" {c} {fqn} ... {?} k v "fqn" |
@@ -924,7 +850,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
924 | // search in the table's metatable too | 850 | // search in the table's metatable too |
925 | if (lua_getmetatable(L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} | 851 | if (lua_getmetatable(L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} |
926 | { | 852 | { |
927 | if( lua_istable(L, -1)) | 853 | if (lua_istable(L, -1)) |
928 | { | 854 | { |
929 | ++ depth_; | 855 | ++ depth_; |
930 | lua_pushliteral(L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable" | 856 | lua_pushliteral(L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable" |
@@ -966,7 +892,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
966 | int uvi = 1; | 892 | int uvi = 1; |
967 | while (lua_getiuservalue(L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u} | 893 | while (lua_getiuservalue(L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u} |
968 | { | 894 | { |
969 | if( lua_istable(L, -1)) // if it is a table, look inside | 895 | if (lua_istable(L, -1)) // if it is a table, look inside |
970 | { | 896 | { |
971 | ++ depth_; | 897 | ++ depth_; |
972 | lua_pushliteral(L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue" | 898 | lua_pushliteral(L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue" |
@@ -1010,13 +936,13 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull }; | |||
1010 | int luaG_nameof( lua_State* L) | 936 | int luaG_nameof( lua_State* L) |
1011 | { | 937 | { |
1012 | int what = lua_gettop( L); | 938 | int what = lua_gettop( L); |
1013 | if( what > 1) | 939 | if (what > 1) |
1014 | { | 940 | { |
1015 | luaL_argerror( L, what, "too many arguments."); | 941 | luaL_argerror( L, what, "too many arguments."); |
1016 | } | 942 | } |
1017 | 943 | ||
1018 | // nil, boolean, light userdata, number and string aren't identifiable | 944 | // nil, boolean, light userdata, number and string aren't identifiable |
1019 | if( lua_type( L, 1) < LUA_TTABLE) | 945 | if (lua_type( L, 1) < LUA_TTABLE) |
1020 | { | 946 | { |
1021 | lua_pushstring( L, luaL_typename( L, 1)); // o "type" | 947 | lua_pushstring( L, luaL_typename( L, 1)); // o "type" |
1022 | lua_insert( L, -2); // "type" o | 948 | lua_insert( L, -2); // "type" o |
@@ -1036,7 +962,7 @@ int luaG_nameof( lua_State* L) | |||
1036 | // this is where we start the search | 962 | // this is where we start the search |
1037 | lua_pushglobaltable( L); // o nil {c} {fqn} _G | 963 | lua_pushglobaltable( L); // o nil {c} {fqn} _G |
1038 | (void) discover_object_name_recur( L, 6666, 1); | 964 | (void) discover_object_name_recur( L, 6666, 1); |
1039 | if( lua_isnil( L, 2)) // try again with registry, just in case... | 965 | if (lua_isnil( L, 2)) // try again with registry, just in case... |
1040 | { | 966 | { |
1041 | lua_pop( L, 1); // o nil {c} {fqn} | 967 | lua_pop( L, 1); // o nil {c} {fqn} |
1042 | lua_pushliteral( L, "_R"); // o nil {c} {fqn} "_R" | 968 | lua_pushliteral( L, "_R"); // o nil {c} {fqn} "_R" |
@@ -1056,56 +982,56 @@ int luaG_nameof( lua_State* L) | |||
1056 | /* | 982 | /* |
1057 | * Push a looked-up native/LuaJIT function. | 983 | * Push a looked-up native/LuaJIT function. |
1058 | */ | 984 | */ |
1059 | static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mode_, char const* upName_) | 985 | void InterCopyContext::lookup_native_func() const |
1060 | { | 986 | { |
1061 | // get the name of the function we want to send | 987 | // get the name of the function we want to send |
1062 | size_t len; | 988 | size_t len; |
1063 | char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); | 989 | char const* fqn = find_lookup_name(L1, L1_i, mode, name, &len); |
1064 | // push the equivalent function in the destination's stack, retrieved from the lookup table | 990 | // push the equivalent function in the destination's stack, retrieved from the lookup table |
1065 | STACK_CHECK_START_REL(L2, 0); // L // L2 | 991 | STACK_CHECK_START_REL(L2, 0); // L1 // L2 |
1066 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 992 | STACK_GROW(L2, 3); // up to 3 slots are necessary on error |
1067 | switch( mode_) | 993 | switch (mode) |
1068 | { | 994 | { |
1069 | default: // shouldn't happen, in theory... | 995 | default: // shouldn't happen, in theory... |
1070 | (void) luaL_error( L, "internal error: unknown lookup mode"); | 996 | luaL_error(L1, "internal error: unknown lookup mode"); // doesn't return |
1071 | return; | 997 | break; |
1072 | 998 | ||
1073 | case LookupMode::ToKeeper: | 999 | case LookupMode::ToKeeper: |
1074 | // push a sentinel closure that holds the lookup name as upvalue | 1000 | // push a sentinel closure that holds the lookup name as upvalue |
1075 | lua_pushlstring( L2, fqn, len); // "f.q.n" | 1001 | lua_pushlstring(L2, fqn, len); // "f.q.n" |
1076 | lua_pushcclosure( L2, func_lookup_sentinel, 1); // f | 1002 | lua_pushcclosure(L2, func_lookup_sentinel, 1); // f |
1077 | break; | 1003 | break; |
1078 | 1004 | ||
1079 | case LookupMode::LaneBody: | 1005 | case LookupMode::LaneBody: |
1080 | case LookupMode::FromKeeper: | 1006 | case LookupMode::FromKeeper: |
1081 | LOOKUP_REGKEY.pushValue(L2); // {} | 1007 | LOOKUP_REGKEY.pushValue(L2); // {} |
1082 | STACK_CHECK( L2, 1); | 1008 | STACK_CHECK(L2, 1); |
1083 | ASSERT_L( lua_istable( L2, -1)); | 1009 | _ASSERT_L(L1, lua_istable(L2, -1)); |
1084 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1010 | lua_pushlstring(L2, fqn, len); // {} "f.q.n" |
1085 | lua_rawget( L2, -2); // {} f | 1011 | lua_rawget(L2, -2); // {} f |
1086 | // nil means we don't know how to transfer stuff: user should do something | 1012 | // nil means we don't know how to transfer stuff: user should do something |
1087 | // anything other than function or table should not happen! | 1013 | // anything other than function or table should not happen! |
1088 | if( !lua_isfunction( L2, -1) && !lua_istable( L2, -1)) | 1014 | if (!lua_isfunction( L2, -1) && !lua_istable( L2, -1)) |
1089 | { | 1015 | { |
1090 | char const* from, * to; | 1016 | char const* from, * to; |
1091 | lua_getglobal( L, "decoda_name"); // ... f ... decoda_name | 1017 | lua_getglobal(L1, "decoda_name"); // ... f ... decoda_name |
1092 | from = lua_tostring( L, -1); | 1018 | from = lua_tostring(L1, -1); |
1093 | lua_pop( L, 1); // ... f ... | 1019 | lua_pop(L1, 1); // ... f ... |
1094 | lua_getglobal( L2, "decoda_name"); // {} f decoda_name | 1020 | lua_getglobal(L2, "decoda_name"); // {} f decoda_name |
1095 | to = lua_tostring( L2, -1); | 1021 | to = lua_tostring(L2, -1); |
1096 | lua_pop( L2, 1); // {} f | 1022 | lua_pop(L2, 1); // {} f |
1097 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 1023 | // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
1098 | (void) luaL_error( | 1024 | (void) luaL_error( |
1099 | (mode_ == LookupMode::FromKeeper) ? L2 : L | 1025 | (mode == LookupMode::FromKeeper) ? L2 : L1 |
1100 | , "%s%s: function '%s' not found in %s destination transfer database." | 1026 | , "%s%s: function '%s' not found in %s destination transfer database." |
1101 | , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN " | 1027 | , lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN " |
1102 | , from ? from : "main" | 1028 | , from ? from : "main" |
1103 | , fqn | 1029 | , fqn |
1104 | , to ? to : "main" | 1030 | , to ? to : "main" |
1105 | ); | 1031 | ); |
1106 | return; | 1032 | return; |
1107 | } | 1033 | } |
1108 | lua_remove( L2, -2); // f | 1034 | lua_remove(L2, -2); // f |
1109 | break; | 1035 | break; |
1110 | 1036 | ||
1111 | /* keep it in case I need it someday, who knows... | 1037 | /* keep it in case I need it someday, who knows... |
@@ -1115,7 +1041,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo | |||
1115 | char const* upname; | 1041 | char const* upname; |
1116 | lua_CFunction f = lua_tocfunction( L, i); | 1042 | lua_CFunction f = lua_tocfunction( L, i); |
1117 | // copy upvalues | 1043 | // copy upvalues |
1118 | for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != nullptr; ++ n) | 1044 | for (n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != nullptr; ++ n) |
1119 | { | 1045 | { |
1120 | luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]] | 1046 | luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]] |
1121 | } | 1047 | } |
@@ -1166,7 +1092,7 @@ static char const* vt_names[] = | |||
1166 | [[nodiscard]] static int buf_writer(lua_State* L, void const* b, size_t size, void* ud) | 1092 | [[nodiscard]] static int buf_writer(lua_State* L, void const* b, size_t size, void* ud) |
1167 | { | 1093 | { |
1168 | luaL_Buffer* B = (luaL_Buffer*) ud; | 1094 | luaL_Buffer* B = (luaL_Buffer*) ud; |
1169 | if( !B->L) | 1095 | if (!B->L) |
1170 | { | 1096 | { |
1171 | luaL_buffinit( L, B); | 1097 | luaL_buffinit( L, B); |
1172 | } | 1098 | } |
@@ -1278,7 +1204,7 @@ void InterCopyContext::copy_func() const | |||
1278 | { // ... _G up[n] | 1204 | { // ... _G up[n] |
1279 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END, n, c.name)); | 1205 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END, n, c.name)); |
1280 | #if LUA_VERSION_NUM >= 502 | 1206 | #if LUA_VERSION_NUM >= 502 |
1281 | if( lua_rawequal(L1, -1, -2)) // is the upvalue equal to the global table? | 1207 | if (lua_rawequal(L1, -1, -2)) // is the upvalue equal to the global table? |
1282 | { | 1208 | { |
1283 | DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); | 1209 | DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); |
1284 | lua_pushglobaltable(L2); // ... {cache} ... function <upvalues> | 1210 | lua_pushglobaltable(L2); // ... {cache} ... function <upvalues> |
@@ -1331,8 +1257,7 @@ void InterCopyContext::copy_func() const | |||
1331 | */ | 1257 | */ |
1332 | void InterCopyContext::copy_cached_func() const | 1258 | void InterCopyContext::copy_cached_func() const |
1333 | { | 1259 | { |
1334 | FuncSubType funcSubType; | 1260 | FuncSubType const funcSubType{ luaG_getfuncsubtype(L1, L1_i) }; |
1335 | std::ignore = luaG_tocfunction(L1, L1_i, &funcSubType); // nullptr for LuaJIT-fast && bytecode functions | ||
1336 | if (funcSubType == FST_Bytecode) | 1261 | if (funcSubType == FST_Bytecode) |
1337 | { | 1262 | { |
1338 | void* const aspointer = const_cast<void*>(lua_topointer(L1, L1_i)); | 1263 | void* const aspointer = const_cast<void*>(lua_topointer(L1, L1_i)); |
@@ -1376,7 +1301,7 @@ void InterCopyContext::copy_cached_func() const | |||
1376 | } | 1301 | } |
1377 | else // function is native/LuaJIT: no need to cache | 1302 | else // function is native/LuaJIT: no need to cache |
1378 | { | 1303 | { |
1379 | lookup_native_func(L2, L1, L1_i, mode, name); // ... {cache} ... function | 1304 | lookup_native_func(); // ... {cache} ... function |
1380 | // if the function was in fact a lookup sentinel, we can either get a function or a table here | 1305 | // if the function was in fact a lookup sentinel, we can either get a function or a table here |
1381 | _ASSERT_L(L1, lua_isfunction(L2, -1) || lua_istable(L2, -1)); | 1306 | _ASSERT_L(L1, lua_isfunction(L2, -1) || lua_istable(L2, -1)); |
1382 | } | 1307 | } |
@@ -1440,7 +1365,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1440 | SourceIndex const val_i{ lua_gettop(L1) }; | 1365 | SourceIndex const val_i{ lua_gettop(L1) }; |
1441 | SourceIndex const key_i{ val_i - 1 }; | 1366 | SourceIndex const key_i{ val_i - 1 }; |
1442 | 1367 | ||
1443 | // Only basic key types are copied over; others ignored | 1368 | // For the key, only basic key types are copied over. others ignored |
1444 | InterCopyContext c{ U, L2, L1, L2_cache_i, key_i, VT::KEY, mode, name }; | 1369 | InterCopyContext c{ U, L2, L1, L2_cache_i, key_i, VT::KEY, mode, name }; |
1445 | if (!c.inter_copy_one()) | 1370 | if (!c.inter_copy_one()) |
1446 | { | 1371 | { |
@@ -1451,7 +1376,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1451 | } | 1376 | } |
1452 | 1377 | ||
1453 | char* valPath{ nullptr }; | 1378 | char* valPath{ nullptr }; |
1454 | if( U->verboseErrors) | 1379 | if (U->verboseErrors) |
1455 | { | 1380 | { |
1456 | // for debug purposes, let's try to build a useful name | 1381 | // for debug purposes, let's try to build a useful name |
1457 | if (lua_type(L1, key_i) == LUA_TSTRING) | 1382 | if (lua_type(L1, key_i) == LUA_TSTRING) |
@@ -1483,20 +1408,17 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
1483 | valPath = (char*) alloca(strlen(name) + 16 + 5); | 1408 | valPath = (char*) alloca(strlen(name) + 16 + 5); |
1484 | sprintf(valPath, "%s[U:%p]", name, key); | 1409 | sprintf(valPath, "%s[U:%p]", name, key); |
1485 | } | 1410 | } |
1486 | else if( lua_type( L1, key_i) == LUA_TBOOLEAN) | 1411 | else if (lua_type( L1, key_i) == LUA_TBOOLEAN) |
1487 | { | 1412 | { |
1488 | int const key{ lua_toboolean(L1, key_i) }; | 1413 | int const key{ lua_toboolean(L1, key_i) }; |
1489 | valPath = (char*) alloca(strlen(name) + 8); | 1414 | valPath = (char*) alloca(strlen(name) + 8); |
1490 | sprintf(valPath, "%s[%s]", name, key ? "true" : "false"); | 1415 | sprintf(valPath, "%s[%s]", name, key ? "true" : "false"); |
1491 | } | 1416 | } |
1492 | } | 1417 | } |
1493 | /* | ||
1494 | * Contents of metatables are copied with cache checking; | ||
1495 | * important to detect loops. | ||
1496 | */ | ||
1497 | c.L1_i = SourceIndex{ val_i }; | 1418 | c.L1_i = SourceIndex{ val_i }; |
1498 | c.name = valPath ? valPath : name; | 1419 | // Contents of metatables are copied with cache checking. important to detect loops. |
1499 | c.vt = VT::NORMAL; | 1420 | c.vt = VT::NORMAL; |
1421 | c.name = valPath ? valPath : name; | ||
1500 | if (c.inter_copy_one()) | 1422 | if (c.inter_copy_one()) |
1501 | { | 1423 | { |
1502 | _ASSERT_L(L1, lua_istable( L2, -3)); | 1424 | _ASSERT_L(L1, lua_istable( L2, -3)); |
@@ -1539,7 +1461,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1539 | STACK_CHECK(L2, 0); | 1461 | STACK_CHECK(L2, 0); |
1540 | 1462 | ||
1541 | // no metatable? -> not clonable | 1463 | // no metatable? -> not clonable |
1542 | if( !lua_getmetatable(L1, L1_i)) // ... mt? | 1464 | if (!lua_getmetatable(L1, L1_i)) // ... mt? |
1543 | { | 1465 | { |
1544 | STACK_CHECK(L1, 0); | 1466 | STACK_CHECK(L1, 0); |
1545 | return false; | 1467 | return false; |
@@ -1547,7 +1469,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1547 | 1469 | ||
1548 | // no __lanesclone? -> not clonable | 1470 | // no __lanesclone? -> not clonable |
1549 | lua_getfield(L1, -1, "__lanesclone"); // ... mt __lanesclone? | 1471 | lua_getfield(L1, -1, "__lanesclone"); // ... mt __lanesclone? |
1550 | if( lua_isnil(L1, -1)) | 1472 | if (lua_isnil(L1, -1)) |
1551 | { | 1473 | { |
1552 | lua_pop(L1, 2); // ... | 1474 | lua_pop(L1, 2); // ... |
1553 | STACK_CHECK(L1, 0); | 1475 | STACK_CHECK(L1, 0); |
@@ -1565,12 +1487,12 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1565 | lua_pop(L1, 1); // ... mt __lanesclone [uv]+ | 1487 | lua_pop(L1, 1); // ... mt __lanesclone [uv]+ |
1566 | -- uvi; | 1488 | -- uvi; |
1567 | // create the clone userdata with the required number of uservalue slots | 1489 | // create the clone userdata with the required number of uservalue slots |
1568 | void* clone = lua_newuserdatauv(L2, userdata_size, uvi); // ... u | 1490 | void* const clone{ lua_newuserdatauv(L2, userdata_size, uvi) }; // ... u |
1569 | // copy the metatable in the target state, and give it to the clone we put there | 1491 | // copy the metatable in the target state, and give it to the clone we put there |
1570 | InterCopyContext c{ U, L2, L1, L2_cache_i, SourceIndex{ mt }, VT::NORMAL, mode, name }; | 1492 | InterCopyContext c{ U, L2, L1, L2_cache_i, SourceIndex{ mt }, VT::NORMAL, mode, name }; |
1571 | if (c.inter_copy_one()) // ... u mt|sentinel | 1493 | if (c.inter_copy_one()) // ... u mt|sentinel |
1572 | { | 1494 | { |
1573 | if( LookupMode::ToKeeper == mode) // ... u sentinel | 1495 | if (LookupMode::ToKeeper == mode) // ... u sentinel |
1574 | { | 1496 | { |
1575 | _ASSERT_L(L1, lua_tocfunction(L2, -1) == table_lookup_sentinel); | 1497 | _ASSERT_L(L1, lua_tocfunction(L2, -1) == table_lookup_sentinel); |
1576 | // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn | 1498 | // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn |
@@ -1645,7 +1567,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1645 | } | 1567 | } |
1646 | 1568 | ||
1647 | // try clonable userdata first | 1569 | // try clonable userdata first |
1648 | if( copyclone()) | 1570 | if (copyclone()) |
1649 | { | 1571 | { |
1650 | STACK_CHECK(L1, 0); | 1572 | STACK_CHECK(L1, 0); |
1651 | STACK_CHECK(L2, 1); | 1573 | STACK_CHECK(L2, 1); |
@@ -1714,8 +1636,8 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1714 | } | 1636 | } |
1715 | lua_pop(L2, 1); // ... | 1637 | lua_pop(L2, 1); // ... |
1716 | 1638 | ||
1717 | // this function has 2 upvalues: the fqn of its metatable, and the userdata itself | 1639 | // userdata_clone_sentinel has 2 upvalues: the fqn of its metatable, and the userdata itself |
1718 | bool const found{ lookup_table(L2, L1, L1_i, mode, name) }; // ... mt? | 1640 | bool const found{ lookup_table() }; // ... mt? |
1719 | if (!found) | 1641 | if (!found) |
1720 | { | 1642 | { |
1721 | STACK_CHECK(L2, 0); | 1643 | STACK_CHECK(L2, 0); |
@@ -1802,7 +1724,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1802 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) | 1724 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) |
1803 | * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism | 1725 | * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism |
1804 | */ | 1726 | */ |
1805 | if (lookup_table(L2, L1, L1_i, mode, name)) | 1727 | if (lookup_table()) |
1806 | { | 1728 | { |
1807 | _ASSERT_L(L1, lua_istable(L2, -1) || (lua_tocfunction(L2, -1) == table_lookup_sentinel)); // from lookup data. can also be table_lookup_sentinel if this is a table we know | 1729 | _ASSERT_L(L1, lua_istable(L2, -1) || (lua_tocfunction(L2, -1) == table_lookup_sentinel)); // from lookup data. can also be table_lookup_sentinel if this is a table we know |
1808 | return true; | 1730 | return true; |
@@ -1849,6 +1771,71 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1849 | 1771 | ||
1850 | // ################################################################################################# | 1772 | // ################################################################################################# |
1851 | 1773 | ||
1774 | [[nodiscard]] bool InterCopyContext::inter_copy_boolean() const | ||
1775 | { | ||
1776 | int const v{ lua_toboolean(L1, L1_i) }; | ||
1777 | DEBUGSPEW_CODE(fprintf(stderr, "%s\n", v ? "true" : "false")); | ||
1778 | lua_pushboolean(L2, v); | ||
1779 | return true; | ||
1780 | } | ||
1781 | |||
1782 | // ################################################################################################# | ||
1783 | |||
1784 | [[nodiscard]] bool InterCopyContext::inter_copy_lightuserdata() const | ||
1785 | { | ||
1786 | void* const p{ lua_touserdata(L1, L1_i) }; | ||
1787 | DEBUGSPEW_CODE(fprintf(stderr, "%p\n", p)); | ||
1788 | lua_pushlightuserdata(L2, p); | ||
1789 | return true; | ||
1790 | } | ||
1791 | |||
1792 | // ################################################################################################# | ||
1793 | |||
1794 | [[nodiscard]] bool InterCopyContext::inter_copy_nil() const | ||
1795 | { | ||
1796 | if (vt == VT::KEY) | ||
1797 | { | ||
1798 | return false; | ||
1799 | } | ||
1800 | lua_pushnil(L2); | ||
1801 | return true; | ||
1802 | } | ||
1803 | |||
1804 | // ################################################################################################# | ||
1805 | |||
1806 | [[nodiscard]] bool InterCopyContext::inter_copy_number() const | ||
1807 | { | ||
1808 | /* LNUM patch support (keeping integer accuracy) */ | ||
1809 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | ||
1810 | if (lua_isinteger(L1, L1_i)) | ||
1811 | { | ||
1812 | lua_Integer const v{ lua_tointeger(L1, L1_i) }; | ||
1813 | DEBUGSPEW_CODE(fprintf(stderr, LUA_INTEGER_FMT "\n", v)); | ||
1814 | lua_pushinteger(L2, v); | ||
1815 | } | ||
1816 | else | ||
1817 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 | ||
1818 | { | ||
1819 | lua_Number const v{ lua_tonumber(L1, L1_i) }; | ||
1820 | DEBUGSPEW_CODE(fprintf(stderr, LUA_NUMBER_FMT "\n", v)); | ||
1821 | lua_pushnumber(L2, v); | ||
1822 | } | ||
1823 | return true; | ||
1824 | } | ||
1825 | |||
1826 | // ################################################################################################# | ||
1827 | |||
1828 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const | ||
1829 | { | ||
1830 | size_t len; | ||
1831 | char const* const s{ lua_tolstring(L1, L1_i, &len) }; | ||
1832 | DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", s)); | ||
1833 | lua_pushlstring(L2, s, len); | ||
1834 | return true; | ||
1835 | } | ||
1836 | |||
1837 | // ################################################################################################# | ||
1838 | |||
1852 | /* | 1839 | /* |
1853 | * Copies a value from 'L1' state (at index 'i') to 'L2' state. Does not remove | 1840 | * Copies a value from 'L1' state (at index 'i') to 'L2' state. Does not remove |
1854 | * the original value. | 1841 | * the original value. |
@@ -1878,7 +1865,7 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1878 | if (lua_getmetatable(L1, L1_i)) // ... mt | 1865 | if (lua_getmetatable(L1, L1_i)) // ... mt |
1879 | { | 1866 | { |
1880 | lua_getfield(L1, -1, "__lanesignore"); // ... mt ignore? | 1867 | lua_getfield(L1, -1, "__lanesignore"); // ... mt ignore? |
1881 | if( lua_isboolean(L1, -1) && lua_toboolean(L1, -1)) | 1868 | if (lua_isboolean(L1, -1) && lua_toboolean(L1, -1)) |
1882 | { | 1869 | { |
1883 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END)); | 1870 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END)); |
1884 | val_type = LuaType::NIL; | 1871 | val_type = LuaType::NIL; |
@@ -1892,81 +1879,21 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
1892 | bool ret{ true }; | 1879 | bool ret{ true }; |
1893 | switch (val_type) | 1880 | switch (val_type) |
1894 | { | 1881 | { |
1895 | /* Basic types allowed both as values, and as table keys */ | 1882 | // Basic types allowed both as values, and as table keys |
1896 | 1883 | case LuaType::BOOLEAN: ret = inter_copy_boolean(); break; | |
1897 | case LuaType::BOOLEAN: | 1884 | case LuaType::NUMBER: ret = inter_copy_number(); break; |
1898 | { | 1885 | case LuaType::STRING: ret = inter_copy_string(); break; |
1899 | int const v{ lua_toboolean(L1, L1_i) }; | 1886 | case LuaType::LIGHTUSERDATA: ret = inter_copy_lightuserdata();break; |
1900 | DEBUGSPEW_CODE( fprintf(stderr, "%s\n", v ? "true" : "false")); | 1887 | |
1901 | lua_pushboolean(L2, v); | 1888 | // The following types are not allowed as table keys |
1902 | } | 1889 | case LuaType::USERDATA: ret = inter_copy_userdata(); break; |
1903 | break; | 1890 | case LuaType::NIL: ret = inter_copy_nil(); break; |
1904 | 1891 | case LuaType::FUNCTION: ret = inter_copy_function(); break; | |
1905 | case LuaType::NUMBER: | 1892 | case LuaType::TABLE: ret = inter_copy_table(); break; |
1906 | /* LNUM patch support (keeping integer accuracy) */ | 1893 | |
1907 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 1894 | // The following types cannot be copied |
1908 | if( lua_isinteger(L1, L1_i)) | 1895 | case LuaType::CDATA: [[fallthrough]]; |
1909 | { | 1896 | case LuaType::THREAD: ret = false; break; |
1910 | lua_Integer const v{ lua_tointeger(L1, L1_i) }; | ||
1911 | DEBUGSPEW_CODE(fprintf(stderr, LUA_INTEGER_FMT "\n", v)); | ||
1912 | lua_pushinteger(L2, v); | ||
1913 | break; | ||
1914 | } | ||
1915 | else | ||
1916 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 | ||
1917 | { | ||
1918 | lua_Number const v{ lua_tonumber(L1, L1_i) }; | ||
1919 | DEBUGSPEW_CODE(fprintf(stderr, LUA_NUMBER_FMT "\n", v)); | ||
1920 | lua_pushnumber(L2, v); | ||
1921 | } | ||
1922 | break; | ||
1923 | |||
1924 | case LuaType::STRING: | ||
1925 | { | ||
1926 | size_t len; | ||
1927 | char const* const s{ lua_tolstring(L1, L1_i, &len) }; | ||
1928 | DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", s)); | ||
1929 | lua_pushlstring(L2, s, len); | ||
1930 | } | ||
1931 | break; | ||
1932 | |||
1933 | case LuaType::LIGHTUSERDATA: | ||
1934 | { | ||
1935 | void* const p{ lua_touserdata(L1, L1_i) }; | ||
1936 | DEBUGSPEW_CODE(fprintf(stderr, "%p\n", p)); | ||
1937 | lua_pushlightuserdata(L2, p); | ||
1938 | } | ||
1939 | break; | ||
1940 | |||
1941 | /* The following types are not allowed as table keys */ | ||
1942 | |||
1943 | case LuaType::USERDATA: | ||
1944 | ret = inter_copy_userdata(); | ||
1945 | break; | ||
1946 | |||
1947 | case LuaType::NIL: | ||
1948 | if (vt == VT::KEY) | ||
1949 | { | ||
1950 | ret = false; | ||
1951 | break; | ||
1952 | } | ||
1953 | lua_pushnil( L2); | ||
1954 | break; | ||
1955 | |||
1956 | case LuaType::FUNCTION: | ||
1957 | ret = inter_copy_function(); | ||
1958 | break; | ||
1959 | |||
1960 | case LuaType::TABLE: | ||
1961 | ret = inter_copy_table(); | ||
1962 | break; | ||
1963 | |||
1964 | /* The following types cannot be copied */ | ||
1965 | |||
1966 | case LuaType::CDATA: | ||
1967 | case LuaType::THREAD: | ||
1968 | ret = false; | ||
1969 | break; | ||
1970 | } | 1897 | } |
1971 | 1898 | ||
1972 | STACK_CHECK(L2, ret ? 1 : 0); | 1899 | STACK_CHECK(L2, ret ? 1 : 0); |
diff --git a/src/tools.h b/src/tools.h index 06646d3..ddf5c67 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -6,13 +6,7 @@ | |||
6 | // forwards | 6 | // forwards |
7 | class Universe; | 7 | class Universe; |
8 | 8 | ||
9 | // ################################################################################################ | 9 | // ################################################################################################# |
10 | |||
11 | #ifdef _DEBUG | ||
12 | void luaG_dump(lua_State* L); | ||
13 | #endif // _DEBUG | ||
14 | |||
15 | // ################################################################################################ | ||
16 | 10 | ||
17 | void push_registry_subtable_mode(lua_State* L, UniqueKey key_, const char* mode_); | 11 | void push_registry_subtable_mode(lua_State* L, UniqueKey key_, const char* mode_); |
18 | void push_registry_subtable(lua_State* L, UniqueKey key_); | 12 | void push_registry_subtable(lua_State* L, UniqueKey key_); |
@@ -31,12 +25,13 @@ enum class InterCopyResult | |||
31 | Error | 25 | Error |
32 | }; | 26 | }; |
33 | 27 | ||
34 | // ################################################################################################ | 28 | // ################################################################################################# |
35 | 29 | ||
36 | using CacheIndex = Unique<int>; | 30 | using CacheIndex = Unique<int>; |
37 | using SourceIndex = Unique<int>; | 31 | using SourceIndex = Unique<int>; |
38 | struct InterCopyContext | 32 | class InterCopyContext |
39 | { | 33 | { |
34 | public: | ||
40 | 35 | ||
41 | Universe* const U; | 36 | Universe* const U; |
42 | Dest const L2; | 37 | Dest const L2; |
@@ -47,35 +42,50 @@ struct InterCopyContext | |||
47 | LookupMode const mode; | 42 | LookupMode const mode; |
48 | char const* name; // that one can change when we reuse the context | 43 | char const* name; // that one can change when we reuse the context |
49 | 44 | ||
50 | [[nodiscard]] bool inter_copy_one() const; | ||
51 | |||
52 | private: | 45 | private: |
53 | 46 | ||
54 | [[nodiscard]] bool inter_copy_userdata() const; | 47 | // for use in copy_cached_func |
55 | [[nodiscard]] bool inter_copy_function() const; | ||
56 | [[nodiscard]] bool inter_copy_table() const; | ||
57 | [[nodiscard]] bool copyclone() const; | ||
58 | [[nodiscard]] bool copydeep() const; | ||
59 | [[nodiscard]] bool push_cached_metatable() const; | ||
60 | void copy_func() const; | 48 | void copy_func() const; |
49 | void lookup_native_func() const; | ||
50 | |||
51 | // for use in inter_copy_function | ||
61 | void copy_cached_func() const; | 52 | void copy_cached_func() const; |
53 | [[nodiscard]] bool lookup_table() const; | ||
54 | |||
55 | // for use in inter_copy_table | ||
62 | void inter_copy_keyvaluepair() const; | 56 | void inter_copy_keyvaluepair() const; |
57 | [[nodiscard]] bool push_cached_metatable() const; | ||
58 | |||
59 | // for use in inter_copy_userdata | ||
60 | [[nodiscard]] bool copyclone() const; | ||
61 | [[nodiscard]] bool copydeep() const; | ||
62 | |||
63 | // copying a single Lua stack item | ||
64 | [[nodiscard]] bool inter_copy_boolean() const; | ||
65 | [[nodiscard]] bool inter_copy_function() const; | ||
66 | [[nodiscard]] bool inter_copy_lightuserdata() const; | ||
67 | [[nodiscard]] bool inter_copy_nil() const; | ||
68 | [[nodiscard]] bool inter_copy_number() const; | ||
69 | [[nodiscard]] bool inter_copy_string() const; | ||
70 | [[nodiscard]] bool inter_copy_table() const; | ||
71 | [[nodiscard]] bool inter_copy_userdata() const; | ||
63 | 72 | ||
64 | public: | 73 | public: |
65 | 74 | ||
75 | [[nodiscard]] bool inter_copy_one() const; | ||
66 | [[nodiscard]] InterCopyResult inter_copy_package() const; | 76 | [[nodiscard]] InterCopyResult inter_copy_package() const; |
67 | [[nodiscard]] InterCopyResult inter_copy(int n_) const; | 77 | [[nodiscard]] InterCopyResult inter_copy(int n_) const; |
68 | [[nodiscard]] InterCopyResult inter_move(int n_) const; | 78 | [[nodiscard]] InterCopyResult inter_move(int n_) const; |
69 | }; | 79 | }; |
70 | 80 | ||
71 | // ################################################################################################ | 81 | // ################################################################################################# |
72 | 82 | ||
73 | [[nodiscard]] int luaG_nameof(lua_State* L); | 83 | [[nodiscard]] int luaG_nameof(lua_State* L); |
74 | 84 | ||
75 | void populate_func_lookup_table(lua_State* L, int _i, char const* _name); | 85 | void populate_func_lookup_table(lua_State* L, int _i, char const* _name); |
76 | void initialize_allocator_function(Universe* U, lua_State* L); | 86 | void initialize_allocator_function(Universe* U, lua_State* L); |
77 | 87 | ||
78 | // ################################################################################################ | 88 | // ################################################################################################# |
79 | 89 | ||
80 | // crc64/we of string "CONFIG_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | 90 | // crc64/we of string "CONFIG_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
81 | static constexpr UniqueKey CONFIG_REGKEY{ 0x31cd24894eae8624ull }; // registry key to access the configuration | 91 | static constexpr UniqueKey CONFIG_REGKEY{ 0x31cd24894eae8624ull }; // registry key to access the configuration |
diff --git a/src/uniquekey.h b/src/uniquekey.h index 78c0765..84553a5 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
@@ -44,8 +44,10 @@ class UniqueKey | |||
44 | } | 44 | } |
45 | void pushValue(lua_State* const L) const | 45 | void pushValue(lua_State* const L) const |
46 | { | 46 | { |
47 | STACK_CHECK_START_REL(L, 0); | ||
47 | pushKey(L); | 48 | pushKey(L); |
48 | lua_rawget(L, LUA_REGISTRYINDEX); | 49 | lua_rawget(L, LUA_REGISTRYINDEX); |
50 | STACK_CHECK(L, 1); | ||
49 | } | 51 | } |
50 | template <typename OP> | 52 | template <typename OP> |
51 | void setValue(lua_State* L, OP operation_) const | 53 | void setValue(lua_State* L, OP operation_) const |
diff --git a/src/universe.cpp b/src/universe.cpp index 4c53987..a02a5e6 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -41,7 +41,7 @@ static constexpr UniqueKey UNIVERSE_FULL_REGKEY{ 0x99CA130C09EDC074ull }; | |||
41 | // xxh64 of string "UNIVERSE_LIGHT_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | 41 | // xxh64 of string "UNIVERSE_LIGHT_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
42 | static constexpr UniqueKey UNIVERSE_LIGHT_REGKEY{ 0x3663C07C742CEB81ull }; | 42 | static constexpr UniqueKey UNIVERSE_LIGHT_REGKEY{ 0x3663C07C742CEB81ull }; |
43 | 43 | ||
44 | // ################################################################################################ | 44 | // ################################################################################################# |
45 | 45 | ||
46 | Universe::Universe() | 46 | Universe::Universe() |
47 | { | 47 | { |
@@ -70,13 +70,13 @@ Universe::Universe() | |||
70 | #endif // PLATFORM_LINUX | 70 | #endif // PLATFORM_LINUX |
71 | } | 71 | } |
72 | 72 | ||
73 | // ################################################################################################ | 73 | // ################################################################################################# |
74 | 74 | ||
75 | // only called from the master state | 75 | // only called from the master state |
76 | Universe* universe_create(lua_State* L) | 76 | Universe* universe_create(lua_State* L) |
77 | { | 77 | { |
78 | ASSERT_L(universe_get(L) == nullptr); | 78 | ASSERT_L(universe_get(L) == nullptr); |
79 | Universe* const U = static_cast<Universe*>(lua_newuserdatauv(L, sizeof(Universe), 0)); // universe | 79 | Universe* const U{ lua_newuserdatauv<Universe>(L, 0) }; // universe |
80 | U->Universe::Universe(); | 80 | U->Universe::Universe(); |
81 | STACK_CHECK_START_REL(L, 1); | 81 | STACK_CHECK_START_REL(L, 1); |
82 | UNIVERSE_FULL_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 82 | UNIVERSE_FULL_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
@@ -85,7 +85,7 @@ Universe* universe_create(lua_State* L) | |||
85 | return U; | 85 | return U; |
86 | } | 86 | } |
87 | 87 | ||
88 | // ################################################################################################ | 88 | // ################################################################################################# |
89 | 89 | ||
90 | void universe_store(lua_State* L, Universe* U) | 90 | void universe_store(lua_State* L, Universe* U) |
91 | { | 91 | { |
@@ -95,7 +95,7 @@ void universe_store(lua_State* L, Universe* U) | |||
95 | STACK_CHECK(L, 0); | 95 | STACK_CHECK(L, 0); |
96 | } | 96 | } |
97 | 97 | ||
98 | // ################################################################################################ | 98 | // ################################################################################################# |
99 | 99 | ||
100 | Universe* universe_get(lua_State* L) | 100 | Universe* universe_get(lua_State* L) |
101 | { | 101 | { |
diff --git a/src/universe.h b/src/universe.h index eb85133..320c400 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -13,7 +13,7 @@ extern "C" { | |||
13 | 13 | ||
14 | #include <mutex> | 14 | #include <mutex> |
15 | 15 | ||
16 | // ################################################################################################ | 16 | // ################################################################################################# |
17 | 17 | ||
18 | // forwards | 18 | // forwards |
19 | struct DeepPrelude; | 19 | struct DeepPrelude; |
@@ -25,7 +25,7 @@ class Lane; | |||
25 | */ | 25 | */ |
26 | #define HAVE_LANE_TRACKING() 1 | 26 | #define HAVE_LANE_TRACKING() 1 |
27 | 27 | ||
28 | // ################################################################################################ | 28 | // ################################################################################################# |
29 | 29 | ||
30 | // everything we need to provide to lua_newstate() | 30 | // everything we need to provide to lua_newstate() |
31 | class AllocatorDefinition | 31 | class AllocatorDefinition |
@@ -35,6 +35,7 @@ class AllocatorDefinition | |||
35 | lua_Alloc m_allocF{ nullptr }; | 35 | lua_Alloc m_allocF{ nullptr }; |
36 | void* m_allocUD{ nullptr }; | 36 | void* m_allocUD{ nullptr }; |
37 | 37 | ||
38 | [[nodiscard]] static void* operator new(size_t size_) noexcept = delete; // can't create one outside of a Lua state | ||
38 | [[nodiscard]] static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv(L, size_, 0); } | 39 | [[nodiscard]] static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv(L, size_, 0); } |
39 | // always embedded somewhere else or "in-place constructed" as a full userdata | 40 | // always embedded somewhere else or "in-place constructed" as a full userdata |
40 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 41 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
@@ -72,7 +73,7 @@ class AllocatorDefinition | |||
72 | } | 73 | } |
73 | }; | 74 | }; |
74 | 75 | ||
75 | // ################################################################################################ | 76 | // ################################################################################################# |
76 | 77 | ||
77 | // mutex-protected allocator for use with Lua states that share a non-threadsafe allocator | 78 | // mutex-protected allocator for use with Lua states that share a non-threadsafe allocator |
78 | class ProtectedAllocator : public AllocatorDefinition | 79 | class ProtectedAllocator : public AllocatorDefinition |
@@ -115,7 +116,7 @@ class ProtectedAllocator : public AllocatorDefinition | |||
115 | } | 116 | } |
116 | }; | 117 | }; |
117 | 118 | ||
118 | // ################################################################################################ | 119 | // ################################################################################################# |
119 | 120 | ||
120 | // everything regarding the Lanes universe is stored in that global structure | 121 | // everything regarding the Lanes universe is stored in that global structure |
121 | // held as a full userdata in the master Lua state that required it for the first time | 122 | // held as a full userdata in the master Lua state that required it for the first time |
@@ -183,13 +184,13 @@ class Universe | |||
183 | Universe& operator=(Universe&&) = delete; | 184 | Universe& operator=(Universe&&) = delete; |
184 | }; | 185 | }; |
185 | 186 | ||
186 | // ################################################################################################ | 187 | // ################################################################################################# |
187 | 188 | ||
188 | [[nodiscard]] Universe* universe_get(lua_State* L); | 189 | [[nodiscard]] Universe* universe_get(lua_State* L); |
189 | [[nodiscard]] Universe* universe_create(lua_State* L); | 190 | [[nodiscard]] Universe* universe_create(lua_State* L); |
190 | void universe_store(lua_State* L, Universe* U); | 191 | void universe_store(lua_State* L, Universe* U); |
191 | 192 | ||
192 | // ################################################################################################ | 193 | // ################################################################################################# |
193 | 194 | ||
194 | #if USE_DEBUG_SPEW() | 195 | #if USE_DEBUG_SPEW() |
195 | class DebugSpewIndentScope | 196 | class DebugSpewIndentScope |