aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r--src/keeper.cpp75
1 files changed, 58 insertions, 17 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index ae09b37..cfeebbb 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -66,6 +66,10 @@ class KeyUD
66 static constexpr int kContentsTableIndex{ 1 }; 66 static constexpr int kContentsTableIndex{ 1 };
67 67
68 public: 68 public:
69 static constexpr std::string_view kUnder{ "under" };
70 static constexpr std::string_view kExact{ "exact" };
71 static constexpr std::string_view kOver{ "over" };
72
69 int first{ 1 }; 73 int first{ 1 };
70 int count{ 0 }; 74 int count{ 0 };
71 LindaLimit limit{ -1 }; 75 LindaLimit limit{ -1 };
@@ -83,6 +87,8 @@ class KeyUD
83 [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); // keepercall_receive[_batched] 87 [[nodiscard]] int pop(KeeperState K_, int minCount_, int maxCount_); // keepercall_receive[_batched]
84 void prepareAccess(KeeperState K_, int idx_) const; 88 void prepareAccess(KeeperState K_, int idx_) const;
85 [[nodiscard]] bool push(KeeperState K_, int count_, bool enforceLimit_); // keepercall_send and keepercall_set 89 [[nodiscard]] bool push(KeeperState K_, int count_, bool enforceLimit_); // keepercall_send and keepercall_set
90 void pushFillStatus(KeeperState K_) const;
91 static void PushFillStatus(KeeperState K_, KeyUD const* key_);
86 [[nodiscard]] bool reset(KeeperState K_); 92 [[nodiscard]] bool reset(KeeperState K_);
87}; 93};
88 94
@@ -232,6 +238,35 @@ bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit
232 238
233// ################################################################################################# 239// #################################################################################################
234 240
241void KeyUD::pushFillStatus(KeeperState const K_) const
242{
243 if (limit < 0) {
244 luaG_pushstring(K_, kUnder);
245 return;
246 }
247 int const _delta{limit - count};
248 if (_delta < 0) {
249 luaG_pushstring(K_, kOver);
250 } else if (_delta > 0) {
251 luaG_pushstring(K_, kUnder);
252 } else {
253 luaG_pushstring(K_, kExact);
254 }
255}
256
257// #################################################################################################
258
259void KeyUD::PushFillStatus(KeeperState const K_, KeyUD const* const key_)
260{
261 if (key_) {
262 key_->pushFillStatus(K_); // _K: ... <fill status>
263 } else {
264 luaG_pushstring(K_, KeyUD::kUnder); // _K: ... "under"
265 }
266}
267
268// #################################################################################################
269
235// expects 'this' on top of the stack 270// expects 'this' on top of the stack
236bool KeyUD::reset(KeeperState const K_) 271bool KeyUD::reset(KeeperState const K_)
237{ 272{
@@ -394,10 +429,11 @@ int keepercall_get(lua_State* const L_)
394// ################################################################################################# 429// #################################################################################################
395 430
396// in: linda key [n|nil] 431// in: linda key [n|nil]
397// out: true or nil 432// out: boolean, <fill status: string>
398int keepercall_limit(lua_State* const L_) 433int keepercall_limit(lua_State* const L_)
399{ 434{
400 KeeperState const _K{ L_ }; 435 KeeperState const _K{ L_ };
436 STACK_CHECK_START_ABS(_K, lua_gettop(_K));
401 // no limit to set, means we read and return the current limit instead 437 // no limit to set, means we read and return the current limit instead
402 bool const _reading{ lua_gettop(_K) == 2 }; 438 bool const _reading{ lua_gettop(_K) == 2 };
403 LindaLimit const _limit{ static_cast<LindaLimit::type>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent 439 LindaLimit const _limit{ static_cast<LindaLimit::type>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent
@@ -408,10 +444,12 @@ int keepercall_limit(lua_State* const L_)
408 lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil 444 lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil
409 KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; 445 KeyUD* _key{ KeyUD::GetPtr(_K, -1) };
410 if (_reading) { 446 if (_reading) {
447 // remove any clutter on the stack
448 lua_settop(_K, 0); // _K:
411 if (_key && _key->limit >= 0) { 449 if (_key && _key->limit >= 0) {
412 lua_pushinteger(_K, _key->limit); // _K: KeysDB key KeyUD limit 450 lua_pushinteger(_K, _key->limit); // _K: limit
413 } else { // if the key doesn't exist, it is unlimited by default 451 } else { // if the key doesn't exist, it is unlimited by default
414 luaG_pushstring(_K, "unlimited"); // _K: KeysDB key KeyUD "unlimited" 452 luaG_pushstring(_K, "unlimited"); // _K: "unlimited"
415 } 453 }
416 // return a single value: the limit of the key 454 // return a single value: the limit of the key
417 } else { 455 } else {
@@ -426,7 +464,9 @@ int keepercall_limit(lua_State* const L_)
426 // this is the case if we detect the key was full but it is no longer the case 464 // this is the case if we detect the key was full but it is no longer the case
427 lua_pushboolean(_K, _key->changeLimit(_limit) ? 1 : 0); // _K: bool 465 lua_pushboolean(_K, _key->changeLimit(_limit) ? 1 : 0); // _K: bool
428 } 466 }
429 return 1; 467 KeyUD::PushFillStatus(_K, _key); // _K: limit|bool <fill status>
468 STACK_CHECK(_K, 2);
469 return 2;
430} 470}
431 471
432// ################################################################################################# 472// #################################################################################################
@@ -538,12 +578,12 @@ int keepercall_set(lua_State* const L_)
538 // retrieve KeysDB associated with the linda 578 // retrieve KeysDB associated with the linda
539 PushKeysDB(_K, 1); // _K: linda key val... KeysDB 579 PushKeysDB(_K, 1); // _K: linda key val... KeysDB
540 lua_replace(_K, 1); // _K: KeysDB key val... 580 lua_replace(_K, 1); // _K: KeysDB key val...
581 lua_pushvalue(_K, 2); // _K: KeysDB key val... key
582 lua_rawget(_K, 1); // _K: KeysDB key val KeyUD|nil
583 KeyUD* _key{ KeyUD::GetPtr(_K, -1) };
541 584
542 if (lua_gettop(_K) == 2) { // no value to set // _K: KeysDB key 585 if (lua_gettop(_K) == 3) { // no value to set // _K: KeysDB key KeyUD|nil
543 lua_pushvalue(_K, -1); // _K: KeysDB key key
544 lua_rawget(_K, 1); // _K: KeysDB key KeyUD|nil
545 // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! 586 // empty the KeyUD for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
546 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
547 if (_key != nullptr) { // might be nullptr if we set a nonexistent key to nil // _K: KeysDB key KeyUD 587 if (_key != nullptr) { // might be nullptr if we set a nonexistent key to nil // _K: KeysDB key KeyUD
548 if (_key->limit < 0) { // KeyUD limit value is the default (unlimited): we can totally remove it 588 if (_key->limit < 0) { // KeyUD limit value is the default (unlimited): we can totally remove it
549 lua_pop(_K, 1); // _K: KeysDB key 589 lua_pop(_K, 1); // _K: KeysDB key
@@ -555,18 +595,17 @@ int keepercall_set(lua_State* const L_)
555 _should_wake_writers = _key->reset(_K); 595 _should_wake_writers = _key->reset(_K);
556 } 596 }
557 } 597 }
598 lua_settop(_K, 0); // we are done, remove everything // _K:
558 } else { // set/replace contents stored at the specified key? 599 } else { // set/replace contents stored at the specified key?
559 int const _count{ lua_gettop(_K) - 2 }; // number of items we want to store 600 int const _count{ lua_gettop(_K) - 3 }; // number of items we want to store // _K: KeysDB key val... KeyUD|nil
560 lua_pushvalue(_K, 2); // _K: KeysDB key val... key 601 if (_key == nullptr) { // can be nullptr if we store a value at a new key // _K: KeysDB key val... nil
561 lua_rawget(_K, 1); // _K: KeysDB key val... KeyUD|nil 602 assert(lua_isnil(_K, -1));
562 KeyUD* _key{ KeyUD::GetPtr(_K, -1) };
563 if (_key == nullptr) { // can be nullptr if we store a value at a new key // KeysDB key val... nil
564 // no need to wake writers in that case, because a writer can't wait on an inexistent key
565 lua_pop(_K, 1); // _K: KeysDB key val... 603 lua_pop(_K, 1); // _K: KeysDB key val...
566 _key = KeyUD::Create(KeeperState{ _K }); // _K: KeysDB key val... KeyUD 604 _key = KeyUD::Create(KeeperState{ _K }); // _K: KeysDB key val... KeyUD
567 lua_pushvalue(_K, 2); // _K: KeysDB key val... KeyUD key 605 lua_pushvalue(_K, 2); // _K: KeysDB key val... KeyUD key
568 lua_pushvalue(_K, -2); // _K: KeysDB key val... KeyUD key KeyUD 606 lua_pushvalue(_K, -2); // _K: KeysDB key val... KeyUD key KeyUD
569 lua_rawset(_K, 1); // _K: KeysDB key val... KeyUD 607 lua_rawset(_K, 1); // _K: KeysDB key val... KeyUD
608 // no need to wake writers, because a writer can't wait on an inexistent key
570 } else { // _K: KeysDB key val... KeyUD 609 } else { // _K: KeysDB key val... KeyUD
571 // the KeyUD exists, we just want to update its contents 610 // the KeyUD exists, we just want to update its contents
572 // we create room if the KeyUD was full but we didn't refill it to the brim with new data 611 // we create room if the KeyUD was full but we didn't refill it to the brim with new data
@@ -575,10 +614,12 @@ int keepercall_set(lua_State* const L_)
575 // replace the key with the KeyUD in the stack 614 // replace the key with the KeyUD in the stack
576 lua_replace(_K, -2 - _count); // _K: KeysDB KeyUD val... 615 lua_replace(_K, -2 - _count); // _K: KeysDB KeyUD val...
577 [[maybe_unused]] bool const _pushed{ _key->push(_K, _count, false) }; // _K: KeysDB 616 [[maybe_unused]] bool const _pushed{ _key->push(_K, _count, false) }; // _K: KeysDB
617 lua_pop(_K, 1); // _K:
578 } 618 }
579 // stack isn't the same here depending on what we did before, but that's not a problem 619 assert(lua_gettop(_K) == 0);
580 lua_pushboolean(_K, _should_wake_writers ? 1 : 0); // _K: ... bool 620 lua_pushboolean(_K, _should_wake_writers ? 1 : 0); // _K: bool
581 return 1; 621 KeyUD::PushFillStatus(_K, _key); // _K: bool <fill status>
622 return 2;
582} 623}
583 624
584// ################################################################################################# 625// #################################################################################################