diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-03 09:46:16 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-03 09:46:16 +0200 |
commit | 420e50697cd036a0d8ea1601961bd6974703ade1 (patch) | |
tree | fd922454b4f94fb38333d3bd49679e01afb56fb5 /src | |
parent | f7a38b5681ebf7429828fca9a9f7c109df853d54 (diff) | |
download | lanes-420e50697cd036a0d8ea1601961bd6974703ade1.tar.gz lanes-420e50697cd036a0d8ea1601961bd6974703ade1.tar.bz2 lanes-420e50697cd036a0d8ea1601961bd6974703ade1.zip |
Clarified keeper.cpp stack tracking comments
Diffstat (limited to 'src')
-rw-r--r-- | src/keeper.cpp | 559 |
1 files changed, 294 insertions, 265 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index 26e5723..7a8a855 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -48,6 +48,12 @@ | |||
48 | #include <cassert> | 48 | #include <cassert> |
49 | #include <ranges> | 49 | #include <ranges> |
50 | 50 | ||
51 | // There is a table at _R[kLindasRegKey] (aka LindasDB) | ||
52 | // This table contains entries of the form [Linda*] = {KeysDB...} | ||
53 | // Each KeysDB contains entries of the form [key] = KeyUD | ||
54 | // where key is a key used in the Lua Linda API to exchange data, and KeyUD is a full userdata with a table uservalue | ||
55 | // the table uservalue is the actual fifo, where elements are added and removed. | ||
56 | |||
51 | // ################################################################################################# | 57 | // ################################################################################################# |
52 | // ################################################################################################# | 58 | // ################################################################################################# |
53 | // ############################################ KeyUD ############################################## | 59 | // ############################################ KeyUD ############################################## |
@@ -68,12 +74,12 @@ class KeyUD | |||
68 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 74 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
69 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } | 75 | static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } |
70 | 76 | ||
71 | [[nodiscard]] static KeyUD* GetPtr(lua_State* L_, int idx_); | 77 | [[nodiscard]] static KeyUD* GetPtr(KeeperState K_, int idx_); |
72 | [[nodiscard]] static KeyUD* Create(KeeperState L_); | 78 | [[nodiscard]] static KeyUD* Create(KeeperState K_); |
73 | [[nodiscard]] static KeyUD* PrepareAccess(lua_State* L_, int idx_); | 79 | [[nodiscard]] static KeyUD* PrepareAccess(KeeperState K_, int idx_); |
74 | void peek(lua_State* L_, int count_); | 80 | void peek(KeeperState K_, int count_); |
75 | void pop(lua_State* L_, int count_); | 81 | void pop(KeeperState K_, int count_); |
76 | void push(lua_State* L_, int count_); | 82 | void push(KeeperState K_, int count_); |
77 | }; | 83 | }; |
78 | 84 | ||
79 | static constexpr int kContentsTableIndex{ 1 }; | 85 | static constexpr int kContentsTableIndex{ 1 }; |
@@ -82,38 +88,38 @@ static constexpr int kContentsTableIndex{ 1 }; | |||
82 | 88 | ||
83 | // in: nothing | 89 | // in: nothing |
84 | // out: { first = 1, count = 0, limit = -1} | 90 | // out: { first = 1, count = 0, limit = -1} |
85 | KeyUD* KeyUD::Create(KeeperState const L_) | 91 | KeyUD* KeyUD::Create(KeeperState const K_) |
86 | { | 92 | { |
87 | STACK_GROW(L_, 2); | 93 | STACK_GROW(K_, 2); |
88 | STACK_CHECK_START_REL(L_, 0); | 94 | STACK_CHECK_START_REL(K_, 0); |
89 | KeyUD* const _key{ new (L_) KeyUD{} }; | 95 | KeyUD* const _key{ new (K_) KeyUD{} }; |
90 | STACK_CHECK(L_, 1); | 96 | STACK_CHECK(K_, 1); |
91 | lua_newtable(L_); | 97 | lua_newtable(K_); |
92 | lua_setiuservalue(L_, -2, kContentsTableIndex); | 98 | lua_setiuservalue(K_, -2, kContentsTableIndex); |
93 | STACK_CHECK(L_, 1); | 99 | STACK_CHECK(K_, 1); |
94 | return _key; | 100 | return _key; |
95 | } | 101 | } |
96 | 102 | ||
97 | // ################################################################################################# | 103 | // ################################################################################################# |
98 | 104 | ||
99 | KeyUD* KeyUD::GetPtr(lua_State* L_, int idx_) | 105 | KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_) |
100 | { | 106 | { |
101 | return lua_tofulluserdata<KeyUD>(L_, idx_); | 107 | return lua_tofulluserdata<KeyUD>(K_, idx_); |
102 | } | 108 | } |
103 | 109 | ||
104 | 110 | ||
105 | // ################################################################################################# | 111 | // ################################################################################################# |
106 | 112 | ||
107 | // replaces the fifo ud by its uservalue on the stack | 113 | // replaces the fifo ud by its uservalue on the stack |
108 | KeyUD* KeyUD::PrepareAccess(lua_State* const L_, int const idx_) | 114 | KeyUD* KeyUD::PrepareAccess(KeeperState const K_, int const idx_) |
109 | { | 115 | { |
110 | KeyUD* const _key{ KeyUD::GetPtr(L_, idx_) }; | 116 | KeyUD* const _key{ KeyUD::GetPtr(K_, idx_) }; |
111 | if (_key) { | 117 | if (_key) { |
112 | int const _idx{ lua_absindex(L_, idx_) }; | 118 | int const _idx{ lua_absindex(K_, idx_) }; |
113 | STACK_GROW(L_, 1); | 119 | STACK_GROW(K_, 1); |
114 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around | 120 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around |
115 | lua_getiuservalue(L_, _idx, kContentsTableIndex); | 121 | lua_getiuservalue(K_, _idx, kContentsTableIndex); |
116 | lua_replace(L_, _idx); | 122 | lua_replace(K_, _idx); |
117 | } | 123 | } |
118 | return _key; | 124 | return _key; |
119 | } | 125 | } |
@@ -125,11 +131,11 @@ KeyUD* KeyUD::PrepareAccess(lua_State* const L_, int const idx_) | |||
125 | // expects exactly 1 value on the stack! | 131 | // expects exactly 1 value on the stack! |
126 | // currently only called with a count of 1, but this may change in the future | 132 | // currently only called with a count of 1, but this may change in the future |
127 | // function assumes that there is enough data in the fifo to satisfy the request | 133 | // function assumes that there is enough data in the fifo to satisfy the request |
128 | void KeyUD::peek(lua_State* const L_, int const count_) | 134 | void KeyUD::peek(KeeperState const K_, int const count_) |
129 | { | 135 | { |
130 | STACK_GROW(L_, count_); | 136 | STACK_GROW(K_, count_); |
131 | for (int const _i : std::ranges::iota_view{ 0, count_ }) { | 137 | for (int const _i : std::ranges::iota_view{ 0, count_ }) { |
132 | lua_rawgeti(L_, 1, first + _i); | 138 | lua_rawgeti(K_, 1, first + _i); |
133 | } | 139 | } |
134 | } | 140 | } |
135 | 141 | ||
@@ -137,28 +143,28 @@ void KeyUD::peek(lua_State* const L_, int const count_) | |||
137 | 143 | ||
138 | // in: fifo | 144 | // in: fifo |
139 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) | 145 | // out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
140 | void KeyUD::pop(lua_State* const L_, int const count_) | 146 | void KeyUD::pop(KeeperState const K_, int const count_) |
141 | { | 147 | { |
142 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 148 | LUA_ASSERT(K_, lua_istable(K_, -1)); |
143 | int const _fifo_idx{ lua_gettop(L_) }; // L_: ... fifotbl | 149 | int const _fifo_idx{ lua_gettop(K_) }; // K_: ... fifotbl |
144 | // each iteration pushes a value on the stack! | 150 | // each iteration pushes a value on the stack! |
145 | STACK_GROW(L_, count_ + 2); | 151 | STACK_GROW(K_, count_ + 2); |
146 | // skip first item, we will push it last | 152 | // skip first item, we will push it last |
147 | for (int const _i : std::ranges::iota_view{ 1, count_ }) { | 153 | for (int const _i : std::ranges::iota_view{ 1, count_ }) { |
148 | int const _at{ first + _i }; | 154 | int const _at{ first + _i }; |
149 | // push item on the stack | 155 | // push item on the stack |
150 | lua_rawgeti(L_, _fifo_idx, _at); // L_: ... fifotbl val | 156 | lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifotbl val |
151 | // remove item from the fifo | 157 | // remove item from the fifo |
152 | lua_pushnil(L_); // L_: ... fifotbl val nil | 158 | lua_pushnil(K_); // K_: ... fifotbl val nil |
153 | lua_rawseti(L_, _fifo_idx, _at); // L_: ... fifotbl val | 159 | lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifotbl val |
154 | } | 160 | } |
155 | // now process first item | 161 | // now process first item |
156 | { | 162 | { |
157 | int const _at{ first }; | 163 | int const _at{ first }; |
158 | lua_rawgeti(L_, _fifo_idx, _at); // L_: ... fifotbl vals val | 164 | lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifotbl vals val |
159 | lua_pushnil(L_); // L_: ... fifotbl vals val nil | 165 | lua_pushnil(K_); // K_: ... fifotbl vals val nil |
160 | lua_rawseti(L_, _fifo_idx, _at); // L_: ... fifotbl vals val | 166 | lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifotbl vals val |
161 | lua_replace(L_, _fifo_idx); // L_: ... vals | 167 | lua_replace(K_, _fifo_idx); // K_: ... vals |
162 | } | 168 | } |
163 | 169 | ||
164 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty | 170 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty |
@@ -171,16 +177,16 @@ void KeyUD::pop(lua_State* const L_, int const count_) | |||
171 | 177 | ||
172 | // ################################################################################################# | 178 | // ################################################################################################# |
173 | 179 | ||
174 | // in: expect fifo ... on top of the stack | 180 | // in: expect fifo args... on top of the stack |
175 | // out: nothing, removes all pushed values from the stack | 181 | // out: nothing, removes all pushed values from the stack |
176 | void KeyUD::push(lua_State* const L_, int const count_) | 182 | void KeyUD::push(KeeperState const K_, int const count_) |
177 | { | 183 | { |
178 | int const _idx{ lua_gettop(L_) - count_ }; | 184 | int const _idx{ lua_gettop(K_) - count_ }; |
179 | int const _start{ first + count - 1 }; | 185 | int const _start{ first + count - 1 }; |
180 | // pop all additional arguments, storing them in the fifo | 186 | // pop all additional arguments, storing them in the fifo |
181 | for (int const _i : std::ranges::reverse_view{ std::ranges::iota_view{ 1, count_ + 1 } }) { | 187 | for (int const _i : std::ranges::reverse_view{ std::ranges::iota_view{ 1, count_ + 1 } }) { |
182 | // store in the fifo the value at the top of the stack at the specified index, popping it from the stack | 188 | // store in the fifo the value at the top of the stack at the specified index, popping it from the stack |
183 | lua_rawseti(L_, _idx, _start + _i); | 189 | lua_rawseti(K_, _idx, _start + _i); |
184 | } | 190 | } |
185 | count += count_; | 191 | count += count_; |
186 | } | 192 | } |
@@ -189,28 +195,28 @@ void KeyUD::push(lua_State* const L_, int const count_) | |||
189 | // ################################################################################################# | 195 | // ################################################################################################# |
190 | 196 | ||
191 | // in: linda_ud expected at stack slot idx | 197 | // in: linda_ud expected at stack slot idx |
192 | // out: fifos[ud] | 198 | // out: the KeysDB table of the linda is pushed at the top of the stack |
193 | // xxh64 of string "kFifosRegKey" generated at https://www.pelock.com/products/hash-calculator | 199 | // xxh64 of string "kLindasRegKey" generated at https://www.pelock.com/products/hash-calculator |
194 | static constexpr RegistryUniqueKey kFifosRegKey{ 0x37F11CE5A6D191AAull }; | 200 | static constexpr RegistryUniqueKey kLindasRegKey{ 0x3AE0D5243A88B962ull }; |
195 | static void push_table(lua_State* L_, int idx_) | 201 | static void PushKeysDB(KeeperState const K_, int const idx_) |
196 | { | 202 | { |
197 | STACK_GROW(L_, 5); | 203 | STACK_GROW(K_, 5); |
198 | STACK_CHECK_START_REL(L_, 0); | 204 | STACK_CHECK_START_REL(K_, 0); |
199 | idx_ = lua_absindex(L_, idx_); | 205 | int const _idx{ lua_absindex(K_, idx_) }; |
200 | kFifosRegKey.pushValue(L_); // L_: ud fifos | 206 | kLindasRegKey.pushValue(K_); // K_: ... LindasDB |
201 | lua_pushvalue(L_, idx_); // L_: ud fifos ud | 207 | lua_pushvalue(K_, _idx); // K_: ... LindasDB linda |
202 | lua_rawget(L_, -2); // L_: ud fifos fifos[ud] | 208 | lua_rawget(K_, -2); // K_: ... LindasDB KeysDB |
203 | STACK_CHECK(L_, 2); | 209 | STACK_CHECK(K_, 2); |
204 | if (lua_isnil(L_, -1)) { | 210 | if (lua_isnil(K_, -1)) { |
205 | lua_pop(L_, 1); // L_: ud fifos | 211 | lua_pop(K_, 1); // K_: ... LindasDB |
206 | // add a new fifos table for this linda | 212 | // add a new KeysDB table for this linda |
207 | lua_newtable(L_); // L_: ud fifos fifos[ud] | 213 | lua_newtable(K_); // K_: ... LindasDB KeysDB |
208 | lua_pushvalue(L_, idx_); // L_: ud fifos fifos[ud] ud | 214 | lua_pushvalue(K_, _idx); // K_: ... LindasDB KeysDB linda |
209 | lua_pushvalue(L_, -2); // L_: ud fifos fifos[ud] ud fifos[ud] | 215 | lua_pushvalue(K_, -2); // K_: ... LindasDB KeysDB linda KeysDB |
210 | lua_rawset(L_, -4); // L_: ud fifos fifos[ud] | 216 | lua_rawset(K_, -4); // K_: ... LindasDB KeysDB |
211 | } | 217 | } |
212 | lua_remove(L_, -2); // L_: ud fifos[ud] | 218 | lua_remove(K_, -2); // K_: ... KeysDB |
213 | STACK_CHECK(L_, 1); | 219 | STACK_CHECK(K_, 1); |
214 | } | 220 | } |
215 | 221 | ||
216 | // ################################################################################################# | 222 | // ################################################################################################# |
@@ -218,50 +224,56 @@ static void push_table(lua_State* L_, int idx_) | |||
218 | // only used by linda:dump() and linda:__towatch() for debugging purposes | 224 | // only used by linda:dump() and linda:__towatch() for debugging purposes |
219 | int keeper_push_linda_storage(Linda& linda_, DestState L_) | 225 | int keeper_push_linda_storage(Linda& linda_, DestState L_) |
220 | { | 226 | { |
221 | Keeper* const _K{ linda_.whichKeeper() }; | 227 | Keeper* const _keeper{ linda_.whichKeeper() }; |
222 | SourceState const _KL{ _K ? _K->L : nullptr }; | 228 | KeeperState const _K{ _keeper ? _keeper->L : nullptr }; |
223 | if (_KL == nullptr) | 229 | if (_K == nullptr) { |
224 | return 0; | 230 | return 0; |
225 | STACK_GROW(_KL, 4); | 231 | } |
226 | STACK_CHECK_START_REL(_KL, 0); | 232 | STACK_GROW(_K, 4); |
227 | kFifosRegKey.pushValue(_KL); // KL: fifos L_: | 233 | STACK_CHECK_START_REL(_K, 0); |
228 | lua_pushlightuserdata(_KL, &linda_); // KL: fifos ud L_: | 234 | kLindasRegKey.pushValue(_K); // _K: LindasDB L_: |
229 | lua_rawget(_KL, -2); // KL: fifos storage L_: | 235 | lua_pushlightuserdata(_K, &linda_); // _K: LindasDB linda L_: |
230 | lua_remove(_KL, -2); // KL: storage L_: | 236 | lua_rawget(_K, -2); // _K: LindasDB KeysDB L_: |
231 | if (!lua_istable(_KL, -1)) { | 237 | lua_remove(_K, -2); // _K: KeysDB L_: |
232 | lua_pop(_KL, 1); // KL: L_: | 238 | if (!lua_istable(_K, -1)) { // possible if we didn't send anything through that linda |
233 | STACK_CHECK(_KL, 0); | 239 | lua_pop(_K, 1); // _K: L_: |
240 | STACK_CHECK(_K, 0); | ||
234 | return 0; | 241 | return 0; |
235 | } | 242 | } |
236 | // move data from keeper to destination state | 243 | // move data from keeper to destination state |
237 | STACK_GROW(L_, 5); | 244 | STACK_GROW(L_, 5); |
238 | STACK_CHECK_START_REL(L_, 0); | 245 | STACK_CHECK_START_REL(L_, 0); |
239 | lua_newtable(L_); // KL: storage L_: out | 246 | lua_newtable(L_); // _K: KeysDB L_: out |
240 | InterCopyContext _c{ linda_.U, L_, _KL, {}, {}, {}, LookupMode::FromKeeper, {} }; | 247 | InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} }; |
241 | lua_pushnil(_KL); // KL: storage nil L_: out | 248 | lua_pushnil(_K); // _K: KeysDB nil L_: out |
242 | while (lua_next(_KL, -2)) { // KL: storage key fifo L_: out | 249 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out |
243 | KeyUD* const _keyUD{ KeyUD::PrepareAccess(_KL, -1) }; // KL: storage key fifotbl L_: out | 250 | KeyUD* const _keyUD{ KeyUD::PrepareAccess(_K, -1) }; // _K: KeysDB key fifo L_: out |
244 | lua_pushvalue(_KL, -2); // KL: storage key fifotbl key L_: out | 251 | lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out |
245 | std::ignore = _c.inter_move(1); // KL: storage key fifotbl L_: out key | 252 | std::ignore = _c.inter_move(1); // _K: KeysDB key fifo L_: out key |
246 | STACK_CHECK(L_, 2); | 253 | STACK_CHECK(L_, 2); |
247 | lua_newtable(L_); // KL: storage key L_: out key keyout | 254 | lua_newtable(L_); // _K: KeysDB key fifo L_: out key keyout |
248 | std::ignore = _c.inter_move(1); // KL: storage key L_: out key keyout fifotbl | 255 | std::ignore = _c.inter_move(1); // _K: KeysDB key L_: out key keyout fifo |
249 | lua_pushinteger(L_, _keyUD->first); // KL: storage key L_: out key keyout fifotbl first | 256 | // keyout.first |
257 | lua_pushinteger(L_, _keyUD->first); // _K: KeysDB key L_: out key keyout fifo first | ||
250 | STACK_CHECK(L_, 5); | 258 | STACK_CHECK(L_, 5); |
251 | lua_setfield(L_, -3, "first"); // KL: storage key L_: out key keyout fifotbl | 259 | lua_setfield(L_, -3, "first"); // _K: KeysDB key L_: out key keyout fifo |
252 | lua_pushinteger(L_, _keyUD->count); // KL: storage key L_: out key keyout fifobtl count | 260 | // keyout.count |
261 | lua_pushinteger(L_, _keyUD->count); // _K: KeysDB key L_: out key keyout fifo count | ||
253 | STACK_CHECK(L_, 5); | 262 | STACK_CHECK(L_, 5); |
254 | lua_setfield(L_, -3, "count"); // KL: storage key L_: out key keyout fifotbl | 263 | lua_setfield(L_, -3, "count"); // _K: KeysDB key L_: out key keyout fifo |
255 | lua_pushinteger(L_, _keyUD->limit); // KL: storage key L_: out key keyout fifotbl limit | 264 | // keyout.limit |
265 | lua_pushinteger(L_, _keyUD->limit); // _K: KeysDB key L_: out key keyout fifo limit | ||
256 | STACK_CHECK(L_, 5); | 266 | STACK_CHECK(L_, 5); |
257 | lua_setfield(L_, -3, "limit"); // KL: storage key L_: out key keyout fifotbl | 267 | lua_setfield(L_, -3, "limit"); // _K: KeysDB key L_: out key keyout fifo |
258 | lua_setfield(L_, -2, "fifo"); // KL: storage key L_: out key keyout | 268 | // keyout.fifo |
259 | lua_rawset(L_, -3); // KL: storage key L_: out | 269 | lua_setfield(L_, -2, "fifo"); // _K: KeysDB key L_: out key keyout |
270 | // out[key] = keyout | ||
271 | lua_rawset(L_, -3); // _K: KeysDB key L_: out | ||
260 | STACK_CHECK(L_, 1); | 272 | STACK_CHECK(L_, 1); |
261 | } // KL_: storage L_: out | 273 | } // _K: KeysDB L_: out |
262 | STACK_CHECK(L_, 1); | 274 | STACK_CHECK(L_, 1); |
263 | lua_pop(_KL, 1); // KL: L_: out | 275 | lua_pop(_K, 1); // _K: L_: out |
264 | STACK_CHECK(_KL, 0); | 276 | STACK_CHECK(_K, 0); |
265 | return 1; | 277 | return 1; |
266 | } | 278 | } |
267 | 279 | ||
@@ -271,16 +283,17 @@ int keeper_push_linda_storage(Linda& linda_, DestState L_) | |||
271 | // ################################################################################################# | 283 | // ################################################################################################# |
272 | // ################################################################################################# | 284 | // ################################################################################################# |
273 | 285 | ||
274 | // in: linda_ud | 286 | // in: linda |
275 | int keepercall_clear(lua_State* const L_) | 287 | int keepercall_clear(lua_State* const L_) |
276 | { | 288 | { |
277 | STACK_GROW(L_, 3); | 289 | STACK_GROW(L_, 3); |
278 | STACK_CHECK_START_REL(L_, 0); | 290 | STACK_CHECK_START_REL(L_, 0); |
279 | kFifosRegKey.pushValue(L_); // L_: ud fifos | 291 | // LindasDB[linda] = nil |
280 | lua_pushvalue(L_, 1); // L_: ud fifos ud | 292 | kLindasRegKey.pushValue(L_); // L_: linda LindasDB |
281 | lua_pushnil(L_); // L_: ud fifos ud nil | 293 | lua_pushvalue(L_, 1); // L_: linda LindasDB linda |
282 | lua_rawset(L_, -3); // L_: ud fifos | 294 | lua_pushnil(L_); // L_: linda LindasDB linda nil |
283 | lua_pop(L_, 1); // L_: ud | 295 | lua_rawset(L_, -3); // L_: linda LindasDB |
296 | lua_pop(L_, 1); // L_: linda | ||
284 | STACK_CHECK(L_, 0); | 297 | STACK_CHECK(L_, 0); |
285 | return 0; | 298 | return 0; |
286 | } | 299 | } |
@@ -291,61 +304,68 @@ int keepercall_clear(lua_State* const L_) | |||
291 | // out: true|false | 304 | // out: true|false |
292 | int keepercall_send(lua_State* const L_) | 305 | int keepercall_send(lua_State* const L_) |
293 | { | 306 | { |
294 | int const _n{ lua_gettop(L_) - 2 }; | 307 | KeeperState const _K{ L_ }; |
295 | push_table(L_, 1); // L_: ud key ... fifos | 308 | int const _n{ lua_gettop(_K) - 2 }; |
309 | STACK_CHECK_START_REL(_K, 0); | ||
310 | PushKeysDB(_K, 1); // _K: linda key args... KeysDB | ||
296 | // get the fifo associated to this key in this linda, create it if it doesn't exist | 311 | // get the fifo associated to this key in this linda, create it if it doesn't exist |
297 | lua_pushvalue(L_, 2); // L_: ud key ... fifos key | 312 | lua_pushvalue(_K, 2); // _K: linda key args... KeysDB key |
298 | lua_rawget(L_, -2); // L_: ud key ... fifos fifo | 313 | lua_rawget(_K, -2); // _K: linda key args... KeysDB KeyUD|nil |
299 | if (lua_isnil(L_, -1)) { | 314 | if (lua_isnil(_K, -1)) { |
300 | lua_pop(L_, 1); // L_: ud key ... fifos | 315 | lua_pop(_K, 1); // _K: linda key args... KeysDB |
301 | std::ignore = KeyUD::Create(KeeperState{ L_ }); // L_: ud key ... fifos fifo | 316 | std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key args... KeysDB KeyUD |
302 | lua_pushvalue(L_, 2); // L_: ud key ... fifos fifo key | 317 | // KeysDB[key] = KeyUD |
303 | lua_pushvalue(L_, -2); // L_: ud key ... fifos fifo key fifo | 318 | lua_pushvalue(_K, 2); // _K: linda key args... KeysDB KeyUD key |
304 | lua_rawset(L_, -4); // L_: ud key ... fifos fifo | 319 | lua_pushvalue(_K, -2); // _K: linda key args... KeysDB KeyUD key KeyUD |
305 | } | 320 | lua_rawset(_K, -4); // _K: linda key args... KeysDB KeyUD |
306 | lua_remove(L_, -2); // L_: ud key ... fifo | 321 | } |
307 | KeyUD* _key{ KeyUD::GetPtr(L_, -1) }; | 322 | lua_remove(_K, -2); // _K: linda key args... KeyUD |
308 | if (_key->limit >= 0 && _key->count + _n > _key->limit) { | 323 | STACK_CHECK(_K, 1); |
309 | lua_settop(L_, 0); // L_: | 324 | KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; |
310 | lua_pushboolean(L_, 0); // L_:false | 325 | if (_key->limit >= 0 && _key->count + _n > _key->limit) { // not enough room? |
326 | // don't send anything | ||
327 | lua_settop(_K, 0); // _K: | ||
328 | lua_pushboolean(_K, 0); // _K: false | ||
311 | } else { | 329 | } else { |
312 | _key = KeyUD::PrepareAccess(L_, -1); // L_: ud fifotbl | 330 | // _key should remain unchanged |
313 | lua_replace(L_, 2); // L_: ud fifotbl ... | 331 | _key = KeyUD::PrepareAccess(_K, -1); // _K: linda key args... fifo |
314 | _key->push(L_, _n); // L_: ud fifotbl | 332 | lua_replace(_K, 2); // _K: linda fifo args... |
315 | lua_settop(L_, 0); // L_: | 333 | _key->push(_K, _n); // _K: linda fifo |
316 | lua_pushboolean(L_, 1); // L_: true | 334 | lua_settop(_K, 0); // _K: |
335 | lua_pushboolean(_K, 1); // _K: true | ||
317 | } | 336 | } |
318 | return 1; | 337 | return 1; |
319 | } | 338 | } |
320 | 339 | ||
321 | // ################################################################################################# | 340 | // ################################################################################################# |
322 | 341 | ||
323 | // in: linda_ud, key [, key]? | 342 | // in: linda, key [, key]? |
324 | // out: (key, val) or nothing | 343 | // out: (key, val) or nothing |
325 | int keepercall_receive(lua_State* const L_) | 344 | int keepercall_receive(lua_State* const L_) |
326 | { | 345 | { |
327 | int const _top{ lua_gettop(L_) }; | 346 | KeeperState const _K{ L_ }; |
328 | push_table(L_, 1); // L_: ud keys fifos | 347 | int const _top{ lua_gettop(_K) }; |
329 | lua_replace(L_, 1); // L_: fifos keys | 348 | PushKeysDB(_K, 1); // _K: linda keys... KeysDB |
349 | lua_replace(_K, 1); // _K: KeysDB keys... | ||
330 | 350 | ||
331 | for (int const _i : std::ranges::iota_view{ 2, _top + 1 }) { | 351 | for (int const _i : std::ranges::iota_view{ 2, _top + 1 }) { |
332 | lua_pushvalue(L_, _i); // L_: fifos keys key[i] | 352 | lua_pushvalue(_K, _i); // _K: KeysDB keys... key[i] |
333 | lua_rawget(L_, 1); // L_: fifos keys fifo | 353 | lua_rawget(_K, 1); // _K: KeysDB keys... KeyUD |
334 | KeyUD* const _key{ KeyUD::PrepareAccess(L_, -1) }; // L_: fifos keys fifotbl | 354 | KeyUD* const _key{ KeyUD::PrepareAccess(_K, -1) }; // _K: KeysDB keys... fifo |
335 | if (_key != nullptr && _key->count > 0) { | 355 | if (_key != nullptr && _key->count > 0) { |
336 | _key->pop(L_, 1); // L_: fifos keys val | 356 | _key->pop(_K, 1); // _K: KeysDB keys... val |
337 | if (!lua_isnil(L_, -1)) { | 357 | if (!lua_isnil(_K, -1)) { |
338 | lua_replace(L_, 1); // L_: val keys | 358 | lua_replace(_K, 1); // _K: val keys... |
339 | lua_settop(L_, _i); // L_: val keys key[i] | 359 | lua_settop(_K, _i); // _K: val keys... key[i] |
340 | if (_i != 2) { | 360 | if (_i != 2) { |
341 | lua_replace(L_, 2); // L_: val key keys | 361 | lua_replace(_K, 2); // _K: val key keys... |
342 | lua_settop(L_, 2); // L_: val key | 362 | lua_settop(_K, 2); // _K: val key |
343 | } | 363 | } |
344 | lua_insert(L_, 1); // L_: key, val | 364 | lua_insert(_K, 1); // _K: key, val |
345 | return 2; | 365 | return 2; |
346 | } | 366 | } |
347 | } | 367 | } |
348 | lua_settop(L_, _top); // L_: data keys | 368 | lua_settop(_K, _top); // _K: data keys... |
349 | } | 369 | } |
350 | // nothing to receive | 370 | // nothing to receive |
351 | return 0; | 371 | return 0; |
@@ -353,26 +373,28 @@ int keepercall_receive(lua_State* const L_) | |||
353 | 373 | ||
354 | // ################################################################################################# | 374 | // ################################################################################################# |
355 | 375 | ||
356 | // in: linda_ud key mincount [maxcount] | 376 | // in: linda key mincount [maxcount] |
357 | int keepercall_receive_batched(lua_State* const L_) | 377 | int keepercall_receive_batched(lua_State* const L_) |
358 | { | 378 | { |
359 | int const _min_count{ static_cast<int>(lua_tointeger(L_, 3)) }; | 379 | KeeperState const _K{ L_ }; |
380 | int const _min_count{ static_cast<int>(lua_tointeger(_K, 3)) }; | ||
360 | if (_min_count > 0) { | 381 | if (_min_count > 0) { |
361 | int const _max_count{ static_cast<int>(luaL_optinteger(L_, 4, _min_count)) }; | 382 | int const _max_count{ static_cast<int>(luaL_optinteger(_K, 4, _min_count)) }; |
362 | lua_settop(L_, 2); // L_: ud key | 383 | lua_settop(_K, 2); // _K: linda key |
363 | lua_insert(L_, 1); // L_: key ud | 384 | lua_insert(_K, 1); // _K: key linda |
364 | push_table(L_, 2); // L_: key ud fifos | 385 | PushKeysDB(_K, 2); // _K: key linda KeysDB |
365 | lua_remove(L_, 2); // L_: key fifos | 386 | lua_remove(_K, 2); // _K: key KeysDB |
366 | lua_pushvalue(L_, 1); // L_: key fifos key | 387 | lua_pushvalue(_K, 1); // _K: key KeysDB key |
367 | lua_rawget(L_, 2); // L_: key fifos fifo | 388 | lua_rawget(_K, 2); // _K: key KeysDB KeyUD |
368 | lua_remove(L_, 2); // L_: key fifo | 389 | lua_remove(_K, 2); // _K: key KeyUD |
369 | KeyUD* const _key{ KeyUD::PrepareAccess(L_, 2) }; // L_: key fifotbl | 390 | KeyUD* const _key{ KeyUD::PrepareAccess(_K, 2) }; // _K: key fifo |
370 | if (_key != nullptr && _key->count >= _min_count) { | 391 | if (_key != nullptr && _key->count >= _min_count) { |
371 | _key->pop(L_, std::min(_max_count, _key->count)); // L_: key ... | 392 | _key->pop(_K, std::min(_max_count, _key->count)); // _K: key val... |
372 | } else { | 393 | } else { |
373 | lua_settop(L_, 0); // L_: | 394 | lua_settop(_K, 0); // _K: |
374 | } | 395 | } |
375 | return lua_gettop(L_); | 396 | // return whatever remains on the stack at that point |
397 | return lua_gettop(_K); | ||
376 | } else { | 398 | } else { |
377 | return 0; | 399 | return 0; |
378 | } | 400 | } |
@@ -384,96 +406,99 @@ int keepercall_receive_batched(lua_State* const L_) | |||
384 | // out: true or nil | 406 | // out: true or nil |
385 | int keepercall_limit(lua_State* const L_) | 407 | int keepercall_limit(lua_State* const L_) |
386 | { | 408 | { |
387 | int const _limit{ static_cast<int>(luaL_optinteger(L_, 3, -1)) }; // -1 if we read nil because the argument is absent | 409 | KeeperState const _K{ L_ }; |
388 | push_table(L_, 1); // L_: ud key n? fifos | 410 | int const _limit{ static_cast<int>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent |
389 | lua_replace(L_, 1); // L_: fifos key n? | 411 | lua_settop(_K, 2); // _K: linda key |
390 | lua_settop(L_, 2); // L_: fifos key | 412 | PushKeysDB(_K, 1); // _K: linda key KeysDB |
391 | lua_pushvalue(L_, -1); // L_: fifos key key | 413 | lua_replace(_K, 1); // _K: KeysDB key |
392 | lua_rawget(L_, -3); // L_: fifos key fifo|nil | 414 | lua_pushvalue(_K, -1); // _K: KeysDB key key |
393 | KeyUD* _key{ KeyUD::GetPtr(L_, -1) }; | 415 | lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil |
394 | if (_key == nullptr) { // L_: fifos key nil | 416 | KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; |
395 | lua_pop(L_, 1); // L_: fifos key | 417 | if (_key == nullptr) { // _K: KeysDB key nil |
396 | _key = KeyUD::Create(KeeperState{ L_ }); // L_: fifos key fifo | 418 | lua_pop(_K, 1); // _K: KeysDB key |
397 | lua_rawset(L_, -3); // L_: fifos | 419 | _key = KeyUD::Create(_K); // _K: KeysDB key fifo |
420 | lua_rawset(_K, -3); // _K: KeysDB | ||
398 | } | 421 | } |
399 | // remove any clutter on the stack | 422 | // remove any clutter on the stack |
400 | lua_settop(L_, 0); // L_: | 423 | lua_settop(_K, 0); // _K: |
401 | // return true if we decide that blocked threads waiting to write on that key should be awakened | 424 | // return true if we decide that blocked threads waiting to write on that key should be awakened |
402 | // this is the case if we detect the key was full but it is no longer the case | 425 | // this is the case if we detect the key was full but it is no longer the case |
403 | if ( | 426 | if ( |
404 | ((_key->limit >= 0) && (_key->count >= _key->limit)) // the key was full if limited and count exceeded the previous limit | 427 | ((_key->limit >= 0) && (_key->count >= _key->limit)) // the key was full if limited and count exceeded the previous limit |
405 | && ((_limit < 0) || (_key->count < _limit)) // the key is not full if unlimited or count is lower than the new limit | 428 | && ((_limit < 0) || (_key->count < _limit)) // the key is not full if unlimited or count is lower than the new limit |
406 | ) { | 429 | ) { |
407 | lua_pushboolean(L_, 1); // L_: true | 430 | lua_pushboolean(_K, 1); // _K: true |
408 | } | 431 | } |
409 | // set the new limit | 432 | // set the new limit |
410 | _key->limit = _limit; | 433 | _key->limit = _limit; |
411 | // return 0 or 1 value | 434 | // return 0 or 1 value |
412 | return lua_gettop(L_); | 435 | return lua_gettop(_K); |
413 | } | 436 | } |
414 | 437 | ||
415 | // ################################################################################################# | 438 | // ################################################################################################# |
416 | 439 | ||
417 | // in: linda_ud key [[val] ...] | 440 | // in: linda key [val...] |
418 | // out: true if the linda was full but it's no longer the case, else nothing | 441 | // out: true if the linda was full but it's no longer the case, else nothing |
419 | int keepercall_set(lua_State* const L_) | 442 | int keepercall_set(lua_State* const L_) |
420 | { | 443 | { |
444 | KeeperState const _K{ L_ }; | ||
421 | bool _should_wake_writers{ false }; | 445 | bool _should_wake_writers{ false }; |
422 | STACK_GROW(L_, 6); | 446 | STACK_GROW(_K, 6); |
423 | 447 | ||
424 | // retrieve fifos associated with the linda | 448 | // retrieve fifos associated with the linda |
425 | push_table(L_, 1); // L_: ud key [val [, ...]] fifos | 449 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB |
426 | lua_replace(L_, 1); // L_: fifos key [val [, ...]] | 450 | lua_replace(_K, 1); // _K: KeysDB key val... |
427 | 451 | ||
428 | // make sure we have a value on the stack | 452 | // make sure we have a value on the stack |
429 | if (lua_gettop(L_) == 2) { // L_: fifos key | 453 | if (lua_gettop(_K) == 2) { // _K: KeysDB key |
430 | lua_pushvalue(L_, -1); // L_: fifos key key | 454 | lua_pushvalue(_K, -1); // _K: KeysDB key key |
431 | lua_rawget(L_, 1); // L_: fifos key fifo|nil | 455 | lua_rawget(_K, 1); // _K: KeysDB key KeyUD|nil |
432 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 456 | // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
433 | KeyUD* const _key{ KeyUD::GetPtr(L_, -1) }; | 457 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
434 | if (_key != nullptr) { // might be nullptr if we set a nonexistent key to nil // L_: fifos key fifo | 458 | if (_key != nullptr) { // might be nullptr if we set a nonexistent key to nil // _K: KeysDB key KeyUD |
435 | if (_key->limit < 0) { // fifo limit value is the default (unlimited): we can totally remove it | 459 | if (_key->limit < 0) { // KeyUD limit value is the default (unlimited): we can totally remove it |
436 | lua_pop(L_, 1); // L_: fifos key | 460 | lua_pop(_K, 1); // _K: KeysDB key |
437 | lua_pushnil(L_); // L_: fifos key nil | 461 | lua_pushnil(_K); // _K: KeysDB key nil |
438 | lua_rawset(L_, -3); // L_: fifos | 462 | lua_rawset(_K, -3); // _K: KeysDB |
439 | } else { | 463 | } else { |
440 | // we create room if the fifo was full but it is no longer the case | 464 | // we create room if the KeyUD was full but it is no longer the case |
441 | _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit); | 465 | _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit); |
442 | lua_remove(L_, -2); // L_: fifos fifo | 466 | lua_remove(_K, -2); // _K: KeysDB KeyUD |
443 | lua_newtable(L_); // L_: fifos fifo {} | 467 | lua_newtable(_K); // _K: KeysDB KeyUD {} |
444 | lua_setiuservalue(L_, -2, kContentsTableIndex); // L_: fifos fifo | 468 | lua_setiuservalue(_K, -2, kContentsTableIndex); // _K: KeysDB KeyUD |
445 | _key->first = 1; | 469 | _key->first = 1; |
446 | _key->count = 0; | 470 | _key->count = 0; |
447 | } | 471 | } |
448 | } | 472 | } |
449 | } else { // set/replace contents stored at the specified key? | 473 | } else { // set/replace contents stored at the specified key? |
450 | int const _count{ lua_gettop(L_) - 2 }; // number of items we want to store | 474 | int const _count{ lua_gettop(_K) - 2 }; // number of items we want to store |
451 | lua_pushvalue(L_, 2); // L_: fifos key [val [, ...]] key | 475 | lua_pushvalue(_K, 2); // _K: KeysDB key val... key |
452 | lua_rawget(L_, 1); // L_: fifos key [val [, ...]] fifo|nil | 476 | lua_rawget(_K, 1); // _K: KeysDB key val... KeyUD|nil |
453 | KeyUD* _key{ KeyUD::GetPtr(L_, -1) }; | 477 | KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; |
454 | if (_key == nullptr) { // can be nullptr if we store a value at a new key // fifos key [val [, ...]] nil | 478 | if (_key == nullptr) { // can be nullptr if we store a value at a new key // KeysDB key val... nil |
455 | // no need to wake writers in that case, because a writer can't wait on an inexistent key | 479 | // no need to wake writers in that case, because a writer can't wait on an inexistent key |
456 | lua_pop(L_, 1); // L_: fifos key [val [, ...]] | 480 | lua_pop(_K, 1); // _K: KeysDB key val... |
457 | std::ignore = KeyUD::Create(KeeperState{ L_ }); // L_: fifos key [val [, ...]] fifo | 481 | std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: KeysDB key val... KeyUD |
458 | lua_pushvalue(L_, 2); // L_: fifos key [val [, ...]] fifo key | 482 | lua_pushvalue(_K, 2); // _K: KeysDB key val... KeyUD key |
459 | lua_pushvalue(L_, -2); // L_: fifos key [val [, ...]] fifo key fifo | 483 | lua_pushvalue(_K, -2); // _K: KeysDB key val... KeyUD key KeyUD |
460 | lua_rawset(L_, 1); // L_: fifos key [val [, ...]] fifo | 484 | lua_rawset(_K, 1); // _K: KeysDB key val... KeyUD |
461 | } else { // L_: fifos key [val [, ...]] fifo | 485 | } else { // _K: KeysDB key val... KeyUD |
462 | // the fifo exists, we just want to update its contents | 486 | // the KeyUD exists, we just want to update its contents |
463 | // we create room if the fifo was full but it is no longer the case | 487 | // we create room if the KeyUD was full but it is no longer the case |
464 | _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit) && (_count < _key->limit); | 488 | _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit) && (_count < _key->limit); |
465 | // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! | 489 | // TODO: turn this into a KeyUD::reset() method |
466 | lua_newtable(L_); // L_: fifos key [val [, ...]] fifo {} | 490 | // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! |
467 | lua_setiuservalue(L_, -2, kContentsTableIndex); // L_: fifos key [val [, ...]] fifo | 491 | lua_newtable(_K); // _K: KeysDB key val... KeyUD {} |
492 | lua_setiuservalue(_K, -2, kContentsTableIndex); // _K: KeysDB key val... KeyUD | ||
468 | _key->first = 1; | 493 | _key->first = 1; |
469 | _key->count = 0; | 494 | _key->count = 0; |
470 | } | 495 | } |
471 | _key = KeyUD::PrepareAccess(L_, -1); // L_: fifos key [val [, ...]] fifotbl | 496 | _key = KeyUD::PrepareAccess(_K, -1); // _K: KeysDB key val... fifo |
472 | // move the fifo below the values we want to store | 497 | // move the fifo below the values we want to store |
473 | lua_insert(L_, 3); // L_: fifos key fifotbl [val [, ...]] | 498 | lua_insert(_K, 3); // _K: KeysDB key fifo val... |
474 | _key->push(L_, _count); // L_: fifos key fifotbl | 499 | _key->push(_K, _count); // _K: KeysDB key fifo |
475 | } | 500 | } |
476 | return _should_wake_writers ? (lua_pushboolean(L_, 1), 1) : 0; | 501 | return _should_wake_writers ? (lua_pushboolean(_K, 1), 1) : 0; |
477 | } | 502 | } |
478 | 503 | ||
479 | // ################################################################################################# | 504 | // ################################################################################################# |
@@ -482,20 +507,21 @@ int keepercall_set(lua_State* const L_) | |||
482 | // out: at most <count> values | 507 | // out: at most <count> values |
483 | int keepercall_get(lua_State* const L_) | 508 | int keepercall_get(lua_State* const L_) |
484 | { | 509 | { |
510 | KeeperState const _K{ L_ }; | ||
485 | int _count{ 1 }; | 511 | int _count{ 1 }; |
486 | if (lua_gettop(L_) == 3) { // L_: ud key count | 512 | if (lua_gettop(_K) == 3) { // _K: linda key count |
487 | _count = static_cast<int>(lua_tointeger(L_, 3)); | 513 | _count = static_cast<int>(lua_tointeger(_K, 3)); |
488 | lua_pop(L_, 1); // L_: ud key | 514 | lua_pop(_K, 1); // _K: linda key |
489 | } | 515 | } |
490 | push_table(L_, 1); // L_: ud key fifos | 516 | PushKeysDB(_K, 1); // _K: linda key KeyUD |
491 | lua_replace(L_, 1); // L_: fifos key | 517 | lua_replace(_K, 1); // _K: KeyUD key |
492 | lua_rawget(L_, 1); // L_: fifos fifo | 518 | lua_rawget(_K, 1); // _K: KeyUD fifo |
493 | KeyUD* const _key{ KeyUD::PrepareAccess(L_, -1) }; // L_: fifos fifotbl | 519 | KeyUD* const _key{ KeyUD::PrepareAccess(_K, -1) }; // _K: KeyUD fifo |
494 | if (_key != nullptr && _key->count > 0) { | 520 | if (_key != nullptr && _key->count > 0) { |
495 | lua_remove(L_, 1); // L_: fifotbl | 521 | lua_remove(_K, 1); // _K: fifo |
496 | _count = std::min(_count, _key->count); | 522 | _count = std::min(_count, _key->count); |
497 | // read <count> value off the fifo | 523 | // read <count> value off the fifo |
498 | _key->peek(L_, _count); // L_: fifotbl ... | 524 | _key->peek(_K, _count); // _K: fifo ... |
499 | return _count; | 525 | return _count; |
500 | } | 526 | } |
501 | // no fifo was ever registered for this key, or it is empty | 527 | // no fifo was ever registered for this key, or it is empty |
@@ -507,58 +533,61 @@ int keepercall_get(lua_State* const L_) | |||
507 | // in: linda_ud [, key [, ...]] | 533 | // in: linda_ud [, key [, ...]] |
508 | int keepercall_count(lua_State* const L_) | 534 | int keepercall_count(lua_State* const L_) |
509 | { | 535 | { |
510 | push_table(L_, 1); // L_: ud keys fifos | 536 | KeeperState const _K{ L_ }; |
511 | switch (lua_gettop(L_)) { | 537 | switch (lua_gettop(_K)) { |
512 | // no key is specified: return a table giving the count of all known keys | 538 | // no key is specified: return a table giving the count of all known keys |
513 | case 2: // L_: ud fifos | 539 | case 1: // _K: linda |
514 | lua_newtable(L_); // L_: ud fifos out | 540 | PushKeysDB(_K, 1); // _K: linda KeysDB |
515 | lua_replace(L_, 1); // L_: out fifos | 541 | lua_newtable(_K); // _K: linda KeysDB out |
516 | lua_pushnil(L_); // L_: out fifos nil | 542 | lua_replace(_K, 1); // _K: out KeysDB |
517 | while (lua_next(L_, 2)) { // L_: out fifos key fifo | 543 | lua_pushnil(_K); // _K: out KeysDB nil |
518 | KeyUD* const _key{ KeyUD::GetPtr(L_, -1) }; | 544 | while (lua_next(_K, 2)) { // _K: out KeysDB key KeyUD |
519 | lua_pop(L_, 1); // L_: out fifos key | 545 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
520 | lua_pushvalue(L_, -1); // L_: out fifos key key | 546 | lua_pop(_K, 1); // _K: out KeysDB key |
521 | lua_pushinteger(L_, _key->count); // L_: out fifos key key count | 547 | lua_pushvalue(_K, -1); // _K: out KeysDB key key |
522 | lua_rawset(L_, -5); // L_: out fifos key | 548 | lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count |
549 | lua_rawset(_K, -5); // _K: out KeysDB key | ||
523 | } | 550 | } |
524 | lua_pop(L_, 1); // L_: out | 551 | lua_pop(_K, 1); // _K: out |
525 | break; | 552 | break; |
526 | 553 | ||
527 | // 1 key is specified: return its count | 554 | // 1 key is specified: return its count |
528 | case 3: // L_: ud key fifos | 555 | case 2: // _K: linda key |
529 | lua_replace(L_, 1); // L_: fifos key | 556 | PushKeysDB(_K, 1); // _K: linda key KeysDB |
530 | lua_rawget(L_, -2); // L_: fifos fifo|nil | 557 | lua_replace(_K, 1); // _K: KeysDB key |
531 | if (lua_isnil(L_, -1)) { // L_: the key is unknown // L_: fifos nil | 558 | lua_rawget(_K, -2); // _K: KeysDB KeyUD|nil |
532 | lua_remove(L_, -2); // L_: nil | 559 | if (lua_isnil(_K, -1)) { // the key is unknown // _K: KeysDB nil |
533 | } else { // the key is known // L_: fifos fifo | 560 | lua_remove(_K, -2); // _K: nil |
534 | KeyUD* const _key{ KeyUD::GetPtr(L_, -1) }; | 561 | } else { // the key is known // _K: KeysDB KeyUD |
535 | lua_pushinteger(L_, _key->count); // L_: fifos fifo count | 562 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
536 | lua_replace(L_, -3); // L_: count fifo | 563 | lua_pushinteger(_K, _key->count); // _K: KeysDB KeyUD count |
537 | lua_pop(L_, 1); // L_: count | 564 | lua_replace(_K, -3); // _K: count KeyUD |
565 | lua_pop(_K, 1); // _K: count | ||
538 | } | 566 | } |
539 | break; | 567 | break; |
540 | 568 | ||
541 | // a variable number of keys is specified: return a table of their counts | 569 | // a variable number of keys is specified: return a table of their counts |
542 | default: // ud keys fifos | 570 | default: // _K: linda keys... key#1 |
543 | lua_newtable(L_); // L_: ud keys... fifos out | 571 | lua_pushvalue(_K, 2); // duplicate the first key of the list // _K: linda keys... key#1 |
544 | lua_replace(L_, 1); // L_: out keys... fifos | 572 | PushKeysDB(_K, 1); // _K: linda keys... key#1 KeysDB |
545 | // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable | 573 | lua_newtable(_K); // _K: linda keys... key#1 KeysDB out |
546 | lua_insert(L_, 2); // L_: out fifos keys... | 574 | lua_replace(_K, 1); // _K: out keys... key#1 KeysDB |
547 | while (lua_gettop(L_) > 2) { | 575 | lua_replace(_K, 2); // the list of keys is the same, but for key#1 moved at the end // _K: out KeysDB keys... |
548 | lua_pushvalue(L_, -1); // L_: out fifos keys... key | 576 | while (lua_gettop(_K) > 2) { |
549 | lua_rawget(L_, 2); // L_: out fifos keys... fifo|nil | 577 | lua_pushvalue(_K, -1); // _K: out KeysDB keys... key |
550 | KeyUD* const _key{ KeyUD::GetPtr(L_, -1) }; | 578 | lua_rawget(_K, 2); // _K: out KeysDB keys... KeyUD|nil |
551 | lua_pop(L_, 1); // L_: out fifos keys... | 579 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
552 | if (_key != nullptr) { // L_: the key is known | 580 | lua_pop(_K, 1); // _K: out KeysDB keys... |
553 | lua_pushinteger(L_, _key->count); // L_: out fifos keys... count | 581 | if (_key != nullptr) { // the key is known |
554 | lua_rawset(L_, 1); // L_: out fifos keys... | 582 | lua_pushinteger(_K, _key->count); // _K: out KeysDB keys... count |
555 | } else { // the key is unknown | 583 | lua_rawset(_K, 1); // _K: out KeysDB keys... |
556 | lua_pop(L_, 1); // L_: out fifos keys... | 584 | } else { // the key is unknown |
585 | lua_pop(_K, 1); // _K: out KeysDB keys... | ||
557 | } | 586 | } |
558 | } // all keys are exhausted // L_: out fifos | 587 | } // all keys are exhausted // _K: out KeysDB |
559 | lua_pop(L_, 1); // L_: out | 588 | lua_pop(_K, 1); // _K: out |
560 | } | 589 | } |
561 | LUA_ASSERT(L_, lua_gettop(L_) == 1); | 590 | LUA_ASSERT(_K, lua_gettop(_K) == 1); |
562 | return 1; | 591 | return 1; |
563 | } | 592 | } |
564 | 593 | ||
@@ -760,7 +789,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
760 | auto _initOneKeeper = [U = &U_, L = L_, gc_threshold = gc_threshold](Keeper& keeper_, int const i_) { | 789 | auto _initOneKeeper = [U = &U_, L = L_, gc_threshold = gc_threshold](Keeper& keeper_, int const i_) { |
761 | STACK_CHECK_START_REL(L, 0); | 790 | STACK_CHECK_START_REL(L, 0); |
762 | // note that we will leak K if we raise an error later | 791 | // note that we will leak K if we raise an error later |
763 | KeeperState const _K{ state::CreateState(U, L) }; // L: settings K: | 792 | KeeperState const _K{ state::CreateState(U, L) }; // L_: settings _K: |
764 | if (_K == nullptr) { | 793 | if (_K == nullptr) { |
765 | raise_luaL_error(L, "out of memory while creating keeper states"); | 794 | raise_luaL_error(L, "out of memory while creating keeper states"); |
766 | } | 795 | } |
@@ -768,12 +797,12 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
768 | keeper_.L = _K; | 797 | keeper_.L = _K; |
769 | 798 | ||
770 | // Give a name to the state | 799 | // Give a name to the state |
771 | lua_pushfstring(_K, "Keeper #%d", i_ + 1); // L: settings K: "Keeper #n" | 800 | lua_pushfstring(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n" |
772 | if constexpr (HAVE_DECODA_SUPPORT()) { | 801 | if constexpr (HAVE_DECODA_SUPPORT()) { |
773 | lua_pushvalue(_K, -1); // K: "Keeper #n" Keeper #n" | 802 | lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" |
774 | lua_setglobal(_K, "decoda_name"); // L: settings K: "Keeper #n" | 803 | lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" |
775 | } | 804 | } |
776 | kLaneNameRegKey.setValue(_K, [](lua_State* L_) { lua_insert(L_, -2); }); // K: | 805 | kLaneNameRegKey.setValue(_K, [](lua_State* L_) { lua_insert(L_, -2); }); // _K: |
777 | 806 | ||
778 | STACK_CHECK_START_ABS(_K, 0); | 807 | STACK_CHECK_START_ABS(_K, 0); |
779 | 808 | ||
@@ -783,23 +812,23 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
783 | 812 | ||
784 | // make sure 'package' is initialized in keeper states, so that we have require() | 813 | // make sure 'package' is initialized in keeper states, so that we have require() |
785 | // this because this is needed when transferring deep userdata object | 814 | // this because this is needed when transferring deep userdata object |
786 | luaL_requiref(_K, LUA_LOADLIBNAME, luaopen_package, 1); // L: settings K: package | 815 | luaL_requiref(_K, LUA_LOADLIBNAME, luaopen_package, 1); // L_: settings _K: package |
787 | lua_pop(_K, 1); // L: settings K: | 816 | lua_pop(_K, 1); // L_: settings _K: |
788 | STACK_CHECK(_K, 0); | 817 | STACK_CHECK(_K, 0); |
789 | tools::SerializeRequire(_K); | 818 | tools::SerializeRequire(_K); |
790 | STACK_CHECK(_K, 0); | 819 | STACK_CHECK(_K, 0); |
791 | 820 | ||
792 | // copy package.path and package.cpath from the source state | 821 | // copy package.path and package.cpath from the source state |
793 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L: settings package K: | 822 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: |
794 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 823 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
795 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ lua_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; | 824 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ lua_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; |
796 | if (_c.inter_copy_package() != InterCopyResult::Success) { // L: settings ... error_msg K: | 825 | if (_c.inter_copy_package() != InterCopyResult::Success) { // L_: settings ... error_msg _K: |
797 | // if something went wrong, the error message is at the top of the stack | 826 | // if something went wrong, the error message is at the top of the stack |
798 | lua_remove(L, -2); // L: settings error_msg | 827 | lua_remove(L, -2); // L_: settings error_msg |
799 | raise_lua_error(L); | 828 | raise_lua_error(L); |
800 | } | 829 | } |
801 | } | 830 | } |
802 | lua_pop(L, 1); // L: settings K: | 831 | lua_pop(L, 1); // L_: settings _K: |
803 | STACK_CHECK(L, 0); | 832 | STACK_CHECK(L, 0); |
804 | STACK_CHECK(_K, 0); | 833 | STACK_CHECK(_K, 0); |
805 | 834 | ||
@@ -808,8 +837,8 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
808 | // will raise an error in L_ in case of problem | 837 | // will raise an error in L_ in case of problem |
809 | state::CallOnStateCreate(U, _K, L, LookupMode::ToKeeper); | 838 | state::CallOnStateCreate(U, _K, L, LookupMode::ToKeeper); |
810 | 839 | ||
811 | // create the fifos table in the keeper state | 840 | // _R[kLindasRegKey] = {} |
812 | kFifosRegKey.setValue(_K, [](lua_State* L_) { lua_newtable(L_); }); | 841 | kLindasRegKey.setValue(_K, [](lua_State* L_) { lua_newtable(L_); }); |
813 | STACK_CHECK(_K, 0); | 842 | STACK_CHECK(_K, 0); |
814 | 843 | ||
815 | // configure GC last | 844 | // configure GC last |