aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 10:45:48 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 10:45:48 +0200
commitfc2fde434b73e9189dfa6b0c160e5fe72a7aee15 (patch)
tree76d02f3a1c4abe0fe1c00489945430cf97325344 /src
parent901ed6e98987a9e02bca8330973f19a34e55bd50 (diff)
downloadlanes-fc2fde434b73e9189dfa6b0c160e5fe72a7aee15.tar.gz
lanes-fc2fde434b73e9189dfa6b0c160e5fe72a7aee15.tar.bz2
lanes-fc2fde434b73e9189dfa6b0c160e5fe72a7aee15.zip
Keeper code internal improvements
Diffstat (limited to 'src')
-rw-r--r--src/keeper.cpp75
1 files changed, 42 insertions, 33 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index 7a8a855..915d6b6 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -63,6 +63,9 @@
63// the full userdata associated to a given Linda key to store its contents 63// the full userdata associated to a given Linda key to store its contents
64class KeyUD 64class KeyUD
65{ 65{
66 private:
67 static constexpr int kContentsTableIndex{ 1 };
68
66 public: 69 public:
67 int first{ 1 }; 70 int first{ 1 };
68 int count{ 0 }; 71 int count{ 0 };
@@ -80,10 +83,9 @@ class KeyUD
80 void peek(KeeperState K_, int count_); 83 void peek(KeeperState K_, int count_);
81 void pop(KeeperState K_, int count_); 84 void pop(KeeperState K_, int count_);
82 void push(KeeperState K_, int count_); 85 void push(KeeperState K_, int count_);
86 [[nodiscard]] bool reset(KeeperState K_);
83}; 87};
84 88
85static constexpr int kContentsTableIndex{ 1 };
86
87// ################################################################################################# 89// #################################################################################################
88 90
89// in: nothing 91// in: nothing
@@ -107,10 +109,10 @@ KeyUD* KeyUD::GetPtr(KeeperState const K_, int idx_)
107 return lua_tofulluserdata<KeyUD>(K_, idx_); 109 return lua_tofulluserdata<KeyUD>(K_, idx_);
108} 110}
109 111
110
111// ################################################################################################# 112// #################################################################################################
112 113
113// replaces the fifo ud by its uservalue on the stack 114// replaces the KeyUD by its uservalue on the stack
115// TODO: make it a non-static member to be called after KeyUD::GetPtr()
114KeyUD* KeyUD::PrepareAccess(KeeperState const K_, int const idx_) 116KeyUD* KeyUD::PrepareAccess(KeeperState const K_, int const idx_)
115{ 117{
116 KeyUD* const _key{ KeyUD::GetPtr(K_, idx_) }; 118 KeyUD* const _key{ KeyUD::GetPtr(K_, idx_) };
@@ -129,10 +131,10 @@ KeyUD* KeyUD::PrepareAccess(KeeperState const K_, int const idx_)
129// in: fifo 131// in: fifo
130// out: ...|nothing 132// out: ...|nothing
131// expects exactly 1 value on the stack! 133// expects exactly 1 value on the stack!
132// currently only called with a count of 1, but this may change in the future
133// function assumes that there is enough data in the fifo to satisfy the request 134// function assumes that there is enough data in the fifo to satisfy the request
134void KeyUD::peek(KeeperState const K_, int const count_) 135void KeyUD::peek(KeeperState const K_, int const count_)
135{ 136{
137 //LUA_ASSERT(K_, KeyUD::GetPtr(K_, 1) == this);
136 STACK_GROW(K_, count_); 138 STACK_GROW(K_, count_);
137 for (int const _i : std::ranges::iota_view{ 0, count_ }) { 139 for (int const _i : std::ranges::iota_view{ 0, count_ }) {
138 lua_rawgeti(K_, 1, first + _i); 140 lua_rawgeti(K_, 1, first + _i);
@@ -142,28 +144,28 @@ void KeyUD::peek(KeeperState const K_, int const count_)
142// ################################################################################################# 144// #################################################################################################
143 145
144// in: fifo 146// in: fifo
145// out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) 147// out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number)
146void KeyUD::pop(KeeperState const K_, int const count_) 148void KeyUD::pop(KeeperState const K_, int const count_)
147{ 149{
148 LUA_ASSERT(K_, lua_istable(K_, -1)); 150 LUA_ASSERT(K_, lua_istable(K_, -1));
149 int const _fifo_idx{ lua_gettop(K_) }; // K_: ... fifotbl 151 int const _fifo_idx{ lua_gettop(K_) }; // K_: ... fifo
150 // each iteration pushes a value on the stack! 152 // each iteration pushes a value on the stack!
151 STACK_GROW(K_, count_ + 2); 153 STACK_GROW(K_, count_ + 2);
152 // skip first item, we will push it last 154 // skip first item, we will push it last
153 for (int const _i : std::ranges::iota_view{ 1, count_ }) { 155 for (int const _i : std::ranges::iota_view{ 1, count_ }) {
154 int const _at{ first + _i }; 156 int const _at{ first + _i };
155 // push item on the stack 157 // push item on the stack
156 lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifotbl val 158 lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo val
157 // remove item from the fifo 159 // remove item from the fifo
158 lua_pushnil(K_); // K_: ... fifotbl val nil 160 lua_pushnil(K_); // K_: ... fifo val nil
159 lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifotbl val 161 lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo val
160 } 162 }
161 // now process first item 163 // now process first item
162 { 164 {
163 int const _at{ first }; 165 int const _at{ first };
164 lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifotbl vals val 166 lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo vals val
165 lua_pushnil(K_); // K_: ... fifotbl vals val nil 167 lua_pushnil(K_); // K_: ... fifo vals val nil
166 lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifotbl vals val 168 lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo vals val
167 lua_replace(K_, _fifo_idx); // K_: ... vals 169 lua_replace(K_, _fifo_idx); // K_: ... vals
168 } 170 }
169 171
@@ -192,6 +194,23 @@ void KeyUD::push(KeeperState const K_, int const count_)
192} 194}
193 195
194// ################################################################################################# 196// #################################################################################################
197
198// expects 'this' on top of the stack
199bool KeyUD::reset(KeeperState const K_)
200{
201 LUA_ASSERT(K_, KeyUD::GetPtr(K_, -1) == this);
202 STACK_CHECK_START_REL(K_, 0);
203 bool const _wasFull{ (limit > 0) && (count >= limit) };
204 // empty the KeyUD: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
205 lua_newtable(K_); // K_: KeysDB key val... KeyUD {}
206 lua_setiuservalue(K_, -2, kContentsTableIndex); // K_: KeysDB key val... KeyUD
207 first = 1;
208 count = 0;
209 STACK_CHECK(K_, 0);
210 return _wasFull;
211}
212
213// #################################################################################################
195// ################################################################################################# 214// #################################################################################################
196 215
197// in: linda_ud expected at stack slot idx 216// in: linda_ud expected at stack slot idx
@@ -247,22 +266,22 @@ int keeper_push_linda_storage(Linda& linda_, DestState L_)
247 InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} }; 266 InterCopyContext _c{ linda_.U, L_, SourceState{ _K }, {}, {}, {}, LookupMode::FromKeeper, {} };
248 lua_pushnil(_K); // _K: KeysDB nil L_: out 267 lua_pushnil(_K); // _K: KeysDB nil L_: out
249 while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out 268 while (lua_next(_K, -2)) { // _K: KeysDB key KeyUD L_: out
250 KeyUD* const _keyUD{ KeyUD::PrepareAccess(_K, -1) }; // _K: KeysDB key fifo L_: out 269 KeyUD* const _key{ KeyUD::PrepareAccess(_K, -1) }; // _K: KeysDB key fifo L_: out
251 lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out 270 lua_pushvalue(_K, -2); // _K: KeysDB key fifo key L_: out
252 std::ignore = _c.inter_move(1); // _K: KeysDB key fifo L_: out key 271 std::ignore = _c.inter_move(1); // _K: KeysDB key fifo L_: out key
253 STACK_CHECK(L_, 2); 272 STACK_CHECK(L_, 2);
254 lua_newtable(L_); // _K: KeysDB key fifo L_: out key keyout 273 lua_newtable(L_); // _K: KeysDB key fifo L_: out key keyout
255 std::ignore = _c.inter_move(1); // _K: KeysDB key L_: out key keyout fifo 274 std::ignore = _c.inter_move(1); // _K: KeysDB key L_: out key keyout fifo
256 // keyout.first 275 // keyout.first
257 lua_pushinteger(L_, _keyUD->first); // _K: KeysDB key L_: out key keyout fifo first 276 lua_pushinteger(L_, _key->first); // _K: KeysDB key L_: out key keyout fifo first
258 STACK_CHECK(L_, 5); 277 STACK_CHECK(L_, 5);
259 lua_setfield(L_, -3, "first"); // _K: KeysDB key L_: out key keyout fifo 278 lua_setfield(L_, -3, "first"); // _K: KeysDB key L_: out key keyout fifo
260 // keyout.count 279 // keyout.count
261 lua_pushinteger(L_, _keyUD->count); // _K: KeysDB key L_: out key keyout fifo count 280 lua_pushinteger(L_, _key->count); // _K: KeysDB key L_: out key keyout fifo count
262 STACK_CHECK(L_, 5); 281 STACK_CHECK(L_, 5);
263 lua_setfield(L_, -3, "count"); // _K: KeysDB key L_: out key keyout fifo 282 lua_setfield(L_, -3, "count"); // _K: KeysDB key L_: out key keyout fifo
264 // keyout.limit 283 // keyout.limit
265 lua_pushinteger(L_, _keyUD->limit); // _K: KeysDB key L_: out key keyout fifo limit 284 lua_pushinteger(L_, _key->limit); // _K: KeysDB key L_: out key keyout fifo limit
266 STACK_CHECK(L_, 5); 285 STACK_CHECK(L_, 5);
267 lua_setfield(L_, -3, "limit"); // _K: KeysDB key L_: out key keyout fifo 286 lua_setfield(L_, -3, "limit"); // _K: KeysDB key L_: out key keyout fifo
268 // keyout.fifo 287 // keyout.fifo
@@ -461,13 +480,9 @@ int keepercall_set(lua_State* const L_)
461 lua_pushnil(_K); // _K: KeysDB key nil 480 lua_pushnil(_K); // _K: KeysDB key nil
462 lua_rawset(_K, -3); // _K: KeysDB 481 lua_rawset(_K, -3); // _K: KeysDB
463 } else { 482 } else {
464 // we create room if the KeyUD was full but it is no longer the case
465 _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit);
466 lua_remove(_K, -2); // _K: KeysDB KeyUD 483 lua_remove(_K, -2); // _K: KeysDB KeyUD
467 lua_newtable(_K); // _K: KeysDB KeyUD {} 484 // we create room if the KeyUD was full but it is no longer the case
468 lua_setiuservalue(_K, -2, kContentsTableIndex); // _K: KeysDB KeyUD 485 _should_wake_writers = _key->reset(_K);
469 _key->first = 1;
470 _key->count = 0;
471 } 486 }
472 } 487 }
473 } else { // set/replace contents stored at the specified key? 488 } else { // set/replace contents stored at the specified key?
@@ -478,22 +493,16 @@ int keepercall_set(lua_State* const L_)
478 if (_key == nullptr) { // can be nullptr if we store a value at a new key // KeysDB key val... nil 493 if (_key == nullptr) { // can be nullptr if we store a value at a new key // KeysDB key val... nil
479 // no need to wake writers in that case, because a writer can't wait on an inexistent key 494 // no need to wake writers in that case, because a writer can't wait on an inexistent key
480 lua_pop(_K, 1); // _K: KeysDB key val... 495 lua_pop(_K, 1); // _K: KeysDB key val...
481 std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: KeysDB key val... KeyUD 496 _key = KeyUD::Create(KeeperState{ _K }); // _K: KeysDB key val... KeyUD
482 lua_pushvalue(_K, 2); // _K: KeysDB key val... KeyUD key 497 lua_pushvalue(_K, 2); // _K: KeysDB key val... KeyUD key
483 lua_pushvalue(_K, -2); // _K: KeysDB key val... KeyUD key KeyUD 498 lua_pushvalue(_K, -2); // _K: KeysDB key val... KeyUD key KeyUD
484 lua_rawset(_K, 1); // _K: KeysDB key val... KeyUD 499 lua_rawset(_K, 1); // _K: KeysDB key val... KeyUD
485 } else { // _K: KeysDB key val... KeyUD 500 } else { // _K: KeysDB key val... KeyUD
486 // the KeyUD exists, we just want to update its contents 501 // the KeyUD exists, we just want to update its contents
487 // we create room if the KeyUD was full but it is no longer the case 502 // we create room if the KeyUD was full but we didn't refill it to the brim with new data
488 _should_wake_writers = (_key->limit > 0) && (_key->count >= _key->limit) && (_count < _key->limit); 503 _should_wake_writers = _key->reset(_K) && (_count < _key->limit);
489 // TODO: turn this into a KeyUD::reset() method
490 // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
491 lua_newtable(_K); // _K: KeysDB key val... KeyUD {}
492 lua_setiuservalue(_K, -2, kContentsTableIndex); // _K: KeysDB key val... KeyUD
493 _key->first = 1;
494 _key->count = 0;
495 } 504 }
496 _key = KeyUD::PrepareAccess(_K, -1); // _K: KeysDB key val... fifo 505 std::ignore = KeyUD::PrepareAccess(_K, -1); // _K: KeysDB key val... fifo
497 // move the fifo below the values we want to store 506 // move the fifo below the values we want to store
498 lua_insert(_K, 3); // _K: KeysDB key fifo val... 507 lua_insert(_K, 3); // _K: KeysDB key fifo val...
499 _key->push(_K, _count); // _K: KeysDB key fifo 508 _key->push(_K, _count); // _K: KeysDB key fifo