diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-04 16:19:47 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-04 16:19:47 +0200 |
commit | c360af2df3e0904c7338cc1f32fcb270b7e34092 (patch) | |
tree | 22b27902eff9148e787c968f5bd60ad44252c3a3 /src | |
parent | 4695cbe96514e6b174fb5050bb2e9a41514091f3 (diff) | |
download | lanes-c360af2df3e0904c7338cc1f32fcb270b7e34092.tar.gz lanes-c360af2df3e0904c7338cc1f32fcb270b7e34092.tar.bz2 lanes-c360af2df3e0904c7338cc1f32fcb270b7e34092.zip |
Refactored keeper implementation of linda:receive()
Diffstat (limited to 'src')
-rw-r--r-- | src/keeper.cpp | 94 | ||||
-rw-r--r-- | src/linda.cpp | 5 |
2 files changed, 50 insertions, 49 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index a546868..b73533a 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -81,7 +81,7 @@ class KeyUD | |||
81 | [[nodiscard]] static KeyUD* Create(KeeperState K_); | 81 | [[nodiscard]] static KeyUD* Create(KeeperState K_); |
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 | void pop(KeeperState K_, int count_); | 84 | [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); |
85 | void prepareAccess(KeeperState K_); | 85 | void prepareAccess(KeeperState K_); |
86 | void push(KeeperState K_, int count_); | 86 | void push(KeeperState K_, int count_); |
87 | [[nodiscard]] bool reset(KeeperState K_); | 87 | [[nodiscard]] bool reset(KeeperState K_); |
@@ -150,14 +150,21 @@ void KeyUD::peek(KeeperState const K_, int const count_) | |||
150 | 150 | ||
151 | // in: fifo | 151 | // in: fifo |
152 | // out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) | 152 | // out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) |
153 | void KeyUD::pop(KeeperState const K_, int const count_) | 153 | int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) |
154 | { | 154 | { |
155 | LUA_ASSERT(K_, lua_istable(K_, -1)); | 155 | if (count < minCount_) { |
156 | int const _fifo_idx{ lua_gettop(K_) }; // K_: ... fifo | 156 | // pop ourselves, return nothing |
157 | lua_pop(K_, 1); // K_: ... this | ||
158 | return 0; | ||
159 | } | ||
160 | int const _popCount{ std::min(count, maxCount_) }; | ||
161 | LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this); // K_: ... this | ||
162 | prepareAccess(K_); // K_: ... fifo | ||
163 | int const _fifo_idx{ lua_gettop(K_) }; | ||
157 | // each iteration pushes a value on the stack! | 164 | // each iteration pushes a value on the stack! |
158 | STACK_GROW(K_, count_ + 2); | 165 | STACK_GROW(K_, _popCount + 2); |
159 | // skip first item, we will push it last | 166 | // skip first item, we will push it last |
160 | for (int const _i : std::ranges::iota_view{ 1, count_ }) { | 167 | for (int const _i : std::ranges::iota_view{ 1, _popCount }) { |
161 | int const _at{ first + _i }; | 168 | int const _at{ first + _i }; |
162 | // push item on the stack | 169 | // push item on the stack |
163 | lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo val | 170 | lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo val |
@@ -166,20 +173,16 @@ void KeyUD::pop(KeeperState const K_, int const count_) | |||
166 | lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo val | 173 | lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo val |
167 | } | 174 | } |
168 | // now process first item | 175 | // now process first item |
169 | { | 176 | lua_rawgeti(K_, _fifo_idx, first); // K_: ... fifo vals val |
170 | int const _at{ first }; | 177 | lua_pushnil(K_); // K_: ... fifo vals val nil |
171 | lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo vals val | 178 | lua_rawseti(K_, _fifo_idx, first); // K_: ... fifo vals val |
172 | lua_pushnil(K_); // K_: ... fifo vals val nil | 179 | lua_replace(K_, _fifo_idx); // K_: ... vals |
173 | lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo vals val | ||
174 | lua_replace(K_, _fifo_idx); // K_: ... vals | ||
175 | } | ||
176 | 180 | ||
177 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty | 181 | // avoid ever-growing indexes by resetting each time we detect the fifo is empty |
178 | { | 182 | int const _new_count{ count - _popCount }; |
179 | int const _new_count{ count - count_ }; | 183 | first = (_new_count == 0) ? 1 : (first + _popCount); |
180 | first = (_new_count == 0) ? 1 : (first + count_); | 184 | count = _new_count; |
181 | count = _new_count; | 185 | return _popCount; |
182 | } | ||
183 | } | 186 | } |
184 | 187 | ||
185 | // ################################################################################################# | 188 | // ################################################################################################# |
@@ -466,21 +469,20 @@ int keepercall_receive(lua_State* const L_) | |||
466 | PushKeysDB(_K, 1); // _K: linda keys... KeysDB | 469 | PushKeysDB(_K, 1); // _K: linda keys... KeysDB |
467 | lua_replace(_K, 1); // _K: KeysDB keys... | 470 | lua_replace(_K, 1); // _K: KeysDB keys... |
468 | 471 | ||
469 | for (int const _i : std::ranges::iota_view{ 2, _top + 1 }) { | 472 | for (int const _keyIdx : std::ranges::iota_view{ 2, _top + 1 }) { |
470 | lua_pushvalue(_K, _i); // _K: KeysDB keys... key[i] | 473 | lua_pushvalue(_K, _keyIdx); // _K: KeysDB keys... key[i] |
471 | lua_rawget(_K, 1); // _K: KeysDB keys... KeyUD | 474 | lua_rawget(_K, 1); // _K: KeysDB keys... KeyUD |
472 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 475 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
473 | if (_key != nullptr && _key->count > 0) { | 476 | if (_key != nullptr) { // it's fine to attempt a read on a key that wasn't yet written to |
474 | _key->prepareAccess(_K); // _K: KeysDB keys... fifo | 477 | int const _popped{ _key->pop(_K, 1, 1) }; // _K: KeysDB keys... val |
475 | _key->pop(_K, 1); // _K: KeysDB keys... val | 478 | if (_popped > 0) { |
476 | if (!lua_isnil(_K, -1)) { | ||
477 | lua_replace(_K, 1); // _K: val keys... | 479 | lua_replace(_K, 1); // _K: val keys... |
478 | lua_settop(_K, _i); // _K: val keys... key[i] | 480 | lua_settop(_K, _keyIdx); // _K: val keys... key[i] |
479 | if (_i != 2) { | 481 | if (_keyIdx != 2) { |
480 | lua_replace(_K, 2); // _K: val key keys... | 482 | lua_replace(_K, 2); // _K: val key[i] keys... |
481 | lua_settop(_K, 2); // _K: val key | 483 | lua_settop(_K, 2); // _K: val key[i] |
482 | } | 484 | } |
483 | lua_insert(_K, 1); // _K: key, val | 485 | lua_insert(_K, 1); // _K: key val |
484 | return 2; | 486 | return 2; |
485 | } | 487 | } |
486 | } | 488 | } |
@@ -496,27 +498,23 @@ int keepercall_receive(lua_State* const L_) | |||
496 | int keepercall_receive_batched(lua_State* const L_) | 498 | int keepercall_receive_batched(lua_State* const L_) |
497 | { | 499 | { |
498 | KeeperState const _K{ L_ }; | 500 | KeeperState const _K{ L_ }; |
501 | // linda:receive() made sure that _min_count > 0 and _max_count > _min_count | ||
499 | int const _min_count{ static_cast<int>(lua_tointeger(_K, 3)) }; | 502 | int const _min_count{ static_cast<int>(lua_tointeger(_K, 3)) }; |
500 | if (_min_count > 0) { | 503 | int const _max_count{ static_cast<int>(luaL_optinteger(_K, 4, _min_count)) }; |
501 | int const _max_count{ static_cast<int>(luaL_optinteger(_K, 4, _min_count)) }; | 504 | lua_settop(_K, 2); // _K: linda key |
502 | lua_settop(_K, 2); // _K: linda key | 505 | lua_insert(_K, 1); // _K: key linda |
503 | lua_insert(_K, 1); // _K: key linda | 506 | PushKeysDB(_K, 2); // _K: key linda KeysDB |
504 | PushKeysDB(_K, 2); // _K: key linda KeysDB | 507 | lua_remove(_K, 2); // _K: key KeysDB |
505 | lua_remove(_K, 2); // _K: key KeysDB | 508 | lua_pushvalue(_K, 1); // _K: key KeysDB key |
506 | lua_pushvalue(_K, 1); // _K: key KeysDB key | 509 | lua_rawget(_K, 2); // _K: key KeysDB KeyUD |
507 | lua_rawget(_K, 2); // _K: key KeysDB KeyUD | 510 | lua_remove(_K, 2); // _K: key KeyUD |
508 | lua_remove(_K, 2); // _K: key KeyUD | 511 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; |
509 | KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; | 512 | if (_key == nullptr || _key->pop(_K, _min_count, _max_count) == 0) { // _K: [key val...]|crap |
510 | if (_key != nullptr && _key->count >= _min_count) { | 513 | // Lua will adjust the stack for us when we return |
511 | _key->prepareAccess(_K); // _K: key fifo | ||
512 | _key->pop(_K, std::min(_max_count, _key->count)); // _K: key val... | ||
513 | } else { | ||
514 | lua_settop(_K, 0); // _K: | ||
515 | } | ||
516 | // return whatever remains on the stack at that point | ||
517 | return lua_gettop(_K); | ||
518 | } else { | ||
519 | return 0; | 514 | return 0; |
515 | } else { | ||
516 | // return whatever remains on the stack at that point: the key and the values we pulled from the fifo | ||
517 | return lua_gettop(_K); | ||
520 | } | 518 | } |
521 | } | 519 | } |
522 | 520 | ||
diff --git a/src/linda.cpp b/src/linda.cpp index 12b5e8a..b623d29 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -470,12 +470,15 @@ LUAG_FUNC(linda_receive) | |||
470 | _selected_keeper_receive = KEEPER_API(receive_batched); | 470 | _selected_keeper_receive = KEEPER_API(receive_batched); |
471 | // we expect a user-defined amount of return value | 471 | // we expect a user-defined amount of return value |
472 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); | 472 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); |
473 | if (_expected_pushed_min < 1) { | ||
474 | raise_luaL_argerror(L_, _key_i + 1, "bad min count"); | ||
475 | } | ||
473 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); | 476 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); |
474 | // don't forget to count the key in addition to the values | 477 | // don't forget to count the key in addition to the values |
475 | ++_expected_pushed_min; | 478 | ++_expected_pushed_min; |
476 | ++_expected_pushed_max; | 479 | ++_expected_pushed_max; |
477 | if (_expected_pushed_min > _expected_pushed_max) { | 480 | if (_expected_pushed_min > _expected_pushed_max) { |
478 | raise_luaL_error(L_, "batched min/max error"); | 481 | raise_luaL_argerror(L_, _key_i + 2, "batched min/max error"); |
479 | } | 482 | } |
480 | } else { | 483 | } else { |
481 | // make sure the keys are of a valid type | 484 | // make sure the keys are of a valid type |