aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-03 09:46:16 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-03 09:46:16 +0200
commit420e50697cd036a0d8ea1601961bd6974703ade1 (patch)
treefd922454b4f94fb38333d3bd49679e01afb56fb5 /src
parentf7a38b5681ebf7429828fca9a9f7c109df853d54 (diff)
downloadlanes-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.cpp559
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
79static constexpr int kContentsTableIndex{ 1 }; 85static 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}
85KeyUD* KeyUD::Create(KeeperState const L_) 91KeyUD* 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
99KeyUD* KeyUD::GetPtr(lua_State* L_, int idx_) 105KeyUD* 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
108KeyUD* KeyUD::PrepareAccess(lua_State* const L_, int const idx_) 114KeyUD* 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
128void KeyUD::peek(lua_State* const L_, int const count_) 134void 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)
140void KeyUD::pop(lua_State* const L_, int const count_) 146void 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
176void KeyUD::push(lua_State* const L_, int const count_) 182void 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
194static constexpr RegistryUniqueKey kFifosRegKey{ 0x37F11CE5A6D191AAull }; 200static constexpr RegistryUniqueKey kLindasRegKey{ 0x3AE0D5243A88B962ull };
195static void push_table(lua_State* L_, int idx_) 201static 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
219int keeper_push_linda_storage(Linda& linda_, DestState L_) 225int 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
275int keepercall_clear(lua_State* const L_) 287int 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
292int keepercall_send(lua_State* const L_) 305int 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
325int keepercall_receive(lua_State* const L_) 344int 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]
357int keepercall_receive_batched(lua_State* const L_) 377int 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
385int keepercall_limit(lua_State* const L_) 407int 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
419int keepercall_set(lua_State* const L_) 442int 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
483int keepercall_get(lua_State* const L_) 508int 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 [, ...]]
508int keepercall_count(lua_State* const L_) 534int 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