diff options
-rw-r--r-- | docs/index.html | 20 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 17 | ||||
-rw-r--r-- | src/lane.cpp | 20 | ||||
-rw-r--r-- | src/lane.h | 11 | ||||
-rw-r--r-- | src/lanes.cpp | 3 | ||||
-rw-r--r-- | src/lanesconf.h | 1 | ||||
-rw-r--r-- | src/uniquekey.h | 6 | ||||
-rw-r--r-- | src/universe.cpp | 6 |
8 files changed, 49 insertions, 35 deletions
diff --git a/docs/index.html b/docs/index.html index 92cc38a..f5a074f 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -183,7 +183,7 @@ | |||
183 | </tr> | 183 | </tr> |
184 | </table> | 184 | </table> |
185 | <p> | 185 | <p> |
186 | <tt>luaopen_lanes_embedded</tt> leaves the module table on the stack. <tt>lanes.configure()</tt> must still be called in order to use Lanes. | 186 | <tt>luaopen_lanes_embedded</tt> leaves the module table on the stack. <a href="#initialization"><tt>lanes.configure()</tt></a> must still be called in order to use Lanes. |
187 | <br/> | 187 | <br/> |
188 | If <tt>_luaopen_lanes</tt> is <tt>nullptr</tt>, a default loader will simply attempt the equivalent of <tt>luaL_dofile(L, "lanes.lua")</tt>. | 188 | If <tt>_luaopen_lanes</tt> is <tt>nullptr</tt>, a default loader will simply attempt the equivalent of <tt>luaL_dofile(L, "lanes.lua")</tt>. |
189 | </p> | 189 | </p> |
@@ -249,17 +249,17 @@ | |||
249 | Requiring the module follows Lua 5.2+ rules: the module is not available under the global name "lanes", but has to be accessed through <tt>require</tt>'s return value. | 249 | Requiring the module follows Lua 5.2+ rules: the module is not available under the global name "lanes", but has to be accessed through <tt>require</tt>'s return value. |
250 | </p> | 250 | </p> |
251 | <p> | 251 | <p> |
252 | After lanes is required, it is necessary to call <tt>lanes.configure()</tt>, which is the only function exposed by the module at this point. Calling <tt>configure()</tt> will perform one-time initializations and make the rest of the API available. | 252 | After lanes is required, it is necessary to call <tt>lanes.configure()</tt>, which is the only function exposed by the module at this point. Calling <tt>lanes.configure()</tt> will perform one-time initializations and make the rest of the API available. |
253 | </p> | 253 | </p> |
254 | <p> | 254 | <p> |
255 | At the same time, <tt>configure()</tt> itself will be replaced by another function that raises an error if called again with differing arguments, if any. | 255 | At the same time, <tt>lanes.configure()</tt> itself will be replaced by another function that raises an error if called again with differing arguments, if any. |
256 | </p> | 256 | </p> |
257 | <p> | 257 | <p> |
258 | Also, once Lanes is initialized, <tt>require()</tt> is replaced by another one that wraps it inside a mutex, both in the main state and in all created lanes. This prevents multiple thread-unsafe module initializations from several lanes to occur simultaneously. | 258 | Also, once Lanes is initialized, <tt>require()</tt> is replaced by another one that wraps it inside a mutex, both in the main state and in all created lanes. This prevents multiple thread-unsafe module initializations from several lanes to occur simultaneously. |
259 | It remains to be seen whether this is actually useful or not: If a module is already threadsafe, protecting its initialization isn't useful. And if it is not, any parallel operation may crash without Lanes being able to do anything about it. | 259 | It remains to be seen whether this is actually useful or not: If a module is already threadsafe, protecting its initialization isn't useful. And if it is not, any parallel operation may crash without Lanes being able to do anything about it. |
260 | </p> | 260 | </p> |
261 | <p> | 261 | <p> |
262 | <b>IMPORTANT NOTE:</b> Only the first occurence of <tt>require "lanes"</tt> must be followed by a call to <tt>.configure()</tt>. From this point, a simple <tt>require "lanes"</tt> will do wherever you need to require lanes again. | 262 | <b>IMPORTANT NOTE:</b> Only the first occurence of <tt>require "lanes"</tt> must be followed by a call to <tt>lanes.configure()</tt>. From this point, a simple <tt>require "lanes"</tt> will be enough wherever you need to require lanes again. |
263 | </p> | 263 | </p> |
264 | 264 | ||
265 | <p> | 265 | <p> |
@@ -758,8 +758,10 @@ | |||
758 | </table> | 758 | </table> |
759 | 759 | ||
760 | <p> | 760 | <p> |
761 | Each lane also gets a global function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says. Supported debuggers are Microsoft Visual Studio (for the C side) and Decoda (for the Lua side). | 761 | Each lane gets a global function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says. Supported debuggers are Microsoft Visual Studio (for the C side) and <a href="https://github.com/unknownworlds/decoda">Decoda</a> (for the Lua side).<br/> |
762 | <br/> | 762 | Decoda support is limited to setting a special global variable <tt>decoda_name</tt>. This is disabled by default. Change <tt>HAVE_DECODA_NAME()</tt> in <tt>lanesconf.h</tt> if necessary.<br/> |
763 | The name is stored inside the Lua state registry so that it is available for error reporting. Changing <tt>decoda_name</tt> doesn't affect this hidden name or the OS thread name reported by MSVC.<br/> | ||
764 | When Lanes is initialized by the first <a href="#initialization"><tt>lanes.configure()</tt></a> call, <tt>"main"</tt> is stored in the registry in the same fashion (but <tt>decoda_name</tt> and the OS thread name are left unchanged).<br/> | ||
763 | The lane also has a method <tt>lane:get_debug_threadname()</tt> that gives access to that name from the caller side (returns <tt>"<unnamed>"</tt> if unset, <tt>"<closed>"</tt> if the internal Lua state is closed). | 765 | The lane also has a method <tt>lane:get_debug_threadname()</tt> that gives access to that name from the caller side (returns <tt>"<unnamed>"</tt> if unset, <tt>"<closed>"</tt> if the internal Lua state is closed). |
764 | </p> | 766 | </p> |
765 | 767 | ||
@@ -1334,7 +1336,7 @@ | |||
1334 | 1336 | ||
1335 | <li> | 1337 | <li> |
1336 | Performance. Changing any slot in a Linda causes all pending threads for that Linda to be momentarily awakened (at least in the C level). | 1338 | Performance. Changing any slot in a Linda causes all pending threads for that Linda to be momentarily awakened (at least in the C level). |
1337 | This can degrade performance due to unnecessary OS level context switches. The more keeper states you declared with <tt>lanes.configure()</tt> the less this should be a problem. | 1339 | This can degrade performance due to unnecessary OS level context switches. The more keeper states you declared with <a href="#initialization"><tt>lanes.configure()</tt></a> the less this should be a problem. |
1338 | </li> | 1340 | </li> |
1339 | </ul> | 1341 | </ul> |
1340 | 1342 | ||
@@ -1356,7 +1358,7 @@ events to a common Linda, but... :).</font> | |||
1356 | </pre></td></tr></table> | 1358 | </pre></td></tr></table> |
1357 | 1359 | ||
1358 | <p> | 1360 | <p> |
1359 | Timers are implemented as a lane. They can be enabled by setting "<tt><a href="#with_timers">with_timers</a></tt>" to <tt>true</tt> in <tt>lanes.configure()</tt> settings. | 1361 | Timers are implemented as a lane. They can be enabled by setting "<tt><a href="#with_timers">with_timers</a></tt>" to <tt>true</tt> in <a href="#initialization"><tt>lanes.configure()</tt></a> settings. |
1360 | </p> | 1362 | </p> |
1361 | 1363 | ||
1362 | <p> | 1364 | <p> |
@@ -1373,7 +1375,7 @@ events to a common Linda, but... :).</font> | |||
1373 | 1375 | ||
1374 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1376 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1375 | local lanes = require "lanes" | 1377 | local lanes = require "lanes" |
1376 | lanes.configure() | 1378 | lanes.configure{with_timers = true} |
1377 | 1379 | ||
1378 | local linda = lanes.linda() | 1380 | local linda = lanes.linda() |
1379 | 1381 | ||
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 6c72b1c..893305e 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -29,6 +29,7 @@ THE SOFTWARE. | |||
29 | #include "debugspew.h" | 29 | #include "debugspew.h" |
30 | #include "deep.h" | 30 | #include "deep.h" |
31 | #include "keeper.h" | 31 | #include "keeper.h" |
32 | #include "lane.h" | ||
32 | #include "linda.h" | 33 | #include "linda.h" |
33 | #include "universe.h" | 34 | #include "universe.h" |
34 | 35 | ||
@@ -106,11 +107,11 @@ THE SOFTWARE. | |||
106 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) | 107 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) |
107 | _fqn = std::string_view{}; // just in case | 108 | _fqn = std::string_view{}; // just in case |
108 | // try to discover the name of the function we want to send | 109 | // try to discover the name of the function we want to send |
109 | lua_getglobal(L1, "decoda_name"); // L1: ... v ... decoda_name | 110 | kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name |
110 | char const* _from{ lua_tostring(L1, -1) }; | 111 | char const* _from{ lua_tostring(L1, -1) }; |
111 | lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... decoda_name luaG_nameof | 112 | lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... lane_name luaG_nameof |
112 | lua_pushvalue(L1, L1_i); // L1: ... v ... decoda_name luaG_nameof t | 113 | lua_pushvalue(L1, L1_i); // L1: ... v ... lane_name luaG_nameof t |
113 | lua_call(L1, 1, 2); // L1: ... v ... decoda_name "type" "name"|nil | 114 | lua_call(L1, 1, 2); // L1: ... v ... lane_name "type" "name"|nil |
114 | char const* _typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) }; | 115 | char const* _typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) }; |
115 | // second return value can be nil if the table was not found | 116 | // second return value can be nil if the table was not found |
116 | // probable reason: the function was removed from the source Lua state before Lanes was required. | 117 | // probable reason: the function was removed from the source Lua state before Lanes was required. |
@@ -325,10 +326,10 @@ void InterCopyContext::lookup_native_func() const | |||
325 | // nil means we don't know how to transfer stuff: user should do something | 326 | // nil means we don't know how to transfer stuff: user should do something |
326 | // anything other than function or table should not happen! | 327 | // anything other than function or table should not happen! |
327 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { | 328 | if (!lua_isfunction(L2, -1) && !lua_istable(L2, -1)) { |
328 | lua_getglobal(L1, "decoda_name"); // L1: ... f ... decoda_name | 329 | kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name |
329 | char const* const _from{ lua_tostring(L1, -1) }; | 330 | char const* const _from{ lua_tostring(L1, -1) }; |
330 | lua_pop(L1, 1); // L1: ... f ... | 331 | lua_pop(L1, 1); // L1: ... f ... |
331 | lua_getglobal(L2, "decoda_name"); // L1: ... f ... L2: {} f decoda_name | 332 | kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name |
332 | char const* const _to{ lua_tostring(L2, -1) }; | 333 | char const* const _to{ lua_tostring(L2, -1) }; |
333 | lua_pop(L2, 1); // L2: {} f | 334 | lua_pop(L2, 1); // L2: {} f |
334 | // 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 | 335 | // 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 |
@@ -449,10 +450,10 @@ void InterCopyContext::copy_cached_func() const | |||
449 | STACK_CHECK(L2, 0); | 450 | STACK_CHECK(L2, 0); |
450 | return false; | 451 | return false; |
451 | } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table | 452 | } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table |
452 | lua_getglobal(L1, "decoda_name"); // L1: ... t ... decoda_name | 453 | kLaneNameRegKey.pushValue(L1); // L1: ... t ... lane_name |
453 | char const* _from{ lua_tostring(L1, -1) }; | 454 | char const* _from{ lua_tostring(L1, -1) }; |
454 | lua_pop(L1, 1); // L1: ... t ... | 455 | lua_pop(L1, 1); // L1: ... t ... |
455 | lua_getglobal(L2, "decoda_name"); // L1: ... t ... L2: {} t decoda_name | 456 | kLaneNameRegKey.pushValue(L2); // L1: ... t ... L2: {} t lane_name |
456 | char const* _to{ lua_tostring(L2, -1) }; | 457 | char const* _to{ lua_tostring(L2, -1) }; |
457 | lua_pop(L2, 1); // L1: ... t ... L2: {} t | 458 | lua_pop(L2, 1); // L1: ... t ... L2: {} t |
458 | raise_luaL_error( | 459 | raise_luaL_error( |
diff --git a/src/lane.cpp b/src/lane.cpp index f220bce..ada1846 100644 --- a/src/lane.cpp +++ b/src/lane.cpp | |||
@@ -802,20 +802,20 @@ Lane::~Lane() | |||
802 | 802 | ||
803 | // ################################################################################################# | 803 | // ################################################################################################# |
804 | 804 | ||
805 | void Lane::changeDebugName(int nameIdx_) | 805 | void Lane::changeDebugName(int const nameIdx_) |
806 | { | 806 | { |
807 | // xxh64 of string "debugName" generated at https://www.pelock.com/products/hash-calculator | 807 | int const _nameIdx{ lua_absindex(L, nameIdx_) }; |
808 | static constexpr RegistryUniqueKey kRegKey{ 0xA194E2645C57F6DDull }; | 808 | luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... |
809 | nameIdx_ = lua_absindex(L, nameIdx_); | ||
810 | luaL_checktype(L, nameIdx_, LUA_TSTRING); // L: ... "name" ... | ||
811 | STACK_CHECK_START_REL(L, 0); | 809 | STACK_CHECK_START_REL(L, 0); |
812 | // 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... | 810 | // 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... |
813 | kRegKey.setValue(L, [nameIdx = nameIdx_](lua_State* L_) { lua_pushvalue(L_, nameIdx); }); // L: ... "name" ... | 811 | kLaneNameRegKey.setValue(L, [idx = _nameIdx](lua_State* L_) { lua_pushvalue(L_, idx); }); // L: ... "name" ... |
814 | // keep a direct pointer on the string | 812 | // keep a direct pointer on the string |
815 | debugName = lua_tostringview(L, nameIdx_); | 813 | debugName = lua_tostringview(L, _nameIdx); |
816 | // to see VM name in Decoda debugger Virtual Machine window | 814 | if constexpr (HAVE_DECODA_NAME()) { |
817 | lua_pushvalue(L, nameIdx_); // L: ... "name" ... "name" | 815 | // to see VM name in Decoda debugger Virtual Machine window |
818 | lua_setglobal(L, "decoda_name"); // L: ... "name" ... | 816 | lua_pushvalue(L, _nameIdx); // L: ... "name" ... "name" |
817 | lua_setglobal(L, "decoda_name"); // L: ... "name" ... | ||
818 | } | ||
819 | // and finally set the OS thread name | 819 | // and finally set the OS thread name |
820 | THREAD_SETNAME(debugName.data()); | 820 | THREAD_SETNAME(debugName.data()); |
821 | STACK_CHECK(L, 0); | 821 | STACK_CHECK(L, 0); |
@@ -13,6 +13,9 @@ | |||
13 | 13 | ||
14 | // ################################################################################################# | 14 | // ################################################################################################# |
15 | 15 | ||
16 | // xxh64 of string "kExtendedStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator | ||
17 | static constexpr RegistryUniqueKey kExtendedStackTraceRegKey{ 0x38147AD48FB426E2ull }; // used as registry key | ||
18 | |||
16 | /* | 19 | /* |
17 | * registry[FINALIZER_REG_KEY] is either nil (no finalizers) or a table | 20 | * registry[FINALIZER_REG_KEY] is either nil (no finalizers) or a table |
18 | * of functions that Lanes will call after the executing 'pcall' has ended. | 21 | * of functions that Lanes will call after the executing 'pcall' has ended. |
@@ -24,15 +27,15 @@ | |||
24 | // xxh64 of string "kFinalizerRegKey" generated at https://www.pelock.com/products/hash-calculator | 27 | // xxh64 of string "kFinalizerRegKey" generated at https://www.pelock.com/products/hash-calculator |
25 | static constexpr RegistryUniqueKey kFinalizerRegKey{ 0xFE936BFAA718FEEAull }; | 28 | static constexpr RegistryUniqueKey kFinalizerRegKey{ 0xFE936BFAA718FEEAull }; |
26 | 29 | ||
27 | // xxh64 of string "kExtendedStackTraceRegKey" generated at https://www.pelock.com/products/hash-calculator | ||
28 | static constexpr RegistryUniqueKey kExtendedStackTraceRegKey{ 0x38147AD48FB426E2ull }; // used as registry key | ||
29 | |||
30 | // xxh64 of string "kLaneGC" generated at https://www.pelock.com/products/hash-calculator | 30 | // xxh64 of string "kLaneGC" generated at https://www.pelock.com/products/hash-calculator |
31 | static constexpr UniqueKey kLaneGC{ 0x5D6122141727F960ull }; | 31 | static constexpr UniqueKey kLaneGC{ 0x5D6122141727F960ull }; |
32 | 32 | ||
33 | // xxh64 of string "kLanePointerRegKey" generated at https://www.pelock.com/products/hash-calculator | 33 | // xxh64 of string "kLanePointerRegKey" generated at https://www.pelock.com/products/hash-calculator |
34 | static constexpr RegistryUniqueKey kLanePointerRegKey{ 0x2D8CF03FE9F0A51Aull }; // used as registry key | 34 | static constexpr RegistryUniqueKey kLanePointerRegKey{ 0x2D8CF03FE9F0A51Aull }; // used as registry key |
35 | 35 | ||
36 | // xxh64 of string "debugName" generated at https://www.pelock.com/products/hash-calculator | ||
37 | static constexpr RegistryUniqueKey kLaneNameRegKey{ 0xA194E2645C57F6DDull }; | ||
38 | |||
36 | // ################################################################################################# | 39 | // ################################################################################################# |
37 | 40 | ||
38 | // The chain is ended by '(Lane*)(-1)', not nullptr: 'selfdestructFirst -> ... -> ... -> (-1)' | 41 | // The chain is ended by '(Lane*)(-1)', not nullptr: 'selfdestructFirst -> ... -> ... -> (-1)' |
@@ -124,7 +127,7 @@ class Lane | |||
124 | Lane(Universe* U_, lua_State* L_, ErrorTraceLevel errorTraceLevel_); | 127 | Lane(Universe* U_, lua_State* L_, ErrorTraceLevel errorTraceLevel_); |
125 | ~Lane(); | 128 | ~Lane(); |
126 | 129 | ||
127 | void changeDebugName(int nameIdx_); | 130 | void changeDebugName(int const nameIdx_); |
128 | void close() { lua_State* _L{ L }; L = nullptr; lua_close(_L); } | 131 | void close() { lua_State* _L{ L }; L = nullptr; lua_close(_L); } |
129 | [[nodiscard]] std::string_view errorTraceLevelString() const; | 132 | [[nodiscard]] std::string_view errorTraceLevelString() const; |
130 | [[nodiscard]] int pushErrorHandler() const; | 133 | [[nodiscard]] int pushErrorHandler() const; |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 20636b2..0ea0900 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -676,6 +676,9 @@ LUAG_FUNC(configure) | |||
676 | // increment refcount so that this linda remains alive as long as the universe exists. | 676 | // increment refcount so that this linda remains alive as long as the universe exists. |
677 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); | 677 | _U->timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); |
678 | lua_pop(L_, 1); // L_: settings | 678 | lua_pop(L_, 1); // L_: settings |
679 | // 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... | ||
680 | kLaneNameRegKey.setValue(L_, [](lua_State* L_) { std::ignore = lua_pushstringview(L_, "main"); }); | ||
681 | |||
679 | } | 682 | } |
680 | STACK_CHECK(L_, 1); | 683 | STACK_CHECK(L_, 1); |
681 | 684 | ||
diff --git a/src/lanesconf.h b/src/lanesconf.h index 3836848..2df7a71 100644 --- a/src/lanesconf.h +++ b/src/lanesconf.h | |||
@@ -42,3 +42,4 @@ | |||
42 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 42 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
43 | 43 | ||
44 | #define USE_DEBUG_SPEW() 0 | 44 | #define USE_DEBUG_SPEW() 0 |
45 | #define HAVE_DECODA_NAME() 0 | ||
diff --git a/src/uniquekey.h b/src/uniquekey.h index 9981bb8..cfc8ab0 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
@@ -62,9 +62,9 @@ class RegistryUniqueKey | |||
62 | void setValue(lua_State* L_, OP operation_) const | 62 | void setValue(lua_State* L_, OP operation_) const |
63 | { | 63 | { |
64 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) | 64 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) |
65 | pushKey(L_); // ... key | 65 | pushKey(L_); // ... key |
66 | operation_(L_); // ... key value | 66 | operation_(L_); // ... key value |
67 | lua_rawset(L_, LUA_REGISTRYINDEX); // ... | 67 | lua_rawset(L_, LUA_REGISTRYINDEX); // ... |
68 | } | 68 | } |
69 | // --------------------------------------------------------------------------------------------- | 69 | // --------------------------------------------------------------------------------------------- |
70 | template <typename T> | 70 | template <typename T> |
diff --git a/src/universe.cpp b/src/universe.cpp index 9e1ac5f..5fe53d5 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -286,7 +286,11 @@ void Universe::initializeKeepers(lua_State* L_) | |||
286 | 286 | ||
287 | // to see VM name in Decoda debugger | 287 | // to see VM name in Decoda debugger |
288 | lua_pushfstring(_K, "Keeper #%d", _i + 1); // L_: settings K: "Keeper #n" | 288 | lua_pushfstring(_K, "Keeper #%d", _i + 1); // L_: settings K: "Keeper #n" |
289 | lua_setglobal(_K, "decoda_name"); // L_: settings K: | 289 | if constexpr (HAVE_DECODA_NAME()) { |
290 | lua_pushvalue(_K, -1); // K: "Keeper #n" Keeper #n" | ||
291 | lua_setglobal(_K, "decoda_name"); // L_: settings K: "Keeper #n" | ||
292 | } | ||
293 | kLaneNameRegKey.setValue(_K, [](lua_State* L_) { lua_insert(L_, -2); }); // K: | ||
290 | // create the fifos table in the keeper state | 294 | // create the fifos table in the keeper state |
291 | Keepers::CreateFifosTable(_K); | 295 | Keepers::CreateFifosTable(_K); |
292 | STACK_CHECK(_K, 0); | 296 | STACK_CHECK(_K, 0); |