diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-04 17:42:09 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-04 17:42:09 +0200 |
commit | 6d90af6ab9ccdfb2f20fb73fc2d6400c23521c0a (patch) | |
tree | 39aad9465b7cdcd1d6de05d335c168c112b8c308 /src | |
parent | c360af2df3e0904c7338cc1f32fcb270b7e34092 (diff) | |
download | lanes-6d90af6ab9ccdfb2f20fb73fc2d6400c23521c0a.tar.gz lanes-6d90af6ab9ccdfb2f20fb73fc2d6400c23521c0a.tar.bz2 lanes-6d90af6ab9ccdfb2f20fb73fc2d6400c23521c0a.zip |
Refactored keeper implementation of linda:send()
Diffstat (limited to 'src')
-rw-r--r-- | src/compat.h | 8 | ||||
-rw-r--r-- | src/keeper.cpp | 94 |
2 files changed, 58 insertions, 44 deletions
diff --git a/src/compat.h b/src/compat.h index 7ac864e..ceb1275 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -186,6 +186,14 @@ inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) | |||
186 | 186 | ||
187 | // ################################################################################################# | 187 | // ################################################################################################# |
188 | 188 | ||
189 | // use this in place of lua_absindex to save a function call | ||
190 | inline int luaG_absindex(lua_State* L_, int idx_) | ||
191 | { | ||
192 | return (((idx_) >= 0 || (idx_) <= LUA_REGISTRYINDEX) ? (idx_) : lua_gettop(L_) + (idx_) + 1); | ||
193 | } | ||
194 | |||
195 | // ################################################################################################# | ||
196 | |||
189 | // a strong-typed wrapper over lua error codes to see them easier in a debugger | 197 | // a strong-typed wrapper over lua error codes to see them easier in a debugger |
190 | enum class LuaError | 198 | enum class LuaError |
191 | { | 199 | { |
diff --git a/src/keeper.cpp b/src/keeper.cpp index b73533a..e7574ed 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -82,8 +82,8 @@ class KeyUD | |||
82 | [[nodiscard]] static KeyUD* GetPtr(KeeperState K_, int idx_); | 82 | [[nodiscard]] static KeyUD* GetPtr(KeeperState K_, int idx_); |
83 | void peek(KeeperState K_, int count_); | 83 | void peek(KeeperState K_, int count_); |
84 | [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); | 84 | [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); |
85 | void prepareAccess(KeeperState K_); | 85 | void prepareAccess(KeeperState K_, int idx_); |
86 | void push(KeeperState K_, int count_); | 86 | [[nodiscard]] bool push(KeeperState K_, int count_); |
87 | [[nodiscard]] bool reset(KeeperState K_); | 87 | [[nodiscard]] bool reset(KeeperState K_); |
88 | }; | 88 | }; |
89 | 89 | ||
@@ -137,7 +137,7 @@ void KeyUD::peek(KeeperState const K_, int const count_) | |||
137 | } | 137 | } |
138 | 138 | ||
139 | // read <count_> value off the fifo | 139 | // read <count_> value off the fifo |
140 | prepareAccess(K_); // K_: fifo | 140 | prepareAccess(K_, -1); // K_: fifo |
141 | int const _at{ lua_gettop(K_) }; | 141 | int const _at{ lua_gettop(K_) }; |
142 | for (int const _i : std::ranges::iota_view{ 1, std::min(count_, count) }) { // push val2 to valN | 142 | for (int const _i : std::ranges::iota_view{ 1, std::min(count_, count) }) { // push val2 to valN |
143 | lua_rawgeti(K_, 1, first + _i); // K_: fifo val2..N | 143 | lua_rawgeti(K_, 1, first + _i); // K_: fifo val2..N |
@@ -159,7 +159,7 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | |||
159 | } | 159 | } |
160 | int const _popCount{ std::min(count, maxCount_) }; | 160 | int const _popCount{ std::min(count, maxCount_) }; |
161 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); // K_: ... this | 161 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); // K_: ... this |
162 | prepareAccess(K_); // K_: ... fifo | 162 | prepareAccess(K_, -1); // K_: ... fifo |
163 | int const _fifo_idx{ lua_gettop(K_) }; | 163 | int const _fifo_idx{ lua_gettop(K_) }; |
164 | // each iteration pushes a value on the stack! | 164 | // each iteration pushes a value on the stack! |
165 | STACK_GROW(K_, _popCount + 2); | 165 | STACK_GROW(K_, _popCount + 2); |
@@ -187,30 +187,40 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | |||
187 | 187 | ||
188 | // ################################################################################################# | 188 | // ################################################################################################# |
189 | 189 | ||
190 | // expects 'this' on top of the stack | 190 | // expects 'this' at the specified index |
191 | // replaces it by its uservalue on the stack | 191 | // replaces it by its uservalue on the stack (the table holding the fifo values) |
192 | void KeyUD::prepareAccess(KeeperState const K_) | 192 | void KeyUD::prepareAccess(KeeperState const K_, int const idx_) |
193 | { | 193 | { |
194 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); | 194 | int const _idx{ luaG_absindex(K_, idx_) }; |
195 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, idx_) == this); | ||
195 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around | 196 | // we can replace the key userdata in the stack without fear of it being GCed, there are other references around |
196 | lua_getiuservalue(K_, -1, kContentsTableIndex); | 197 | lua_getiuservalue(K_, _idx, kContentsTableIndex); |
197 | lua_replace(K_, -2); | 198 | lua_replace(K_, _idx); |
198 | } | 199 | } |
199 | 200 | ||
200 | // ################################################################################################# | 201 | // ################################################################################################# |
201 | 202 | ||
202 | // in: expect fifo args... on top of the stack | 203 | // in: expect this val... on top of the stack |
203 | // out: nothing, removes all pushed values from the stack | 204 | // out: nothing, removes all pushed values from the stack |
204 | void KeyUD::push(KeeperState const K_, int const count_) | 205 | bool KeyUD::push(KeeperState const K_, int const count_) |
205 | { | 206 | { |
206 | int const _idx{ lua_gettop(K_) - count_ }; | 207 | int const _fifoIdx{ luaG_absindex(K_, -1 - count_) }; |
208 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, _fifoIdx) == this); // K_: this val... | ||
209 | if (limit >= 0 && count + count_ > limit) { // not enough room | ||
210 | return false; | ||
211 | } | ||
212 | |||
213 | prepareAccess(K_, _fifoIdx); // K_: fifo val... | ||
207 | int const _start{ first + count - 1 }; | 214 | int const _start{ first + count - 1 }; |
208 | // pop all additional arguments, storing them in the fifo | 215 | // pop all additional arguments, storing them in the fifo |
209 | for (int const _i : std::ranges::reverse_view{ std::ranges::iota_view{ 1, count_ + 1 } }) { | 216 | for (int const _i : std::ranges::reverse_view{ std::ranges::iota_view{ 1, count_ + 1 } }) { |
210 | // store in the fifo the value at the top of the stack at the specified index, popping it from the stack | 217 | // store in the fifo the value at the top of the stack at the specified index, popping it from the stack |
211 | lua_rawseti(K_, _idx, _start + _i); | 218 | lua_rawseti(K_, _fifoIdx, _start + _i); |
212 | } | 219 | } |
213 | count += count_; | 220 | count += count_; |
221 | // all values are, gone, only our fifo remains, we can remove it | ||
222 | lua_pop(K_, 1); // K_: | ||
223 | return true; | ||
214 | } | 224 | } |
215 | 225 | ||
216 | // ################################################################################################# | 226 | // ################################################################################################# |
@@ -241,7 +251,7 @@ static void PushKeysDB(KeeperState const K_, int const idx_) | |||
241 | { | 251 | { |
242 | STACK_GROW(K_, 5); | 252 | STACK_GROW(K_, 5); |
243 | STACK_CHECK_START_REL(K_, 0); | 253 | STACK_CHECK_START_REL(K_, 0); |
244 | int const _idx{ lua_absindex(K_, idx_) }; | 254 | int const _idx{ luaG_absindex(K_, idx_) }; |
245 | kLindasRegKey.pushValue(K_); // K_: ... LindasDB | 255 | kLindasRegKey.pushValue(K_); // K_: ... LindasDB |
246 | lua_pushvalue(K_, _idx); // K_: ... LindasDB linda | 256 | lua_pushvalue(K_, _idx); // K_: ... LindasDB linda |
247 | lua_rawget(K_, -2); // K_: ... LindasDB KeysDB | 257 | lua_rawget(K_, -2); // K_: ... LindasDB KeysDB |
@@ -287,7 +297,7 @@ int keeper_push_linda_storage(Linda& linda_, DestState L_) | |||
287 | lua_pushnil(_K); // _K: KeysDB nil L_: out | 297 | lua_pushnil(_K); // _K: KeysDB nil L_: out |
288 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out | 298 | while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out |
289 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 299 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
290 | _key->prepareAccess(_K); // _K: KeysDB key fifo L_: out | 300 | _key->prepareAccess(_K, -1); // _K: KeysDB key fifo L_: out |
291 | lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out | 301 | lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out |
292 | std::ignore = _c.inter_move(1); // _K: KeysDB key fifo L_: out key | 302 | std::ignore = _c.inter_move(1); // _K: KeysDB key fifo L_: out key |
293 | STACK_CHECK(L_, 2); | 303 | STACK_CHECK(L_, 2); |
@@ -340,7 +350,7 @@ int keepercall_count(lua_State* const L_) | |||
340 | lua_pushvalue(_K, -1); // _K: out KeysDB key key | 350 | lua_pushvalue(_K, -1); // _K: out KeysDB key key |
341 | lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count | 351 | lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count |
342 | lua_rawset(_K, -5); // _K: out KeysDB key | 352 | lua_rawset(_K, -5); // _K: out KeysDB key |
343 | } | 353 | } // when loop is done, lua_next() pushes nothing // _K: out KeysDB |
344 | lua_pop(_K, 1); // _K: out | 354 | lua_pop(_K, 1); // _K: out |
345 | break; | 355 | break; |
346 | 356 | ||
@@ -520,39 +530,36 @@ int keepercall_receive_batched(lua_State* const L_) | |||
520 | 530 | ||
521 | // ################################################################################################# | 531 | // ################################################################################################# |
522 | 532 | ||
523 | // in: linda_ud, key, ... | 533 | // in: linda, key, ... |
524 | // out: true|false | 534 | // out: true|false |
525 | int keepercall_send(lua_State* const L_) | 535 | int keepercall_send(lua_State* const L_) |
526 | { | 536 | { |
527 | KeeperState const _K{ L_ }; | 537 | KeeperState const _K{ L_ }; |
528 | int const _n{ lua_gettop(_K) - 2 }; | 538 | int const _n{ lua_gettop(_K) - 2 }; |
529 | STACK_CHECK_START_REL(_K, 0); | 539 | STACK_CHECK_START_REL(_K, 0); // _K: linda key val... |
530 | PushKeysDB(_K, 1); // _K: linda key args... KeysDB | 540 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB |
531 | // get the fifo associated to this key in this linda, create it if it doesn't exist | 541 | // get the fifo associated to this key in this linda, create it if it doesn't exist |
532 | lua_pushvalue(_K, 2); // _K: linda key args... KeysDB key | 542 | lua_pushvalue(_K, 2); // _K: linda key val... KeysDB key |
533 | lua_rawget(_K, -2); // _K: linda key args... KeysDB KeyUD|nil | 543 | lua_rawget(_K, -2); // _K: linda key val... KeysDB KeyUD|nil |
534 | if (lua_isnil(_K, -1)) { | 544 | if (lua_isnil(_K, -1)) { |
535 | lua_pop(_K, 1); // _K: linda key args... KeysDB | 545 | lua_pop(_K, 1); // _K: linda key val... KeysDB |
536 | std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key args... KeysDB KeyUD | 546 | std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key val... KeysDB KeyUD |
537 | // KeysDB[key] = KeyUD | 547 | // KeysDB[key] = KeyUD |
538 | lua_pushvalue(_K, 2); // _K: linda key args... KeysDB KeyUD key | 548 | lua_pushvalue(_K, 2); // _K: linda key val... KeysDB KeyUD key |
539 | lua_pushvalue(_K, -2); // _K: linda key args... KeysDB KeyUD key KeyUD | 549 | lua_pushvalue(_K, -2); // _K: linda key val... KeysDB KeyUD key KeyUD |
540 | lua_rawset(_K, -4); // _K: linda key args... KeysDB KeyUD | 550 | lua_rawset(_K, -4); // _K: linda key val... KeysDB KeyUD |
541 | } | 551 | } |
542 | lua_remove(_K, -2); // _K: linda key args... KeyUD | 552 | lua_replace(_K, 2); // _K: linda KeyUD val... KeysDB |
543 | STACK_CHECK(_K, 1); | 553 | lua_pop(_K, 1); // _K: linda KeyUD val... |
544 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 554 | STACK_CHECK(_K, 0); |
545 | if (_key->limit >= 0 && _key->count + _n > _key->limit) { // not enough room? | 555 | KeyUD* const _key{ KeyUD::GetPtr(_K, 2) }; |
546 | // don't send anything | 556 | if (_key && _key->push(_K, _n)) { // not enough room? |
547 | lua_settop(_K, 0); // _K: | 557 | lua_settop(_K, 0); // _K: |
548 | lua_pushboolean(_K, 0); // _K: false | 558 | lua_pushboolean(_K, 1); // _K: true |
549 | } else { | 559 | } else { |
550 | // _key should remain unchanged | 560 | // don't send anything |
551 | _key->prepareAccess(_K); // _K: linda key args... fifo | ||
552 | lua_replace(_K, 2); // _K: linda fifo args... | ||
553 | _key->push(_K, _n); // _K: linda fifo | ||
554 | lua_settop(_K, 0); // _K: | 561 | lua_settop(_K, 0); // _K: |
555 | lua_pushboolean(_K, 1); // _K: true | 562 | lua_pushboolean(_K, 0); // _K: false |
556 | } | 563 | } |
557 | return 1; | 564 | return 1; |
558 | } | 565 | } |
@@ -567,7 +574,7 @@ int keepercall_set(lua_State* const L_) | |||
567 | bool _should_wake_writers{ false }; | 574 | bool _should_wake_writers{ false }; |
568 | STACK_GROW(_K, 6); | 575 | STACK_GROW(_K, 6); |
569 | 576 | ||
570 | // retrieve fifos associated with the linda | 577 | // retrieve KeysDB associated with the linda |
571 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB | 578 | PushKeysDB(_K, 1); // _K: linda key val... KeysDB |
572 | lua_replace(_K, 1); // _K: KeysDB key val... | 579 | lua_replace(_K, 1); // _K: KeysDB key val... |
573 | 580 | ||
@@ -605,10 +612,9 @@ int keepercall_set(lua_State* const L_) | |||
605 | // we create room if the KeyUD was full but we didn't refill it to the brim with new data | 612 | // we create room if the KeyUD was full but we didn't refill it to the brim with new data |
606 | _should_wake_writers = _key->reset(_K) && (_count < _key->limit); | 613 | _should_wake_writers = _key->reset(_K) && (_count < _key->limit); |
607 | } | 614 | } |
608 | _key->prepareAccess(_K); // _K: KeysDB key val... fifo | 615 | // replace the key with the KeyUD in the stack |
609 | // move the fifo below the values we want to store. can be slow if there are a lot. TODO: optimize that if possible | 616 | lua_replace(_K, -2 - _count); // _K: KeysDB KeyUD val... |
610 | lua_insert(_K, 3); // _K: KeysDB key fifo val... | 617 | [[maybe_unused]] bool const _pushed{ _key->push(_K, _count) }; // _K: KeysDB |
611 | _key->push(_K, _count); // _K: KeysDB key fifo | ||
612 | } | 618 | } |
613 | return _should_wake_writers ? (lua_pushboolean(_K, 1), 1) : 0; | 619 | return _should_wake_writers ? (lua_pushboolean(_K, 1), 1) : 0; |
614 | } | 620 | } |
@@ -843,7 +849,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int | |||
843 | // copy package.path and package.cpath from the source state | 849 | // copy package.path and package.cpath from the source state |
844 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: | 850 | if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: |
845 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 851 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
846 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ lua_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; | 852 | InterCopyContext _c{ U, DestState{ _K }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; |
847 | if (_c.inter_copy_package() != InterCopyResult::Success) { // L_: settings ... error_msg _K: | 853 | if (_c.inter_copy_package() != InterCopyResult::Success) { // L_: settings ... error_msg _K: |
848 | // if something went wrong, the error message is at the top of the stack | 854 | // if something went wrong, the error message is at the top of the stack |
849 | lua_remove(L, -2); // L_: settings error_msg | 855 | lua_remove(L, -2); // L_: settings error_msg |