aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 17:42:09 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 17:42:09 +0200
commit6d90af6ab9ccdfb2f20fb73fc2d6400c23521c0a (patch)
tree39aad9465b7cdcd1d6de05d335c168c112b8c308 /src
parentc360af2df3e0904c7338cc1f32fcb270b7e34092 (diff)
downloadlanes-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.h8
-rw-r--r--src/keeper.cpp94
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
190inline 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
190enum class LuaError 198enum 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)
192void KeyUD::prepareAccess(KeeperState const K_) 192void 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
204void KeyUD::push(KeeperState const K_, int const count_) 205bool 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
525int keepercall_send(lua_State* const L_) 535int 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