diff options
-rw-r--r-- | src/cancel.cpp | 4 | ||||
-rw-r--r-- | src/cancel.h | 5 | ||||
-rw-r--r-- | src/deep.cpp | 5 | ||||
-rw-r--r-- | src/keeper.cpp | 21 | ||||
-rw-r--r-- | src/lanes.cpp | 71 | ||||
-rw-r--r-- | src/lanes_private.h | 14 | ||||
-rw-r--r-- | src/linda.cpp | 33 | ||||
-rw-r--r-- | src/state.cpp | 34 | ||||
-rw-r--r-- | src/tools.cpp | 18 | ||||
-rw-r--r-- | src/uniquekey.h | 31 | ||||
-rw-r--r-- | src/universe.cpp | 13 |
11 files changed, 125 insertions, 124 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index 8b8977b..0f7a6af 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -55,8 +55,8 @@ THE SOFTWARE. | |||
55 | */ | 55 | */ |
56 | static inline CancelRequest cancel_test(lua_State* L) | 56 | static inline CancelRequest cancel_test(lua_State* L) |
57 | { | 57 | { |
58 | Lane* const lane{ get_lane_from_registry(L) }; | 58 | Lane* const lane{ LANE_POINTER_REGKEY.readLightUserDataValue<Lane>(L) }; |
59 | // 's' is nullptr for the original main state (and no-one can cancel that) | 59 | // 'lane' is nullptr for the original main state (and no-one can cancel that) |
60 | return lane ? lane->cancel_request : CancelRequest::None; | 60 | return lane ? lane->cancel_request : CancelRequest::None; |
61 | } | 61 | } |
62 | 62 | ||
diff --git a/src/cancel.h b/src/cancel.h index 9cd7d5b..481cca4 100644 --- a/src/cancel.h +++ b/src/cancel.h | |||
@@ -48,15 +48,12 @@ enum CancelOp | |||
48 | // crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ | 48 | // crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ |
49 | static constexpr UniqueKey CANCEL_ERROR{ 0xe97d41626cc97577ull }; // 'raise_cancel_error' sentinel | 49 | static constexpr UniqueKey CANCEL_ERROR{ 0xe97d41626cc97577ull }; // 'raise_cancel_error' sentinel |
50 | 50 | ||
51 | // crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/ | ||
52 | static constexpr UniqueKey CANCEL_TEST_KEY{ 0xe66f5960c57d133aull }; // used as registry key | ||
53 | |||
54 | CancelResult thread_cancel(lua_State* L, Lane* lane_, CancelOp op_, double secs_, bool force_, double waitkill_timeout_); | 51 | CancelResult thread_cancel(lua_State* L, Lane* lane_, CancelOp op_, double secs_, bool force_, double waitkill_timeout_); |
55 | 52 | ||
56 | [[noreturn]] static inline void raise_cancel_error(lua_State* L) | 53 | [[noreturn]] static inline void raise_cancel_error(lua_State* L) |
57 | { | 54 | { |
58 | STACK_GROW(L, 1); | 55 | STACK_GROW(L, 1); |
59 | CANCEL_ERROR.push(L); // special error value | 56 | CANCEL_ERROR.pushKey(L); // special error value |
60 | raise_lua_error(L); // doesn't return | 57 | raise_lua_error(L); // doesn't return |
61 | } | 58 | } |
62 | 59 | ||
diff --git a/src/deep.cpp b/src/deep.cpp index 652b19d..290e5ff 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -32,8 +32,9 @@ THE SOFTWARE. | |||
32 | =============================================================================== | 32 | =============================================================================== |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "compat.h" | ||
36 | #include "deep.h" | 35 | #include "deep.h" |
36 | |||
37 | #include "compat.h" | ||
37 | #include "tools.h" | 38 | #include "tools.h" |
38 | #include "uniquekey.h" | 39 | #include "uniquekey.h" |
39 | #include "universe.h" | 40 | #include "universe.h" |
@@ -95,7 +96,7 @@ static void get_deep_lookup( lua_State* L) | |||
95 | { | 96 | { |
96 | STACK_GROW( L, 1); | 97 | STACK_GROW( L, 1); |
97 | STACK_CHECK_START_REL(L, 1); // a | 98 | STACK_CHECK_START_REL(L, 1); // a |
98 | DEEP_LOOKUP_KEY.query_registry(L); // a {} | 99 | DEEP_LOOKUP_KEY.pushValue(L); // a {} |
99 | if( !lua_isnil( L, -1)) | 100 | if( !lua_isnil( L, -1)) |
100 | { | 101 | { |
101 | lua_insert( L, -2); // {} a | 102 | lua_insert( L, -2); // {} a |
diff --git a/src/keeper.cpp b/src/keeper.cpp index f88d0ab..aab7abe 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -188,7 +188,7 @@ static void push_table(lua_State* L, int idx_) | |||
188 | STACK_GROW(L, 5); | 188 | STACK_GROW(L, 5); |
189 | STACK_CHECK_START_REL(L, 0); | 189 | STACK_CHECK_START_REL(L, 0); |
190 | idx_ = lua_absindex(L, idx_); | 190 | idx_ = lua_absindex(L, idx_); |
191 | FIFOS_KEY.query_registry(L); // ud fifos | 191 | FIFOS_KEY.pushValue(L); // ud fifos |
192 | lua_pushvalue(L, idx_); // ud fifos ud | 192 | lua_pushvalue(L, idx_); // ud fifos ud |
193 | lua_rawget(L, -2); // ud fifos fifos[ud] | 193 | lua_rawget(L, -2); // ud fifos fifos[ud] |
194 | STACK_CHECK(L, 2); | 194 | STACK_CHECK(L, 2); |
@@ -209,16 +209,17 @@ static void push_table(lua_State* L, int idx_) | |||
209 | 209 | ||
210 | int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t magic_) | 210 | int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t magic_) |
211 | { | 211 | { |
212 | Keeper* const K = which_keeper( U->keepers, magic_); | 212 | Keeper* const K{ which_keeper(U->keepers, magic_) }; |
213 | lua_State* const KL = K ? K->L : nullptr; | 213 | lua_State* const KL{ K ? K->L : nullptr }; |
214 | if( KL == nullptr) return 0; | 214 | if (KL == nullptr) |
215 | return 0; | ||
215 | STACK_GROW(KL, 4); | 216 | STACK_GROW(KL, 4); |
216 | STACK_CHECK_START_REL(KL, 0); | 217 | STACK_CHECK_START_REL(KL, 0); |
217 | FIFOS_KEY.query_registry(KL); // fifos | 218 | FIFOS_KEY.pushValue(KL); // fifos |
218 | lua_pushlightuserdata(KL, ptr_); // fifos ud | 219 | lua_pushlightuserdata(KL, ptr_); // fifos ud |
219 | lua_rawget(KL, -2); // fifos storage | 220 | lua_rawget(KL, -2); // fifos storage |
220 | lua_remove(KL, -2); // storage | 221 | lua_remove(KL, -2); // storage |
221 | if( !lua_istable(KL, -1)) | 222 | if (!lua_istable(KL, -1)) |
222 | { | 223 | { |
223 | lua_pop(KL, 1); // | 224 | lua_pop(KL, 1); // |
224 | STACK_CHECK(KL, 0); | 225 | STACK_CHECK(KL, 0); |
@@ -229,7 +230,7 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t m | |||
229 | STACK_GROW(L, 5); | 230 | STACK_GROW(L, 5); |
230 | STACK_CHECK_START_REL(L, 0); | 231 | STACK_CHECK_START_REL(L, 0); |
231 | lua_newtable(L); // out | 232 | lua_newtable(L); // out |
232 | while( lua_next(KL, -2)) // storage key fifo | 233 | while (lua_next(KL, -2)) // storage key fifo |
233 | { | 234 | { |
234 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl | 235 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl |
235 | lua_pushvalue(KL, -2); // storage key fifotbl key | 236 | lua_pushvalue(KL, -2); // storage key fifotbl key |
@@ -263,7 +264,7 @@ int keepercall_clear(lua_State* L) | |||
263 | { | 264 | { |
264 | STACK_GROW(L, 3); | 265 | STACK_GROW(L, 3); |
265 | STACK_CHECK_START_REL(L, 0); | 266 | STACK_CHECK_START_REL(L, 0); |
266 | FIFOS_KEY.query_registry(L); // ud fifos | 267 | FIFOS_KEY.pushValue(L); // ud fifos |
267 | lua_pushvalue(L, 1); // ud fifos ud | 268 | lua_pushvalue(L, 1); // ud fifos ud |
268 | lua_pushnil(L); // ud fifos ud nil | 269 | lua_pushnil(L); // ud fifos ud nil |
269 | lua_rawset(L, -3); // ud fifos | 270 | lua_rawset(L, -3); // ud fifos |
@@ -722,7 +723,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
722 | lua_pushfstring(K, "Keeper #%d", i + 1); // "Keeper #n" | 723 | lua_pushfstring(K, "Keeper #%d", i + 1); // "Keeper #n" |
723 | lua_setglobal(K, "decoda_name"); // | 724 | lua_setglobal(K, "decoda_name"); // |
724 | // create the fifos table in the keeper state | 725 | // create the fifos table in the keeper state |
725 | FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); }); | 726 | FIFOS_KEY.setValue(K, [](lua_State* L) { lua_newtable(L); }); |
726 | STACK_CHECK(K, 0); | 727 | STACK_CHECK(K, 0); |
727 | } | 728 | } |
728 | STACK_CHECK(L, 0); | 729 | STACK_CHECK(L, 0); |
@@ -788,7 +789,7 @@ void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode | |||
788 | { | 789 | { |
789 | if (lua_isnil(L, i)) | 790 | if (lua_isnil(L, i)) |
790 | { | 791 | { |
791 | NIL_SENTINEL.push(L); | 792 | NIL_SENTINEL.pushKey(L); |
792 | lua_replace(L, i); | 793 | lua_replace(L, i); |
793 | } | 794 | } |
794 | } | 795 | } |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 86972f7..327c2df 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * LANES.C Copyright (c) 2007-08, Asko Kauppi | 2 | * LANES.CPP Copyright (c) 2007-08, Asko Kauppi |
3 | * Copyright (C) 2009-19, Benoit Germain | 3 | * Copyright (C) 2009-24, Benoit Germain |
4 | * | 4 | * |
5 | * Multithreading in Lua. | 5 | * Multithreading in Lua. |
6 | * | 6 | * |
@@ -56,7 +56,7 @@ | |||
56 | =============================================================================== | 56 | =============================================================================== |
57 | 57 | ||
58 | Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> | 58 | Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> |
59 | 2011-19 Benoit Germain <bnt.germain@gmail.com> | 59 | 2011-24 Benoit Germain <bnt.germain@gmail.com> |
60 | 60 | ||
61 | Permission is hereby granted, free of charge, to any person obtaining a copy | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy |
62 | of this software and associated documentation files (the "Software"), to deal | 62 | of this software and associated documentation files (the "Software"), to deal |
@@ -79,22 +79,17 @@ THE SOFTWARE. | |||
79 | =============================================================================== | 79 | =============================================================================== |
80 | */ | 80 | */ |
81 | 81 | ||
82 | #include <string.h> | ||
83 | #include <stdio.h> | ||
84 | #include <stdlib.h> | ||
85 | #include <ctype.h> | ||
86 | #include <assert.h> | ||
87 | |||
88 | #include "lanes.h" | 82 | #include "lanes.h" |
89 | #include "threading.h" | 83 | |
90 | #include "compat.h" | 84 | #include "compat.h" |
91 | #include "tools.h" | ||
92 | #include "state.h" | ||
93 | #include "universe.h" | ||
94 | #include "keeper.h" | 85 | #include "keeper.h" |
95 | #include "lanes_private.h" | 86 | #include "lanes_private.h" |
87 | #include "state.h" | ||
88 | #include "threading.h" | ||
89 | #include "tools.h" | ||
90 | #include "universe.h" | ||
96 | 91 | ||
97 | #if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) | 92 | #if !(defined(PLATFORM_XBOX) || defined(PLATFORM_WIN32) || defined(PLATFORM_POCKETPC)) |
98 | # include <sys/time.h> | 93 | # include <sys/time.h> |
99 | #endif | 94 | #endif |
100 | 95 | ||
@@ -157,8 +152,8 @@ static bool push_registry_table( lua_State* L, UniqueKey key, bool create) | |||
157 | STACK_GROW(L, 3); | 152 | STACK_GROW(L, 3); |
158 | STACK_CHECK_START_REL(L, 0); | 153 | STACK_CHECK_START_REL(L, 0); |
159 | 154 | ||
160 | key.query_registry(L); // ? | 155 | key.pushValue(L); // ? |
161 | if (lua_isnil(L, -1)) // nil? | 156 | if (lua_isnil(L, -1)) // nil? |
162 | { | 157 | { |
163 | lua_pop(L, 1); // | 158 | lua_pop(L, 1); // |
164 | STACK_CHECK(L, 0); | 159 | STACK_CHECK(L, 0); |
@@ -168,8 +163,8 @@ static bool push_registry_table( lua_State* L, UniqueKey key, bool create) | |||
168 | return false; | 163 | return false; |
169 | } | 164 | } |
170 | 165 | ||
171 | lua_newtable( L); // t | 166 | lua_newtable(L); // t |
172 | key.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 167 | key.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
173 | } | 168 | } |
174 | STACK_CHECK(L, 1); | 169 | STACK_CHECK(L, 1); |
175 | return true; // table pushed | 170 | return true; // table pushed |
@@ -653,14 +648,14 @@ LUAG_FUNC( set_error_reporting) | |||
653 | return luaL_error(L, "unsupported error reporting model"); | 648 | return luaL_error(L, "unsupported error reporting model"); |
654 | } | 649 | } |
655 | done: | 650 | done: |
656 | EXTENDED_STACKTRACE_REGKEY.set_registry(L, [equal](lua_State* L) { lua_pushboolean(L, equal); }); | 651 | EXTENDED_STACKTRACE_REGKEY.setValue(L, [equal](lua_State* L) { lua_pushboolean(L, equal); }); |
657 | return 0; | 652 | return 0; |
658 | } | 653 | } |
659 | 654 | ||
660 | static int lane_error( lua_State* L) | 655 | static int lane_error(lua_State* L) |
661 | { | 656 | { |
662 | // error message (any type) | 657 | // error message (any type) |
663 | STACK_CHECK_START_ABS(L, 1); // some_error | 658 | STACK_CHECK_START_ABS(L, 1); // some_error |
664 | 659 | ||
665 | // Don't do stack survey for cancelled lanes. | 660 | // Don't do stack survey for cancelled lanes. |
666 | // | 661 | // |
@@ -670,9 +665,7 @@ static int lane_error( lua_State* L) | |||
670 | } | 665 | } |
671 | 666 | ||
672 | STACK_GROW(L, 3); | 667 | STACK_GROW(L, 3); |
673 | EXTENDED_STACKTRACE_REGKEY.query_registry(L); // some_error basic|extended | 668 | bool const extended{ EXTENDED_STACKTRACE_REGKEY.readBoolValue(L) }; |
674 | bool const extended{ lua_toboolean(L, -1) ? true : false}; | ||
675 | lua_pop(L, 1); // some_error | ||
676 | STACK_CHECK(L, 1); | 669 | STACK_CHECK(L, 1); |
677 | 670 | ||
678 | // Place stack trace at 'registry[STACKTRACE_REGKEY]' for the 'lua_pcall()' | 671 | // Place stack trace at 'registry[STACKTRACE_REGKEY]' for the 'lua_pcall()' |
@@ -685,7 +678,7 @@ static int lane_error( lua_State* L) | |||
685 | // | 678 | // |
686 | // table of { "sourcefile.lua:<line>", ... } | 679 | // table of { "sourcefile.lua:<line>", ... } |
687 | // | 680 | // |
688 | lua_newtable( L); // some_error {} | 681 | lua_newtable(L); // some_error {} |
689 | 682 | ||
690 | // Best to start from level 1, but in some cases it might be a C function | 683 | // Best to start from level 1, but in some cases it might be a C function |
691 | // and we don't get '.currentline' for that. It's okay - just keep level | 684 | // and we don't get '.currentline' for that. It's okay - just keep level |
@@ -697,7 +690,7 @@ static int lane_error( lua_State* L) | |||
697 | lua_getinfo(L, extended ? "Sln" : "Sl", &ar); | 690 | lua_getinfo(L, extended ? "Sln" : "Sl", &ar); |
698 | if (extended) | 691 | if (extended) |
699 | { | 692 | { |
700 | lua_newtable( L); // some_error {} {} | 693 | lua_newtable(L); // some_error {} {} |
701 | 694 | ||
702 | lua_pushstring(L, ar.source); // some_error {} {} source | 695 | lua_pushstring(L, ar.source); // some_error {} {} source |
703 | lua_setfield(L, -2, "source"); // some_error {} {} | 696 | lua_setfield(L, -2, "source"); // some_error {} {} |
@@ -726,7 +719,7 @@ static int lane_error( lua_State* L) | |||
726 | } | 719 | } |
727 | 720 | ||
728 | // store the stack trace table in the registry | 721 | // store the stack trace table in the registry |
729 | STACKTRACE_REGKEY.set_registry(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error | 722 | STACKTRACE_REGKEY.setValue(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error |
730 | 723 | ||
731 | STACK_CHECK(L, 1); | 724 | STACK_CHECK(L, 1); |
732 | return 1; // the untouched error value | 725 | return 1; // the untouched error value |
@@ -748,7 +741,7 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | |||
748 | // fetch the call stack table from the registry where the handler stored it | 741 | // fetch the call stack table from the registry where the handler stored it |
749 | STACK_GROW(L, 1); | 742 | STACK_GROW(L, 1); |
750 | // yields nil if no stack was generated (in case of cancellation for example) | 743 | // yields nil if no stack was generated (in case of cancellation for example) |
751 | STACKTRACE_REGKEY.query_registry(L); // err trace|nil | 744 | STACKTRACE_REGKEY.pushValue(L); // err trace|nil |
752 | STACK_CHECK(L, 1); | 745 | STACK_CHECK(L, 1); |
753 | 746 | ||
754 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed | 747 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed |
@@ -780,7 +773,7 @@ LUAG_FUNC(set_debug_threadname) | |||
780 | lua_settop(L, 1); | 773 | lua_settop(L, 1); |
781 | STACK_CHECK_START_ABS(L, 1); | 774 | STACK_CHECK_START_ABS(L, 1); |
782 | // 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... | 775 | // 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... |
783 | hidden_regkey.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 776 | hidden_regkey.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
784 | STACK_CHECK(L, 1); | 777 | STACK_CHECK(L, 1); |
785 | lane->debug_name = lua_tostring(L, -1); | 778 | lane->debug_name = lua_tostring(L, -1); |
786 | // keep a direct pointer on the string | 779 | // keep a direct pointer on the string |
@@ -1213,7 +1206,7 @@ LUAG_FUNC( lane_new) | |||
1213 | STACK_CHECK_RESET_REL(L, 0); | 1206 | STACK_CHECK_RESET_REL(L, 0); |
1214 | STACK_CHECK( L2, 1 + nargs); | 1207 | STACK_CHECK( L2, 1 + nargs); |
1215 | 1208 | ||
1216 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 1209 | // 'lane' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
1217 | // | 1210 | // |
1218 | // a Lane full userdata needs a single uservalue | 1211 | // a Lane full userdata needs a single uservalue |
1219 | Lane** const ud{ lua_newuserdatauv<Lane*>(L, 1) }; // func libs priority globals package required gc_cb lane | 1212 | Lane** const ud{ lua_newuserdatauv<Lane*>(L, 1) }; // func libs priority globals package required gc_cb lane |
@@ -1257,15 +1250,15 @@ LUAG_FUNC( lane_new) | |||
1257 | // Store the gc_cb callback in the uservalue | 1250 | // Store the gc_cb callback in the uservalue |
1258 | if (gc_cb_idx > 0) | 1251 | if (gc_cb_idx > 0) |
1259 | { | 1252 | { |
1260 | GCCB_KEY.push(L); // func libs priority globals package required gc_cb lane uv k | 1253 | GCCB_KEY.pushKey(L); // func libs priority globals package required gc_cb lane uv k |
1261 | lua_pushvalue(L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb | 1254 | lua_pushvalue(L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb |
1262 | lua_rawset(L, -3); // func libs priority globals package required gc_cb lane uv | 1255 | lua_rawset(L, -3); // func libs priority globals package required gc_cb lane uv |
1263 | } | 1256 | } |
1264 | 1257 | ||
1265 | lua_setiuservalue(L, -2, 1); // func libs priority globals package required gc_cb lane | 1258 | lua_setiuservalue(L, -2, 1); // func libs priority globals package required gc_cb lane |
1266 | 1259 | ||
1267 | // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). | 1260 | // Store 'lane' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). |
1268 | CANCEL_TEST_KEY.set_registry(L2, [lane](lua_State* L) { lua_pushlightuserdata(L, lane); }); // func [... args ...] | 1261 | LANE_POINTER_REGKEY.setValue(L2, [lane](lua_State* L) { lua_pushlightuserdata(L, lane); }); // func [... args ...] |
1269 | 1262 | ||
1270 | STACK_CHECK(L, 1); | 1263 | STACK_CHECK(L, 1); |
1271 | STACK_CHECK( L2, 1 + nargs); | 1264 | STACK_CHECK( L2, 1 + nargs); |
@@ -1298,7 +1291,7 @@ LUAG_FUNC(thread_gc) | |||
1298 | 1291 | ||
1299 | // if there a gc callback? | 1292 | // if there a gc callback? |
1300 | lua_getiuservalue(L, 1, 1); // ud uservalue | 1293 | lua_getiuservalue(L, 1, 1); // ud uservalue |
1301 | GCCB_KEY.push(L); // ud uservalue __gc | 1294 | GCCB_KEY.pushKey(L); // ud uservalue __gc |
1302 | lua_rawget(L, -2); // ud uservalue gc_cb|nil | 1295 | lua_rawget(L, -2); // ud uservalue gc_cb|nil |
1303 | if (!lua_isnil(L, -1)) | 1296 | if (!lua_isnil(L, -1)) |
1304 | { | 1297 | { |
@@ -1988,12 +1981,12 @@ LUAG_FUNC(configure) | |||
1988 | lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX | 1981 | lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX |
1989 | lua_setfield(L, -2, "max_prio"); // settings M | 1982 | lua_setfield(L, -2, "max_prio"); // settings M |
1990 | 1983 | ||
1991 | CANCEL_ERROR.push(L); // settings M CANCEL_ERROR | 1984 | CANCEL_ERROR.pushKey(L); // settings M CANCEL_ERROR |
1992 | lua_setfield(L, -2, "cancel_error"); // settings M | 1985 | lua_setfield(L, -2, "cancel_error"); // settings M |
1993 | 1986 | ||
1994 | STACK_CHECK(L, 2); // reference stack contains only the function argument 'settings' | 1987 | STACK_CHECK(L, 2); // reference stack contains only the function argument 'settings' |
1995 | // we'll need this every time we transfer some C function from/to this state | 1988 | // we'll need this every time we transfer some C function from/to this state |
1996 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); // settings M | 1989 | LOOKUP_REGKEY.setValue(L, [](lua_State* L) { lua_newtable(L); }); // settings M |
1997 | STACK_CHECK(L, 2); | 1990 | STACK_CHECK(L, 2); |
1998 | 1991 | ||
1999 | // register all native functions found in that module in the transferable functions database | 1992 | // register all native functions found in that module in the transferable functions database |
@@ -2016,7 +2009,7 @@ LUAG_FUNC(configure) | |||
2016 | lua_pop(L, 1); // settings | 2009 | lua_pop(L, 1); // settings |
2017 | 2010 | ||
2018 | // set _R[CONFIG_REGKEY] = settings | 2011 | // set _R[CONFIG_REGKEY] = settings |
2019 | CONFIG_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 2012 | CONFIG_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
2020 | STACK_CHECK(L, 1); | 2013 | STACK_CHECK(L, 1); |
2021 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | 2014 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); |
2022 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); | 2015 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); |
@@ -2105,11 +2098,11 @@ LANES_API int luaopen_lanes_core( lua_State* L) | |||
2105 | 2098 | ||
2106 | // Create main module interface table | 2099 | // Create main module interface table |
2107 | // we only have 1 closure, which must be called to configure Lanes | 2100 | // we only have 1 closure, which must be called to configure Lanes |
2108 | lua_newtable( L); // M | 2101 | lua_newtable(L); // M |
2109 | lua_pushvalue(L, 1); // M "lanes.core" | 2102 | lua_pushvalue(L, 1); // M "lanes.core" |
2110 | lua_pushvalue(L, -2); // M "lanes.core" M | 2103 | lua_pushvalue(L, -2); // M "lanes.core" M |
2111 | lua_pushcclosure(L, LG_configure, 2); // M LG_configure() | 2104 | lua_pushcclosure(L, LG_configure, 2); // M LG_configure() |
2112 | CONFIG_REGKEY.query_registry(L); // M LG_configure() settings | 2105 | CONFIG_REGKEY.pushValue(L); // M LG_configure() settings |
2113 | if (!lua_isnil(L, -1)) // this is not the first require "lanes.core": call configure() immediately | 2106 | if (!lua_isnil(L, -1)) // this is not the first require "lanes.core": call configure() immediately |
2114 | { | 2107 | { |
2115 | lua_pushvalue(L, -1); // M LG_configure() settings settings | 2108 | lua_pushvalue(L, -1); // M LG_configure() settings settings |
diff --git a/src/lanes_private.h b/src/lanes_private.h index 85b3c52..1530b9e 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h | |||
@@ -72,21 +72,13 @@ struct Lane | |||
72 | // For tracking only | 72 | // For tracking only |
73 | }; | 73 | }; |
74 | 74 | ||
75 | // xxh64 of string "LANE_POINTER_REGKEY" generated at https://www.pelock.com/products/hash-calculator | ||
76 | static constexpr UniqueKey LANE_POINTER_REGKEY{ 0xB3022205633743BCull }; // used as registry key | ||
77 | |||
75 | // To allow free-running threads (longer lifespan than the handle's) | 78 | // To allow free-running threads (longer lifespan than the handle's) |
76 | // 'Lane' are malloc/free'd and the handle only carries a pointer. | 79 | // 'Lane' are malloc/free'd and the handle only carries a pointer. |
77 | // This is not deep userdata since the handle's not portable among lanes. | 80 | // This is not deep userdata since the handle's not portable among lanes. |
78 | // | 81 | // |
79 | #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) | 82 | #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) |
80 | 83 | ||
81 | static inline Lane* get_lane_from_registry( lua_State* L) | ||
82 | { | ||
83 | STACK_GROW( L, 1); | ||
84 | STACK_CHECK_START_REL(L, 0); | ||
85 | CANCEL_TEST_KEY.query_registry(L); | ||
86 | Lane* const s{ lua_tolightuserdata<Lane>(L, -1) }; // lightuserdata (true 'Lane' pointer) / nil | ||
87 | lua_pop( L, 1); | ||
88 | STACK_CHECK( L, 0); | ||
89 | return s; | ||
90 | } | ||
91 | |||
92 | int push_thread_status( lua_State* L, Lane* s); | 84 | int push_thread_status( lua_State* L, Lane* s); |
diff --git a/src/linda.cpp b/src/linda.cpp index 77dc4cb..14eba2d 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -216,11 +216,8 @@ LUAG_FUNC(linda_protected_call) | |||
216 | LUAG_FUNC(linda_send) | 216 | LUAG_FUNC(linda_send) |
217 | { | 217 | { |
218 | Linda* const linda{ lua_toLinda<false>(L, 1) }; | 218 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
219 | bool ret{ false }; | 219 | time_d timeout{ -1.0 }; |
220 | CancelRequest cancel{ CancelRequest::None }; | 220 | int key_i{ 2 }; // index of first key, if timeout not there |
221 | int pushed; | ||
222 | time_d timeout = -1.0; | ||
223 | int key_i = 2; // index of first key, if timeout not there | ||
224 | 221 | ||
225 | if (lua_type(L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion | 222 | if (lua_type(L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion |
226 | { | 223 | { |
@@ -250,7 +247,7 @@ LUAG_FUNC(linda_send) | |||
250 | if (as_nil_sentinel) | 247 | if (as_nil_sentinel) |
251 | { | 248 | { |
252 | // send a single nil if nothing is provided | 249 | // send a single nil if nothing is provided |
253 | NIL_SENTINEL.push(L); | 250 | NIL_SENTINEL.pushKey(L); |
254 | } | 251 | } |
255 | else | 252 | else |
256 | { | 253 | { |
@@ -260,9 +257,11 @@ LUAG_FUNC(linda_send) | |||
260 | 257 | ||
261 | // convert nils to some special non-nil sentinel in sent values | 258 | // convert nils to some special non-nil sentinel in sent values |
262 | keeper_toggle_nil_sentinels(L, key_i + 1, eLM_ToKeeper); | 259 | keeper_toggle_nil_sentinels(L, key_i + 1, eLM_ToKeeper); |
263 | 260 | bool ret{ false }; | |
261 | CancelRequest cancel{ CancelRequest::None }; | ||
262 | int pushed{ 0 }; | ||
264 | { | 263 | { |
265 | Lane* const lane{ get_lane_from_registry(L) }; | 264 | Lane* const lane{ LANE_POINTER_REGKEY.readLightUserDataValue<Lane>(L) }; |
266 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 265 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
267 | lua_State* const KL{ K ? K->L : nullptr }; | 266 | lua_State* const KL{ K ? K->L : nullptr }; |
268 | if (KL == nullptr) | 267 | if (KL == nullptr) |
@@ -339,7 +338,7 @@ LUAG_FUNC(linda_send) | |||
339 | { | 338 | { |
340 | case CancelRequest::Soft: | 339 | case CancelRequest::Soft: |
341 | // if user wants to soft-cancel, the call returns lanes.cancel_error | 340 | // if user wants to soft-cancel, the call returns lanes.cancel_error |
342 | CANCEL_ERROR.push(L); | 341 | CANCEL_ERROR.pushKey(L); |
343 | return 1; | 342 | return 1; |
344 | 343 | ||
345 | case CancelRequest::Hard: | 344 | case CancelRequest::Hard: |
@@ -387,7 +386,7 @@ LUAG_FUNC(linda_receive) | |||
387 | keeper_api_t keeper_receive; | 386 | keeper_api_t keeper_receive; |
388 | int expected_pushed_min{ 0 }, expected_pushed_max{ 0 }; | 387 | int expected_pushed_min{ 0 }, expected_pushed_max{ 0 }; |
389 | // are we in batched mode? | 388 | // are we in batched mode? |
390 | BATCH_SENTINEL.push(L); | 389 | BATCH_SENTINEL.pushKey(L); |
391 | int const is_batched{ lua501_equal(L, key_i, -1) }; | 390 | int const is_batched{ lua501_equal(L, key_i, -1) }; |
392 | lua_pop(L, 1); | 391 | lua_pop(L, 1); |
393 | if (is_batched) | 392 | if (is_batched) |
@@ -419,7 +418,7 @@ LUAG_FUNC(linda_receive) | |||
419 | expected_pushed_min = expected_pushed_max = 2; | 418 | expected_pushed_min = expected_pushed_max = 2; |
420 | } | 419 | } |
421 | 420 | ||
422 | Lane* const lane{ get_lane_from_registry(L) }; | 421 | Lane* const lane{ LANE_POINTER_REGKEY.readLightUserDataValue<Lane>(L) }; |
423 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; | 422 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
424 | if (K == nullptr) | 423 | if (K == nullptr) |
425 | return 0; | 424 | return 0; |
@@ -492,7 +491,7 @@ LUAG_FUNC(linda_receive) | |||
492 | { | 491 | { |
493 | case CancelRequest::Soft: | 492 | case CancelRequest::Soft: |
494 | // if user wants to soft-cancel, the call returns CANCEL_ERROR | 493 | // if user wants to soft-cancel, the call returns CANCEL_ERROR |
495 | CANCEL_ERROR.push(L); | 494 | CANCEL_ERROR.pushKey(L); |
496 | return 1; | 495 | return 1; |
497 | 496 | ||
498 | case CancelRequest::Hard: | 497 | case CancelRequest::Hard: |
@@ -551,7 +550,7 @@ LUAG_FUNC(linda_set) | |||
551 | else // linda is cancelled | 550 | else // linda is cancelled |
552 | { | 551 | { |
553 | // do nothing and return lanes.cancel_error | 552 | // do nothing and return lanes.cancel_error |
554 | CANCEL_ERROR.push(L); | 553 | CANCEL_ERROR.pushKey(L); |
555 | pushed = 1; | 554 | pushed = 1; |
556 | } | 555 | } |
557 | 556 | ||
@@ -610,7 +609,7 @@ LUAG_FUNC(linda_get) | |||
610 | else // linda is cancelled | 609 | else // linda is cancelled |
611 | { | 610 | { |
612 | // do nothing and return lanes.cancel_error | 611 | // do nothing and return lanes.cancel_error |
613 | CANCEL_ERROR.push(L); | 612 | CANCEL_ERROR.pushKey(L); |
614 | pushed = 1; | 613 | pushed = 1; |
615 | } | 614 | } |
616 | // an error can be raised if we attempt to read an unregistered function | 615 | // an error can be raised if we attempt to read an unregistered function |
@@ -655,7 +654,7 @@ LUAG_FUNC( linda_limit) | |||
655 | else // linda is cancelled | 654 | else // linda is cancelled |
656 | { | 655 | { |
657 | // do nothing and return lanes.cancel_error | 656 | // do nothing and return lanes.cancel_error |
658 | CANCEL_ERROR.push(L); | 657 | CANCEL_ERROR.pushKey(L); |
659 | pushed = 1; | 658 | pushed = 1; |
660 | } | 659 | } |
661 | // propagate pushed boolean if any | 660 | // propagate pushed boolean if any |
@@ -961,10 +960,10 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
961 | lua_setfield(L, -2, "dump"); | 960 | lua_setfield(L, -2, "dump"); |
962 | 961 | ||
963 | // some constants | 962 | // some constants |
964 | BATCH_SENTINEL.push(L); | 963 | BATCH_SENTINEL.pushKey(L); |
965 | lua_setfield(L, -2, "batched"); | 964 | lua_setfield(L, -2, "batched"); |
966 | 965 | ||
967 | NIL_SENTINEL.push(L); | 966 | NIL_SENTINEL.pushKey(L); |
968 | lua_setfield(L, -2, "null"); | 967 | lua_setfield(L, -2, "null"); |
969 | 968 | ||
970 | STACK_CHECK(L, 1); | 969 | STACK_CHECK(L, 1); |
diff --git a/src/state.cpp b/src/state.cpp index b52bdb5..2678280 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -203,14 +203,14 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | |||
203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
205 | 205 | ||
206 | CONFIG_REGKEY.query_registry(L); // config | 206 | CONFIG_REGKEY.pushValue(L); // config |
207 | // copy settings from from source to destination registry | 207 | // copy settings from from source to destination registry |
208 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config | 208 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config |
209 | { | 209 | { |
210 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); | 210 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); |
211 | } | 211 | } |
212 | // set L2:_R[CONFIG_REGKEY] = settings | 212 | // set L2:_R[CONFIG_REGKEY] = settings |
213 | CONFIG_REGKEY.set_registry(L2, [](lua_State* L) { lua_insert(L, -2); }); // config | 213 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config |
214 | STACK_CHECK( L2, 0); | 214 | STACK_CHECK( L2, 0); |
215 | STACK_CHECK( L, 0); | 215 | STACK_CHECK( L, 0); |
216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
@@ -273,43 +273,43 @@ lua_State* create_state( Universe* U, lua_State* from_) | |||
273 | 273 | ||
274 | if (L == nullptr) | 274 | if (L == nullptr) |
275 | { | 275 | { |
276 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | 276 | std::ignore = luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); |
277 | } | 277 | } |
278 | return L; | 278 | return L; |
279 | } | 279 | } |
280 | 280 | ||
281 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) | 281 | void call_on_state_create(Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) |
282 | { | 282 | { |
283 | if (U->on_state_create_func != nullptr) | 283 | if (U->on_state_create_func != nullptr) |
284 | { | 284 | { |
285 | STACK_CHECK_START_REL(L, 0); | 285 | STACK_CHECK_START_REL(L, 0); |
286 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 286 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
287 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) | 287 | if (U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
288 | { | 288 | { |
289 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 289 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
290 | lua_pushcfunction( L, U->on_state_create_func); // on_state_create() | 290 | lua_pushcfunction(L, U->on_state_create_func); // on_state_create() |
291 | } | 291 | } |
292 | else // Lua function located in the config table, copied when we opened "lanes.core" | 292 | else // Lua function located in the config table, copied when we opened "lanes.core" |
293 | { | 293 | { |
294 | if( mode_ != eLM_LaneBody) | 294 | if (mode_ != eLM_LaneBody) |
295 | { | 295 | { |
296 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there | 296 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there |
297 | // this doesn't count as an error though | 297 | // this doesn't count as an error though |
298 | STACK_CHECK(L, 0); | 298 | STACK_CHECK(L, 0); |
299 | return; | 299 | return; |
300 | } | 300 | } |
301 | CONFIG_REGKEY.query_registry(L); // {} | 301 | CONFIG_REGKEY.pushValue(L); // {} |
302 | STACK_CHECK( L, 1); | 302 | STACK_CHECK(L, 1); |
303 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() | 303 | lua_getfield(L, -1, "on_state_create"); // {} on_state_create() |
304 | lua_remove( L, -2); // on_state_create() | 304 | lua_remove(L, -2); // on_state_create() |
305 | } | 305 | } |
306 | STACK_CHECK( L, 1); | 306 | STACK_CHECK(L, 1); |
307 | // capture error and raise it in caller state | 307 | // capture error and raise it in caller state |
308 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 308 | if (lua_pcall(L, 0, 0, 0) != LUA_OK) |
309 | { | 309 | { |
310 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 310 | luaL_error(from_, "on_state_create failed: \"%s\"", lua_isstring(L, -1) ? lua_tostring(L, -1) : lua_typename(L, lua_type(L, -1))); |
311 | } | 311 | } |
312 | STACK_CHECK( L, 0); | 312 | STACK_CHECK(L, 0); |
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
@@ -339,7 +339,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
339 | STACK_CHECK(L, 0); | 339 | STACK_CHECK(L, 0); |
340 | 340 | ||
341 | // we'll need this every time we transfer some C function from/to this state | 341 | // we'll need this every time we transfer some C function from/to this state |
342 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); | 342 | LOOKUP_REGKEY.setValue(L, [](lua_State* L) { lua_newtable(L); }); |
343 | STACK_CHECK(L, 0); | 343 | STACK_CHECK(L, 0); |
344 | 344 | ||
345 | // neither libs (not even 'base') nor special init func: we are done | 345 | // neither libs (not even 'base') nor special init func: we are done |
diff --git a/src/tools.cpp b/src/tools.cpp index 52c70bc..98224ae 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -64,7 +64,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode | |||
64 | STACK_GROW(L, 3); | 64 | STACK_GROW(L, 3); |
65 | STACK_CHECK_START_REL(L, 0); | 65 | STACK_CHECK_START_REL(L, 0); |
66 | 66 | ||
67 | key_.query_registry(L); // {}|nil | 67 | key_.pushValue(L); // {}|nil |
68 | STACK_CHECK(L, 1); | 68 | STACK_CHECK(L, 1); |
69 | 69 | ||
70 | if (lua_isnil(L, -1)) | 70 | if (lua_isnil(L, -1)) |
@@ -72,7 +72,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode | |||
72 | lua_pop(L, 1); // | 72 | lua_pop(L, 1); // |
73 | lua_newtable(L); // {} | 73 | lua_newtable(L); // {} |
74 | // _R[key_] = {} | 74 | // _R[key_] = {} |
75 | key_.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // {} | 75 | key_.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // {} |
76 | STACK_CHECK(L, 1); | 76 | STACK_CHECK(L, 1); |
77 | 77 | ||
78 | // Set its metatable if requested | 78 | // Set its metatable if requested |
@@ -554,7 +554,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
554 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 554 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
555 | STACK_GROW( L, 3); | 555 | STACK_GROW( L, 3); |
556 | STACK_CHECK_START_REL(L, 0); | 556 | STACK_CHECK_START_REL(L, 0); |
557 | LOOKUP_REGKEY.query_registry(L); // {} | 557 | LOOKUP_REGKEY.pushValue(L); // {} |
558 | STACK_CHECK( L, 1); | 558 | STACK_CHECK( L, 1); |
559 | ASSERT_L( lua_istable( L, -1)); | 559 | ASSERT_L( lua_istable( L, -1)); |
560 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function | 560 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function |
@@ -570,7 +570,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
570 | } | 570 | } |
571 | else if( lua_type( L, in_base) == LUA_TTABLE) | 571 | else if( lua_type( L, in_base) == LUA_TTABLE) |
572 | { | 572 | { |
573 | lua_newtable( L); // {} {fqn} | 573 | lua_newtable(L); // {} {fqn} |
574 | if( name_) | 574 | if( name_) |
575 | { | 575 | { |
576 | STACK_CHECK( L, 2); | 576 | STACK_CHECK( L, 2); |
@@ -584,12 +584,12 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
584 | STACK_CHECK( L, 2); | 584 | STACK_CHECK( L, 2); |
585 | } | 585 | } |
586 | // retrieve the cache, create it if we haven't done it yet | 586 | // retrieve the cache, create it if we haven't done it yet |
587 | LOOKUPCACHE_REGKEY.query_registry(L); // {} {fqn} {cache}? | 587 | LOOKUPCACHE_REGKEY.pushValue(L); // {} {fqn} {cache}? |
588 | if( lua_isnil( L, -1)) | 588 | if( lua_isnil( L, -1)) |
589 | { | 589 | { |
590 | lua_pop( L, 1); // {} {fqn} | 590 | lua_pop( L, 1); // {} {fqn} |
591 | lua_newtable( L); // {} {fqn} {cache} | 591 | lua_newtable( L); // {} {fqn} {cache} |
592 | LOOKUPCACHE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 592 | LOOKUPCACHE_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
593 | STACK_CHECK( L, 3); | 593 | STACK_CHECK( L, 3); |
594 | } | 594 | } |
595 | // process everything we find in that table, filling in lookup data for all functions and tables we see there | 595 | // process everything we find in that table, filling in lookup data for all functions and tables we see there |
@@ -698,7 +698,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char | |||
698 | else | 698 | else |
699 | { | 699 | { |
700 | // fetch the name from the source state's lookup table | 700 | // fetch the name from the source state's lookup table |
701 | LOOKUP_REGKEY.query_registry(L); // ... v ... {} | 701 | LOOKUP_REGKEY.pushValue(L); // ... v ... {} |
702 | STACK_CHECK( L, 1); | 702 | STACK_CHECK( L, 1); |
703 | ASSERT_L( lua_istable( L, -1)); | 703 | ASSERT_L( lua_istable( L, -1)); |
704 | lua_pushvalue( L, i); // ... v ... {} v | 704 | lua_pushvalue( L, i); // ... v ... {} v |
@@ -771,7 +771,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c | |||
771 | 771 | ||
772 | case eLM_LaneBody: | 772 | case eLM_LaneBody: |
773 | case eLM_FromKeeper: | 773 | case eLM_FromKeeper: |
774 | LOOKUP_REGKEY.query_registry(L2); // {} | 774 | LOOKUP_REGKEY.pushValue(L2); // {} |
775 | STACK_CHECK( L2, 1); | 775 | STACK_CHECK( L2, 1); |
776 | ASSERT_L( lua_istable( L2, -1)); | 776 | ASSERT_L( lua_istable( L2, -1)); |
777 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 777 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
@@ -1072,7 +1072,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo | |||
1072 | 1072 | ||
1073 | case eLM_LaneBody: | 1073 | case eLM_LaneBody: |
1074 | case eLM_FromKeeper: | 1074 | case eLM_FromKeeper: |
1075 | LOOKUP_REGKEY.query_registry(L2); // {} | 1075 | LOOKUP_REGKEY.pushValue(L2); // {} |
1076 | STACK_CHECK( L2, 1); | 1076 | STACK_CHECK( L2, 1); |
1077 | ASSERT_L( lua_istable( L2, -1)); | 1077 | ASSERT_L( lua_istable( L2, -1)); |
1078 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1078 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
diff --git a/src/uniquekey.h b/src/uniquekey.h index 93aaf37..bd3b61f 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
@@ -31,7 +31,7 @@ class UniqueKey | |||
31 | return m_storage == rhs_.m_storage; | 31 | return m_storage == rhs_.m_storage; |
32 | } | 32 | } |
33 | 33 | ||
34 | void push(lua_State* const L) const | 34 | void pushKey(lua_State* const L) const |
35 | { | 35 | { |
36 | lua_pushlightuserdata(L, std::bit_cast<void*>(m_storage)); | 36 | lua_pushlightuserdata(L, std::bit_cast<void*>(m_storage)); |
37 | } | 37 | } |
@@ -39,17 +39,38 @@ class UniqueKey | |||
39 | { | 39 | { |
40 | return lua_touserdata(L, i) == std::bit_cast<void*>(m_storage); | 40 | return lua_touserdata(L, i) == std::bit_cast<void*>(m_storage); |
41 | } | 41 | } |
42 | void query_registry(lua_State* const L) const | 42 | void pushValue(lua_State* const L) const |
43 | { | 43 | { |
44 | push(L); | 44 | pushKey(L); |
45 | lua_rawget(L, LUA_REGISTRYINDEX); | 45 | lua_rawget(L, LUA_REGISTRYINDEX); |
46 | } | 46 | } |
47 | template <typename OP> | 47 | template <typename OP> |
48 | void set_registry(lua_State* L, OP operation_) const | 48 | void setValue(lua_State* L, OP operation_) const |
49 | { | 49 | { |
50 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) | 50 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) |
51 | push(L); // ... key | 51 | pushKey(L); // ... key |
52 | operation_(L); // ... key value | 52 | operation_(L); // ... key value |
53 | lua_rawset(L, LUA_REGISTRYINDEX); // ... | 53 | lua_rawset(L, LUA_REGISTRYINDEX); // ... |
54 | } | 54 | } |
55 | template <typename T> | ||
56 | T* readLightUserDataValue(lua_State* const L) const | ||
57 | { | ||
58 | STACK_GROW(L, 1); | ||
59 | STACK_CHECK_START_REL(L, 0); | ||
60 | pushValue(L); | ||
61 | T* const value{ lua_tolightuserdata<T>(L, -1) }; // lightuserdata/nil | ||
62 | lua_pop(L, 1); | ||
63 | STACK_CHECK(L, 0); | ||
64 | return value; | ||
65 | } | ||
66 | bool readBoolValue(lua_State* const L) const | ||
67 | { | ||
68 | STACK_GROW(L, 1); | ||
69 | STACK_CHECK_START_REL(L, 0); | ||
70 | pushValue(L); | ||
71 | bool const value{ lua_toboolean(L, -1) ? true : false}; // bool/nil | ||
72 | lua_pop(L, 1); | ||
73 | STACK_CHECK(L, 0); | ||
74 | return value; | ||
75 | } | ||
55 | }; | 76 | }; |
diff --git a/src/universe.cpp b/src/universe.cpp index 3792da6..c487ac0 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -50,8 +50,8 @@ Universe* universe_create(lua_State* L) | |||
50 | Universe* const U = static_cast<Universe*>(lua_newuserdatauv(L, sizeof(Universe), 0)); // universe | 50 | Universe* const U = static_cast<Universe*>(lua_newuserdatauv(L, sizeof(Universe), 0)); // universe |
51 | U->Universe::Universe(); | 51 | U->Universe::Universe(); |
52 | STACK_CHECK_START_REL(L, 1); | 52 | STACK_CHECK_START_REL(L, 1); |
53 | UNIVERSE_FULL_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 53 | UNIVERSE_FULL_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
54 | UNIVERSE_LIGHT_REGKEY.set_registry(L, [U](lua_State* L) { lua_pushlightuserdata( L, U); }); | 54 | UNIVERSE_LIGHT_REGKEY.setValue(L, [U](lua_State* L) { lua_pushlightuserdata( L, U); }); |
55 | STACK_CHECK(L, 1); | 55 | STACK_CHECK(L, 1); |
56 | return U; | 56 | return U; |
57 | } | 57 | } |
@@ -62,7 +62,7 @@ void universe_store(lua_State* L, Universe* U) | |||
62 | { | 62 | { |
63 | ASSERT_L(universe_get(L) == nullptr); | 63 | ASSERT_L(universe_get(L) == nullptr); |
64 | STACK_CHECK_START_REL(L, 0); | 64 | STACK_CHECK_START_REL(L, 0); |
65 | UNIVERSE_LIGHT_REGKEY.set_registry(L, [U](lua_State* L) { U ? lua_pushlightuserdata( L, U) : lua_pushnil( L); }); | 65 | UNIVERSE_LIGHT_REGKEY.setValue(L, [U](lua_State* L) { U ? lua_pushlightuserdata( L, U) : lua_pushnil( L); }); |
66 | STACK_CHECK( L, 0); | 66 | STACK_CHECK( L, 0); |
67 | } | 67 | } |
68 | 68 | ||
@@ -70,11 +70,8 @@ void universe_store(lua_State* L, Universe* U) | |||
70 | 70 | ||
71 | Universe* universe_get(lua_State* L) | 71 | Universe* universe_get(lua_State* L) |
72 | { | 72 | { |
73 | STACK_GROW(L, 2); | ||
74 | STACK_CHECK_START_REL(L, 0); | 73 | STACK_CHECK_START_REL(L, 0); |
75 | UNIVERSE_LIGHT_REGKEY.query_registry(L); | 74 | Universe* const universe{ UNIVERSE_LIGHT_REGKEY.readLightUserDataValue<Universe>(L) }; |
76 | Universe* const universe{ lua_tolightuserdata<Universe>(L, -1) }; // nullptr if nil | 75 | STACK_CHECK( L, 0); |
77 | lua_pop(L, 1); | ||
78 | STACK_CHECK(L, 0); | ||
79 | return universe; | 76 | return universe; |
80 | } | 77 | } |