diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-10-08 18:42:39 +0200 |
commit | 16b5070c0cd56e10c5074eb9903dbc3ae4e15a61 (patch) | |
tree | f6d5cdb74b505e13aa3261f7ab6192da0133b7b9 /src/lane.cpp | |
parent | e939e5e6a894a042d3301e47faa05264445f27f6 (diff) | |
download | lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.gz lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.bz2 lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.zip |
Sprinkling StackIndex all over the place
Diffstat (limited to 'src/lane.cpp')
-rw-r--r-- | src/lane.cpp | 140 |
1 files changed, 71 insertions, 69 deletions
diff --git a/src/lane.cpp b/src/lane.cpp index baba0fa..d4d409f 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -47,7 +47,7 @@ static constexpr UniqueKey kCachedTostring{ 0xAB5EA23BCEA0C35Cull }; | |||
47 | // lane:get_threadname() | 47 | // lane:get_threadname() |
48 | static LUAG_FUNC(get_threadname) | 48 | static LUAG_FUNC(get_threadname) |
49 | { | 49 | { |
50 | Lane* const _lane{ ToLane(L_, 1) }; | 50 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
51 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); | 51 | luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); |
52 | luaG_pushstring(L_, _lane->getDebugName()); | 52 | luaG_pushstring(L_, _lane->getDebugName()); |
53 | return 1; | 53 | return 1; |
@@ -70,7 +70,7 @@ static LUAG_FUNC(set_finalizer) | |||
70 | // Get the current finalizer table (if any), create one if it doesn't exist | 70 | // Get the current finalizer table (if any), create one if it doesn't exist |
71 | std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} | 71 | std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} |
72 | // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. | 72 | // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. |
73 | int const _idx{ static_cast<int>(lua_rawlen(L_, -1) + 1) }; | 73 | int const _idx{ static_cast<int>(lua_rawlen(L_, kIdxTop) + 1) }; |
74 | lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer | 74 | lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer |
75 | lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers} | 75 | lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers} |
76 | // no need to adjust the stack, Lua does this for us | 76 | // no need to adjust the stack, Lua does this for us |
@@ -85,12 +85,12 @@ static LUAG_FUNC(set_finalizer) | |||
85 | static LUAG_FUNC(lane_threadname) | 85 | static LUAG_FUNC(lane_threadname) |
86 | { | 86 | { |
87 | // C s_lane structure is a light userdata upvalue | 87 | // C s_lane structure is a light userdata upvalue |
88 | Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) }; | 88 | Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, StackIndex{ lua_upvalueindex(1) }) }; |
89 | LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state | 89 | LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state |
90 | if (lua_gettop(L_) == 1) { | 90 | if (lua_gettop(L_) == 1) { |
91 | lua_settop(L_, 1); | 91 | lua_settop(L_, 1); |
92 | STACK_CHECK_START_REL(L_, 0); | 92 | STACK_CHECK_START_REL(L_, 0); |
93 | _lane->changeDebugName(-1); | 93 | _lane->changeDebugName(kIdxTop); |
94 | STACK_CHECK(L_, 0); | 94 | STACK_CHECK(L_, 0); |
95 | return 0; | 95 | return 0; |
96 | } else if (lua_gettop(L_) == 0) { | 96 | } else if (lua_gettop(L_) == 0) { |
@@ -113,19 +113,19 @@ static LUAG_FUNC(lane_threadname) | |||
113 | // | 113 | // |
114 | static LUAG_FUNC(thread_join) | 114 | static LUAG_FUNC(thread_join) |
115 | { | 115 | { |
116 | Lane* const _lane{ ToLane(L_, 1) }; | 116 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; |
117 | 117 | ||
118 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 118 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
119 | if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | 119 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion |
120 | lua_Duration const duration{ lua_tonumber(L_, 2) }; | 120 | lua_Duration const duration{ lua_tonumber(L_, 2) }; |
121 | if (duration.count() >= 0.0) { | 121 | if (duration.count() >= 0.0) { |
122 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); | 122 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); |
123 | } else { | 123 | } else { |
124 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | 124 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); |
125 | } | 125 | } |
126 | 126 | ||
127 | } else if (!lua_isnoneornil(L_, 2)) { | 127 | } else if (!lua_isnoneornil(L_, 2)) { |
128 | raise_luaL_argerror(L_, 2, "incorrect duration type"); | 128 | raise_luaL_argerror(L_, StackIndex{ 2 }, "incorrect duration type"); |
129 | } | 129 | } |
130 | 130 | ||
131 | lua_settop(L_, 1); // L_: lane | 131 | lua_settop(L_, 1); // L_: lane |
@@ -150,7 +150,7 @@ static LUAG_FUNC(thread_join) | |||
150 | if (_stored == 0) { | 150 | if (_stored == 0) { |
151 | raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing"); | 151 | raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing"); |
152 | } | 152 | } |
153 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 153 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
154 | for (int _i = 2; _i <= _stored; ++_i) { | 154 | for (int _i = 2; _i <= _stored; ++_i) { |
155 | lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N | 155 | lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N |
156 | } | 156 | } |
@@ -163,7 +163,7 @@ static LUAG_FUNC(thread_join) | |||
163 | case Lane::Error: | 163 | case Lane::Error: |
164 | { | 164 | { |
165 | LUA_ASSERT(L_, _stored == 2 || _stored == 3); | 165 | LUA_ASSERT(L_, _stored == 2 || _stored == 3); |
166 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 166 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
167 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error> | 167 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error> |
168 | lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil | 168 | lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil |
169 | if (lua_isnil(L_, -1)) { | 169 | if (lua_isnil(L_, -1)) { |
@@ -178,11 +178,11 @@ static LUAG_FUNC(thread_join) | |||
178 | 178 | ||
179 | case Lane::Cancelled: | 179 | case Lane::Cancelled: |
180 | LUA_ASSERT(L_, _stored == 2); | 180 | LUA_ASSERT(L_, _stored == 2); |
181 | lua_getiuservalue(L_, 1, 1); // L_: lane {uv} | 181 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv} |
182 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error | 182 | lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error |
183 | lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil | 183 | lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil |
184 | lua_replace(L_, -3); // L_: lane nil cancel_error | 184 | lua_replace(L_, -3); // L_: lane nil cancel_error |
185 | LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, -1)); | 185 | LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, kIdxTop)); |
186 | _ret = 2; | 186 | _ret = 2; |
187 | break; | 187 | break; |
188 | 188 | ||
@@ -199,8 +199,8 @@ static LUAG_FUNC(thread_join) | |||
199 | 199 | ||
200 | LUAG_FUNC(thread_resume) | 200 | LUAG_FUNC(thread_resume) |
201 | { | 201 | { |
202 | static constexpr int kSelf{ 1 }; | 202 | static constexpr StackIndex kIdxSelf{ 1 }; |
203 | Lane* const _lane{ ToLane(L_, kSelf) }; | 203 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
204 | lua_State* const _L2{ _lane->L }; | 204 | lua_State* const _L2{ _lane->L }; |
205 | 205 | ||
206 | // wait until the lane yields | 206 | // wait until the lane yields |
@@ -225,7 +225,7 @@ LUAG_FUNC(thread_resume) | |||
225 | STACK_CHECK_START_ABS(_L2, _nresults); | 225 | STACK_CHECK_START_ABS(_L2, _nresults); |
226 | 226 | ||
227 | // clear any fetched returned values that we might have stored previously | 227 | // clear any fetched returned values that we might have stored previously |
228 | _lane->resetResultsStorage(L_, 1); | 228 | _lane->resetResultsStorage(L_, kIdxSelf); |
229 | 229 | ||
230 | // to retrieve the yielded value of the coroutine on our stack | 230 | // to retrieve the yielded value of the coroutine on our stack |
231 | InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; | 231 | InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; |
@@ -254,9 +254,9 @@ LUAG_FUNC(thread_resume) | |||
254 | // Else If key is found in the environment, return it | 254 | // Else If key is found in the environment, return it |
255 | static int thread_index_number(lua_State* L_) | 255 | static int thread_index_number(lua_State* L_) |
256 | { | 256 | { |
257 | static constexpr int kSelf{ 1 }; | 257 | static constexpr StackIndex kIdxSelf{ 1 }; |
258 | 258 | ||
259 | Lane* const _lane{ ToLane(L_, kSelf) }; | 259 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
260 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n | 260 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n |
261 | int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; | 261 | int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; |
262 | lua_pop(L_, 1); // L_: lane | 262 | lua_pop(L_, 1); // L_: lane |
@@ -284,13 +284,13 @@ static int thread_index_number(lua_State* L_) | |||
284 | // Else raise an error | 284 | // Else raise an error |
285 | static int thread_index_string(lua_State* L_) | 285 | static int thread_index_string(lua_State* L_) |
286 | { | 286 | { |
287 | static constexpr int kSelf{ 1 }; | 287 | static constexpr StackIndex kIdxSelf{ 1 }; |
288 | static constexpr int kKey{ 2 }; | 288 | static constexpr StackIndex kIdxKey{ 2 }; |
289 | 289 | ||
290 | Lane* const _lane{ ToLane(L_, kSelf) }; | 290 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
291 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" | 291 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" |
292 | 292 | ||
293 | std::string_view const _keystr{ luaG_tostring(L_, kKey) }; | 293 | std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) }; |
294 | lua_settop(L_, 2); // keep only our original arguments on the stack | 294 | lua_settop(L_, 2); // keep only our original arguments on the stack |
295 | if (_keystr == "status") { | 295 | if (_keystr == "status") { |
296 | _lane->pushStatusString(L_); // L_: lane "key" "<status>" | 296 | _lane->pushStatusString(L_); // L_: lane "key" "<status>" |
@@ -301,7 +301,7 @@ static int thread_index_string(lua_State* L_) | |||
301 | return 1; | 301 | return 1; |
302 | } | 302 | } |
303 | // return self.metatable[key] | 303 | // return self.metatable[key] |
304 | lua_getmetatable(L_, kSelf); // L_: lane "key" mt | 304 | lua_getmetatable(L_, kIdxSelf); // L_: lane "key" mt |
305 | lua_replace(L_, -3); // L_: mt "key" | 305 | lua_replace(L_, -3); // L_: mt "key" |
306 | lua_rawget(L_, -2); // L_: mt value | 306 | lua_rawget(L_, -2); // L_: mt value |
307 | // only "cancel" and "join" are registered as functions, any other string will raise an error | 307 | // only "cancel" and "join" are registered as functions, any other string will raise an error |
@@ -316,9 +316,9 @@ static int thread_index_string(lua_State* L_) | |||
316 | // lane:__index(key,usr) -> value | 316 | // lane:__index(key,usr) -> value |
317 | static LUAG_FUNC(thread_index) | 317 | static LUAG_FUNC(thread_index) |
318 | { | 318 | { |
319 | static constexpr int kSelf{ 1 }; | 319 | static constexpr StackIndex kIdxSelf{ 1 }; |
320 | static constexpr int kKey{ 2 }; | 320 | static constexpr StackIndex kKey{ 2 }; |
321 | Lane* const _lane{ ToLane(L_, kSelf) }; | 321 | Lane* const _lane{ ToLane(L_, kIdxSelf) }; |
322 | LUA_ASSERT(L_, lua_gettop(L_) == 2); | 322 | LUA_ASSERT(L_, lua_gettop(L_) == 2); |
323 | 323 | ||
324 | switch (luaG_type(L_, kKey)) { | 324 | switch (luaG_type(L_, kKey)) { |
@@ -329,17 +329,17 @@ static LUAG_FUNC(thread_index) | |||
329 | return thread_index_string(L_); // stack modification is undefined, returned value is at the top | 329 | return thread_index_string(L_); // stack modification is undefined, returned value is at the top |
330 | 330 | ||
331 | default: // unknown key | 331 | default: // unknown key |
332 | lua_getmetatable(L_, kSelf); // L_: mt | 332 | lua_getmetatable(L_, kIdxSelf); // L_: mt |
333 | kCachedError.pushKey(L_); // L_: mt kCachedError | 333 | kCachedError.pushKey(L_); // L_: mt kCachedError |
334 | lua_rawget(L_, -2); // L_: mt error() | 334 | lua_rawget(L_, -2); // L_: mt error() |
335 | if (luaG_type(L_, -1) != LuaType::FUNCTION) { | 335 | if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) { |
336 | raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, -1).data()); | 336 | raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); |
337 | } | 337 | } |
338 | luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " | 338 | luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " |
339 | kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring | 339 | kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring |
340 | lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring() | 340 | lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring() |
341 | if (luaG_type(L_, -1) != LuaType::FUNCTION) { | 341 | if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) { |
342 | raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, -1).data()); | 342 | raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); |
343 | } | 343 | } |
344 | lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k | 344 | lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k |
345 | lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" | 345 | lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" |
@@ -417,7 +417,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
417 | 417 | ||
418 | // Don't do stack survey for cancelled lanes. | 418 | // Don't do stack survey for cancelled lanes. |
419 | // | 419 | // |
420 | if (kCancelError.equals(L_, 1)) { | 420 | if (kCancelError.equals(L_, StackIndex{ 1 })) { |
421 | return 1; // just pass on | 421 | return 1; // just pass on |
422 | } | 422 | } |
423 | 423 | ||
@@ -436,6 +436,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
436 | // table of { "sourcefile.lua:<line>", ... } | 436 | // table of { "sourcefile.lua:<line>", ... } |
437 | // | 437 | // |
438 | lua_newtable(L_); // L_: some_error {} | 438 | lua_newtable(L_); // L_: some_error {} |
439 | StackIndex const kIdxTraceTbl{ luaG_absindex(L_, kIdxTop) }; | ||
439 | 440 | ||
440 | // Best to start from level 1, but in some cases it might be a C function | 441 | // Best to start from level 1, but in some cases it might be a C function |
441 | // and we don't get '.currentline' for that. It's okay - just keep level | 442 | // and we don't get '.currentline' for that. It's okay - just keep level |
@@ -446,27 +447,27 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
446 | lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); | 447 | lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); |
447 | if (_extended) { | 448 | if (_extended) { |
448 | lua_newtable(L_); // L_: some_error {} {} | 449 | lua_newtable(L_); // L_: some_error {} {} |
449 | 450 | StackIndex const kIdxFrameTbl{ luaG_absindex(L_, kIdxTop) }; | |
450 | lua_pushstring(L_, _ar.source); // L_: some_error {} {} source | 451 | lua_pushstring(L_, _ar.source); // L_: some_error {} {} source |
451 | luaG_setfield(L_, -2, std::string_view{ "source" }); // L_: some_error {} {} | 452 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "source" }); // L_: some_error {} {} |
452 | 453 | ||
453 | lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline | 454 | lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline |
454 | luaG_setfield(L_, -2, std::string_view{ "currentline" }); // L_: some_error {} {} | 455 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "currentline" }); // L_: some_error {} {} |
455 | 456 | ||
456 | lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name | 457 | lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name |
457 | luaG_setfield(L_, -2, std::string_view{ "name" }); // L_: some_error {} {} | 458 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "name" }); // L_: some_error {} {} |
458 | 459 | ||
459 | lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat | 460 | lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat |
460 | luaG_setfield(L_, -2, std::string_view{ "namewhat" }); // L_: some_error {} {} | 461 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "namewhat" }); // L_: some_error {} {} |
461 | 462 | ||
462 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what | 463 | lua_pushstring(L_, _ar.what); // L_: some_error {} {} what |
463 | luaG_setfield(L_, -2, std::string_view{ "what" }); // L_: some_error {} {} | 464 | luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "what" }); // L_: some_error {} {} |
464 | } else if (_ar.currentline > 0) { | 465 | } else if (_ar.currentline > 0) { |
465 | luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" | 466 | luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" |
466 | } else { | 467 | } else { |
467 | luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" | 468 | luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" |
468 | } | 469 | } |
469 | lua_rawseti(L_, -2, static_cast<lua_Integer>(_n)); // L_: some_error {} | 470 | lua_rawseti(L_, kIdxTraceTbl, static_cast<lua_Integer>(_n)); // L_: some_error {} |
470 | } | 471 | } |
471 | 472 | ||
472 | // store the stack trace table in the registry | 473 | // store the stack trace table in the registry |
@@ -480,10 +481,10 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
480 | // ########################################## Finalizer ############################################ | 481 | // ########################################## Finalizer ############################################ |
481 | // ################################################################################################# | 482 | // ################################################################################################# |
482 | 483 | ||
483 | [[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] int const stk_base_) | 484 | [[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] StackIndex const stk_base_) |
484 | { | 485 | { |
485 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry | 486 | // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry |
486 | int const _top{ lua_gettop(L_) }; | 487 | StackIndex const _top{ lua_gettop(L_) }; |
487 | switch (rc_) { | 488 | switch (rc_) { |
488 | case LuaError::OK: // no error, body return values are on the stack | 489 | case LuaError::OK: // no error, body return values are on the stack |
489 | break; | 490 | break; |
@@ -499,7 +500,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
499 | 500 | ||
500 | // For cancellation the error message is kCancelError, and a stack trace isn't placed | 501 | // For cancellation the error message is kCancelError, and a stack trace isn't placed |
501 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | 502 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table |
502 | LUA_ASSERT(L_, luaG_type(L_, 1 + stk_base_) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); | 503 | LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 + stk_base_ }) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); |
503 | // Just leaving the stack trace table on the stack is enough to get it through to the master. | 504 | // Just leaving the stack trace table on the stack is enough to get it through to the master. |
504 | } else { | 505 | } else { |
505 | // any kind of error can be thrown with error(), or through a lane/linda cancellation | 506 | // any kind of error can be thrown with error(), or through a lane/linda cancellation |
@@ -544,7 +545,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
544 | 545 | ||
545 | STACK_GROW(_L, 5); | 546 | STACK_GROW(_L, 5); |
546 | 547 | ||
547 | int const _finalizers{ lua_gettop(_L) }; | 548 | StackIndex const _finalizers{ lua_gettop(_L) }; |
548 | // always push something as error handler, to have the same stack structure | 549 | // always push something as error handler, to have the same stack structure |
549 | int const _error_handler{ (errorTraceLevel_ != Lane::Minimal) | 550 | int const _error_handler{ (errorTraceLevel_ != Lane::Minimal) |
550 | ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L)) | 551 | ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L)) |
@@ -581,7 +582,8 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
581 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace | 582 | // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace |
582 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? | 583 | _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? |
583 | if (_rc != LuaError::OK) { | 584 | if (_rc != LuaError::OK) { |
584 | _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, lua_gettop(_L)); // _L: ... finalizers error_handler() err_msg2? trace | 585 | StackIndex const _top{ lua_gettop(_L) }; |
586 | _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, _top); // _L: ... finalizers error_handler() err_msg2? trace | ||
585 | // If one finalizer fails, don't run the others. Return this | 587 | // If one finalizer fails, don't run the others. Return this |
586 | // as the 'real' error, replacing what we could have had (or not) | 588 | // as the 'real' error, replacing what we could have had (or not) |
587 | // from the actual code. | 589 | // from the actual code. |
@@ -610,7 +612,7 @@ int Lane::LuaErrorHandler(lua_State* L_) | |||
610 | 612 | ||
611 | if (lane_->isCoroutine()) { | 613 | if (lane_->isCoroutine()) { |
612 | // only the coroutine thread should remain on the master state when we are done | 614 | // only the coroutine thread should remain on the master state when we are done |
613 | LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, 1) == LuaType::THREAD); | 615 | LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, StackIndex{ 1 }) == LuaType::THREAD); |
614 | } | 616 | } |
615 | 617 | ||
616 | return _rc; | 618 | return _rc; |
@@ -670,7 +672,7 @@ static void PrepareLaneHelpers(Lane* const lane_) | |||
670 | lua_State* const _L{ lane_->L }; | 672 | lua_State* const _L{ lane_->L }; |
671 | // Tie "set_finalizer()" to the state | 673 | // Tie "set_finalizer()" to the state |
672 | lua_pushcfunction(_L, LG_set_finalizer); | 674 | lua_pushcfunction(_L, LG_set_finalizer); |
673 | tools::PopulateFuncLookupTable(_L, -1, "set_finalizer"); | 675 | tools::PopulateFuncLookupTable(_L, kIdxTop, "set_finalizer"); |
674 | lua_setglobal(_L, "set_finalizer"); | 676 | lua_setglobal(_L, "set_finalizer"); |
675 | 677 | ||
676 | // Tie "lane_threadname()" to the state | 678 | // Tie "lane_threadname()" to the state |
@@ -681,7 +683,7 @@ static void PrepareLaneHelpers(Lane* const lane_) | |||
681 | 683 | ||
682 | // Tie "cancel_test()" to the state | 684 | // Tie "cancel_test()" to the state |
683 | lua_pushcfunction(_L, LG_cancel_test); | 685 | lua_pushcfunction(_L, LG_cancel_test); |
684 | tools::PopulateFuncLookupTable(_L, -1, "cancel_test"); | 686 | tools::PopulateFuncLookupTable(_L, kIdxTop, "cancel_test"); |
685 | lua_setglobal(_L, "cancel_test"); | 687 | lua_setglobal(_L, "cancel_test"); |
686 | } | 688 | } |
687 | 689 | ||
@@ -752,7 +754,7 @@ static void lane_main(Lane* const lane_) | |||
752 | } | 754 | } |
753 | 755 | ||
754 | // in case of error and if it exists, fetch stack trace from registry and push it | 756 | // in case of error and if it exists, fetch stack trace from registry and push it |
755 | lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] | 757 | lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, StackIndex{ 1 }); // L: retvals|error [trace] |
756 | 758 | ||
757 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); | 759 | DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); |
758 | // Call finalizers, if the script has set them up. | 760 | // Call finalizers, if the script has set them up. |
@@ -782,7 +784,7 @@ static void lane_main(Lane* const lane_) | |||
782 | } | 784 | } |
783 | 785 | ||
784 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them | 786 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them |
785 | Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, 1) ? Lane::Cancelled : Lane::Error }; | 787 | Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, StackIndex{ 1 }) ? Lane::Cancelled : Lane::Error }; |
786 | // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too | 788 | // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too |
787 | std::lock_guard _guard{ lane_->doneMutex }; | 789 | std::lock_guard _guard{ lane_->doneMutex }; |
788 | lane_->status = _st; | 790 | lane_->status = _st; |
@@ -794,7 +796,7 @@ static void lane_main(Lane* const lane_) | |||
794 | #if LUA_VERSION_NUM >= 504 | 796 | #if LUA_VERSION_NUM >= 504 |
795 | static LUAG_FUNC(lane_close) | 797 | static LUAG_FUNC(lane_close) |
796 | { | 798 | { |
797 | [[maybe_unused]] Lane* const _lane{ ToLane(L_, 1) }; // L_: lane err|nil | 799 | [[maybe_unused]] Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane err|nil |
798 | // drop the error if any | 800 | // drop the error if any |
799 | lua_settop(L_, 1); // L_: lane | 801 | lua_settop(L_, 1); // L_: lane |
800 | 802 | ||
@@ -823,10 +825,10 @@ static LUAG_FUNC(lane_close) | |||
823 | static LUAG_FUNC(lane_gc) | 825 | static LUAG_FUNC(lane_gc) |
824 | { | 826 | { |
825 | bool _have_gc_cb{ false }; | 827 | bool _have_gc_cb{ false }; |
826 | Lane* const _lane{ ToLane(L_, 1) }; // L_: ud | 828 | Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: ud |
827 | 829 | ||
828 | // if there a gc callback? | 830 | // if there a gc callback? |
829 | lua_getiuservalue(L_, 1, 1); // L_: ud uservalue | 831 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: ud uservalue |
830 | kLaneGC.pushKey(L_); // L_: ud uservalue __gc | 832 | kLaneGC.pushKey(L_); // L_: ud uservalue __gc |
831 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil | 833 | lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil |
832 | if (!lua_isnil(L_, -1)) { | 834 | if (!lua_isnil(L_, -1)) { |
@@ -932,7 +934,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
932 | 934 | ||
933 | // ################################################################################################# | 935 | // ################################################################################################# |
934 | 936 | ||
935 | [[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) | 937 | [[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) |
936 | { | 938 | { |
937 | cancelRequest = CancelRequest::Hard; // it's now signaled to stop | 939 | cancelRequest = CancelRequest::Hard; // it's now signaled to stop |
938 | // lane_->thread.get_stop_source().request_stop(); | 940 | // lane_->thread.get_stop_source().request_stop(); |
@@ -949,7 +951,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
949 | 951 | ||
950 | // ################################################################################################# | 952 | // ################################################################################################# |
951 | 953 | ||
952 | [[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) | 954 | [[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_) |
953 | { | 955 | { |
954 | cancelRequest = CancelRequest::Soft; // it's now signaled to stop | 956 | cancelRequest = CancelRequest::Soft; // it's now signaled to stop |
955 | // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own | 957 | // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own |
@@ -966,9 +968,9 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono: | |||
966 | 968 | ||
967 | // ################################################################################################# | 969 | // ################################################################################################# |
968 | 970 | ||
969 | void Lane::changeDebugName(int const nameIdx_) | 971 | void Lane::changeDebugName(StackIndex const nameIdx_) |
970 | { | 972 | { |
971 | int const _nameIdx{ luaG_absindex(L, nameIdx_) }; | 973 | StackIndex const _nameIdx{ luaG_absindex(L, nameIdx_) }; |
972 | luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... | 974 | luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... |
973 | STACK_CHECK_START_REL(L, 0); | 975 | STACK_CHECK_START_REL(L, 0); |
974 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... | 976 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... |
@@ -1064,11 +1066,11 @@ void Lane::pushStatusString(lua_State* L_) const | |||
1064 | 1066 | ||
1065 | void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | 1067 | void Lane::pushIndexedResult(lua_State* const L_, int const key_) const |
1066 | { | 1068 | { |
1067 | static constexpr int kSelf{ 1 }; | 1069 | static constexpr StackIndex kIdxSelf{ 1 }; |
1068 | LUA_ASSERT(L_, ToLane(L_, kSelf) == this); // L_: lane ... | 1070 | LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); // L_: lane ... |
1069 | STACK_GROW(L_, 3); | 1071 | STACK_GROW(L_, 3); |
1070 | 1072 | ||
1071 | lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} | 1073 | lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv} |
1072 | if (status != Lane::Error) { | 1074 | if (status != Lane::Error) { |
1073 | lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i] | 1075 | lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i] |
1074 | lua_remove(L_, -2); // L_: lane ... uv[i] | 1076 | lua_remove(L_, -2); // L_: lane ... uv[i] |
@@ -1083,7 +1085,7 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | |||
1083 | lua_remove(L_, -2); // L_: lane ... <error> | 1085 | lua_remove(L_, -2); // L_: lane ... <error> |
1084 | return; | 1086 | return; |
1085 | } | 1087 | } |
1086 | lua_getmetatable(L_, kSelf); // L_: lane ... {uv} <error> {mt} | 1088 | lua_getmetatable(L_, kIdxSelf); // L_: lane ... {uv} <error> {mt} |
1087 | lua_replace(L_, -3); // L_: lane ... {mt} <error> | 1089 | lua_replace(L_, -3); // L_: lane ... {mt} <error> |
1088 | // Note: Lua 5.1 interpreter is not prepared to show | 1090 | // Note: Lua 5.1 interpreter is not prepared to show |
1089 | // non-string errors, so we use 'tostring()' here | 1091 | // non-string errors, so we use 'tostring()' here |
@@ -1127,11 +1129,11 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const | |||
1127 | 1129 | ||
1128 | // replace the current uservalue (a table holding the returned values of the lane body) | 1130 | // replace the current uservalue (a table holding the returned values of the lane body) |
1129 | // by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost | 1131 | // by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost |
1130 | void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_) | 1132 | void Lane::resetResultsStorage(lua_State* const L_, StackIndex const self_idx_) |
1131 | { | 1133 | { |
1132 | STACK_GROW(L_, 4); | 1134 | STACK_GROW(L_, 4); |
1133 | STACK_CHECK_START_REL(L_, 0); | 1135 | STACK_CHECK_START_REL(L_, 0); |
1134 | int const _self_idx{ luaG_absindex(L_, self_idx_) }; | 1136 | StackIndex const _self_idx{ luaG_absindex(L_, self_idx_) }; |
1135 | LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... | 1137 | LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... |
1136 | // create the new table | 1138 | // create the new table |
1137 | lua_newtable(L_); // L_: ... self ... {} | 1139 | lua_newtable(L_); // L_: ... self ... {} |
@@ -1154,12 +1156,12 @@ void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_) | |||
1154 | // ################################################################################################# | 1156 | // ################################################################################################# |
1155 | 1157 | ||
1156 | // intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed | 1158 | // intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed |
1157 | void Lane::securizeDebugName(lua_State* L_) | 1159 | void Lane::securizeDebugName(lua_State* const L_) |
1158 | { | 1160 | { |
1159 | STACK_CHECK_START_REL(L_, 0); | 1161 | STACK_CHECK_START_REL(L_, 0); |
1160 | STACK_GROW(L_, 3); | 1162 | STACK_GROW(L_, 3); |
1161 | // a Lane's uservalue should be a table | 1163 | // a Lane's uservalue should be a table |
1162 | lua_getiuservalue(L_, 1, 1); // L_: lane ... {uv} | 1164 | lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane ... {uv} |
1163 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 1165 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
1164 | // we don't care about the actual key, so long as it's unique and can't collide with anything. | 1166 | // we don't care about the actual key, so long as it's unique and can't collide with anything. |
1165 | lua_newtable(L_); // L_: lane ... {uv} {} | 1167 | lua_newtable(L_); // L_: lane ... {uv} {} |
@@ -1174,7 +1176,7 @@ void Lane::securizeDebugName(lua_State* L_) | |||
1174 | 1176 | ||
1175 | // ################################################################################################# | 1177 | // ################################################################################################# |
1176 | 1178 | ||
1177 | void Lane::startThread(int priority_) | 1179 | void Lane::startThread(int const priority_) |
1178 | { | 1180 | { |
1179 | thread = std::thread([this]() { lane_main(this); }); | 1181 | thread = std::thread([this]() { lane_main(this); }); |
1180 | if (priority_ != kThreadPrioDefault) { | 1182 | if (priority_ != kThreadPrioDefault) { |
@@ -1189,12 +1191,12 @@ void Lane::startThread(int priority_) | |||
1189 | // t[i] = result #i | 1191 | // t[i] = result #i |
1190 | int Lane::storeResults(lua_State* const L_) | 1192 | int Lane::storeResults(lua_State* const L_) |
1191 | { | 1193 | { |
1192 | static constexpr int kSelf{ 1 }; | 1194 | static constexpr StackIndex kIdxSelf{ 1 }; |
1193 | LUA_ASSERT(L_, ToLane(L_, kSelf) == this); | 1195 | LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); |
1194 | 1196 | ||
1195 | STACK_CHECK_START_REL(L_, 0); | 1197 | STACK_CHECK_START_REL(L_, 0); |
1196 | lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} | 1198 | lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv} |
1197 | int const _tidx{ lua_gettop(L_) }; | 1199 | StackIndex const _tidx{ lua_gettop(L_) }; |
1198 | 1200 | ||
1199 | int _stored{}; | 1201 | int _stored{}; |
1200 | if (nresults == 0) { | 1202 | if (nresults == 0) { |
@@ -1252,7 +1254,7 @@ int Lane::storeResults(lua_State* const L_) | |||
1252 | case Lane::Cancelled: | 1254 | case Lane::Cancelled: |
1253 | _stored = 2; | 1255 | _stored = 2; |
1254 | // we should have a single value, kCancelError, in the stack of L | 1256 | // we should have a single value, kCancelError, in the stack of L |
1255 | LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, 1)); | 1257 | LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, StackIndex{ 1 })); |
1256 | // store nil, cancel_error in the results | 1258 | // store nil, cancel_error in the results |
1257 | lua_pushnil(L_); // L_: lane ... {uv} nil | 1259 | lua_pushnil(L_); // L_: lane ... {uv} nil |
1258 | lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv} | 1260 | lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv} |