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 |
