aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 14:43:39 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-04 14:43:39 +0200
commit046f07e1a79f0d39b1db5f69f6132dbe70cda2a4 (patch)
tree657561aceb9cfab85ed32e456c7472c504b9b002 /src
parent20e551590b4491dade12191caf94411e7ec67dd9 (diff)
downloadlanes-046f07e1a79f0d39b1db5f69f6132dbe70cda2a4.tar.gz
lanes-046f07e1a79f0d39b1db5f69f6132dbe70cda2a4.tar.bz2
lanes-046f07e1a79f0d39b1db5f69f6132dbe70cda2a4.zip
Moved keeper functions around
Diffstat (limited to 'src')
-rw-r--r--src/keeper.cpp295
-rw-r--r--src/keeper.h12
-rw-r--r--src/lindafactory.cpp2
3 files changed, 155 insertions, 154 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index f1079e4..1779ab3 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -306,8 +306,72 @@ int keeper_push_linda_storage(Linda& linda_, DestState L_)
306// ################################################################################################# 306// #################################################################################################
307// ################################################################################################# 307// #################################################################################################
308 308
309// in: linda [, key [, ...]]
310int keepercall_count(lua_State* const L_)
311{
312 KeeperState const _K{ L_ };
313 switch (lua_gettop(_K)) {
314 // no key is specified: return a table giving the count of all known keys
315 case 1: // _K: linda
316 PushKeysDB(_K, 1); // _K: linda KeysDB
317 lua_newtable(_K); // _K: linda KeysDB out
318 lua_replace(_K, 1); // _K: out KeysDB
319 lua_pushnil(_K); // _K: out KeysDB nil
320 while (lua_next(_K, 2)) { // _K: out KeysDB key KeyUD
321 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
322 lua_pop(_K, 1); // _K: out KeysDB key
323 lua_pushvalue(_K, -1); // _K: out KeysDB key key
324 lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count
325 lua_rawset(_K, -5); // _K: out KeysDB key
326 }
327 lua_pop(_K, 1); // _K: out
328 break;
329
330 // 1 key is specified: return its count
331 case 2: // _K: linda key
332 PushKeysDB(_K, 1); // _K: linda key KeysDB
333 lua_replace(_K, 1); // _K: KeysDB key
334 lua_rawget(_K, -2); // _K: KeysDB KeyUD|nil
335 if (lua_isnil(_K, -1)) { // the key is unknown // _K: KeysDB nil
336 lua_remove(_K, -2); // _K: nil
337 } else { // the key is known // _K: KeysDB KeyUD
338 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
339 lua_pushinteger(_K, _key->count); // _K: KeysDB KeyUD count
340 lua_replace(_K, -3); // _K: count KeyUD
341 lua_pop(_K, 1); // _K: count
342 }
343 break;
344
345 // a variable number of keys is specified: return a table of their counts
346 default: // _K: linda keys... key#1
347 lua_pushvalue(_K, 2); // duplicate the first key of the list // _K: linda keys... key#1
348 PushKeysDB(_K, 1); // _K: linda keys... key#1 KeysDB
349 lua_newtable(_K); // _K: linda keys... key#1 KeysDB out
350 lua_replace(_K, 1); // _K: out keys... key#1 KeysDB
351 lua_replace(_K, 2); // the list of keys is the same, but for key#1 moved at the end // _K: out KeysDB keys...
352 while (lua_gettop(_K) > 2) {
353 lua_pushvalue(_K, -1); // _K: out KeysDB keys... key
354 lua_rawget(_K, 2); // _K: out KeysDB keys... KeyUD|nil
355 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
356 lua_pop(_K, 1); // _K: out KeysDB keys...
357 if (_key != nullptr) { // the key is known
358 lua_pushinteger(_K, _key->count); // _K: out KeysDB keys... count
359 lua_rawset(_K, 1); // _K: out KeysDB keys...
360 } else { // the key is unknown
361 lua_pop(_K, 1); // _K: out KeysDB keys...
362 }
363 } // all keys are exhausted // _K: out KeysDB
364 lua_pop(_K, 1); // _K: out
365 }
366 LUA_ASSERT(_K, lua_gettop(_K) == 1);
367 return 1;
368}
369
370// #################################################################################################
371
309// in: linda 372// in: linda
310int keepercall_clear(lua_State* const L_) 373// not part of the linda public API, only used for cleanup at linda GC
374int keepercall_destruct(lua_State* const L_)
311{ 375{
312 STACK_GROW(L_, 3); 376 STACK_GROW(L_, 3);
313 STACK_CHECK_START_REL(L_, 0); 377 STACK_CHECK_START_REL(L_, 0);
@@ -323,41 +387,64 @@ int keepercall_clear(lua_State* const L_)
323 387
324// ################################################################################################# 388// #################################################################################################
325 389
326// in: linda_ud, key, ... 390// in: linda_ud key [count]
327// out: true|false 391// out: at most <count> values
328int keepercall_send(lua_State* const L_) 392int keepercall_get(lua_State* const L_)
329{ 393{
330 KeeperState const _K{ L_ }; 394 KeeperState const _K{ L_ };
331 int const _n{ lua_gettop(_K) - 2 }; 395 int _count{ 1 };
332 STACK_CHECK_START_REL(_K, 0); 396 if (lua_gettop(_K) == 3) { // _K: linda key count
333 PushKeysDB(_K, 1); // _K: linda key args... KeysDB 397 _count = static_cast<int>(lua_tointeger(_K, 3)); // linda:get() made sure _count >= 1
334 // get the fifo associated to this key in this linda, create it if it doesn't exist 398 lua_pop(_K, 1); // _K: linda key
335 lua_pushvalue(_K, 2); // _K: linda key args... KeysDB key
336 lua_rawget(_K, -2); // _K: linda key args... KeysDB KeyUD|nil
337 if (lua_isnil(_K, -1)) {
338 lua_pop(_K, 1); // _K: linda key args... KeysDB
339 std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key args... KeysDB KeyUD
340 // KeysDB[key] = KeyUD
341 lua_pushvalue(_K, 2); // _K: linda key args... KeysDB KeyUD key
342 lua_pushvalue(_K, -2); // _K: linda key args... KeysDB KeyUD key KeyUD
343 lua_rawset(_K, -4); // _K: linda key args... KeysDB KeyUD
344 } 399 }
345 lua_remove(_K, -2); // _K: linda key args... KeyUD 400 PushKeysDB(_K, 1); // _K: linda key KeysDB
346 STACK_CHECK(_K, 1); 401 lua_replace(_K, 1); // _K: KeysDB key
402 lua_rawget(_K, 1); // _K: KeysDB KeyUD
403 lua_remove(_K, 1); // _K: KeyUD
347 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) }; 404 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
348 if (_key->limit >= 0 && _key->count + _n > _key->limit) { // not enough room? 405 if (_key != nullptr) {
349 // don't send anything 406 _key->peek(_K, _count); // _K: val...
350 lua_settop(_K, 0); // _K:
351 lua_pushboolean(_K, 0); // _K: false
352 } else { 407 } else {
353 // _key should remain unchanged 408 // no fifo was ever registered for this key, or it is empty
354 _key->prepareAccess(_K); // _K: linda key args... fifo 409 lua_pop(_K, 1); // _K:
355 lua_replace(_K, 2); // _K: linda fifo args... 410 }
356 _key->push(_K, _n); // _K: linda fifo 411 return lua_gettop(_K);
357 lua_settop(_K, 0); // _K: 412}
413
414// #################################################################################################
415
416// in: linda key [n|nil]
417// out: true or nil
418int keepercall_limit(lua_State* const L_)
419{
420 KeeperState const _K{ L_ };
421 int const _limit{ static_cast<int>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent
422 lua_settop(_K, 2); // _K: linda key
423 PushKeysDB(_K, 1); // _K: linda key KeysDB
424 lua_replace(_K, 1); // _K: KeysDB key
425 lua_pushvalue(_K, -1); // _K: KeysDB key key
426 lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil
427 KeyUD* _key{ KeyUD::GetPtr(_K, -1) };
428 if (_key == nullptr) { // _K: KeysDB key nil
429 lua_pop(_K, 1); // _K: KeysDB key
430 _key = KeyUD::Create(_K); // _K: KeysDB key KeyUD
431 lua_rawset(_K, -3); // _K: KeysDB
432 }
433 // remove any clutter on the stack
434 lua_settop(_K, 0); // _K:
435 // return true if we decide that blocked threads waiting to write on that key should be awakened
436 // this is the case if we detect the key was full but it is no longer the case
437 // TODO: make this KeyUD::changeLimit() -> was full (bool)
438 if (
439 ((_key->limit >= 0) && (_key->count >= _key->limit)) // the key was full if limited and count exceeded the previous limit
440 && ((_limit < 0) || (_key->count < _limit)) // the key is not full if unlimited or count is lower than the new limit
441 ) {
358 lua_pushboolean(_K, 1); // _K: true 442 lua_pushboolean(_K, 1); // _K: true
359 } 443 }
360 return 1; 444 // set the new limit
445 _key->limit = _limit;
446 // return 0 or 1 value
447 return lua_gettop(_K);
361} 448}
362 449
363// ################################################################################################# 450// #################################################################################################
@@ -427,38 +514,41 @@ int keepercall_receive_batched(lua_State* const L_)
427 514
428// ################################################################################################# 515// #################################################################################################
429 516
430// in: linda_ud key [n|nil] 517// in: linda_ud, key, ...
431// out: true or nil 518// out: true|false
432int keepercall_limit(lua_State* const L_) 519int keepercall_send(lua_State* const L_)
433{ 520{
434 KeeperState const _K{ L_ }; 521 KeeperState const _K{ L_ };
435 int const _limit{ static_cast<int>(luaL_optinteger(_K, 3, -1)) }; // -1 if we read nil because the argument is absent 522 int const _n{ lua_gettop(_K) - 2 };
436 lua_settop(_K, 2); // _K: linda key 523 STACK_CHECK_START_REL(_K, 0);
437 PushKeysDB(_K, 1); // _K: linda key KeysDB 524 PushKeysDB(_K, 1); // _K: linda key args... KeysDB
438 lua_replace(_K, 1); // _K: KeysDB key 525 // get the fifo associated to this key in this linda, create it if it doesn't exist
439 lua_pushvalue(_K, -1); // _K: KeysDB key key 526 lua_pushvalue(_K, 2); // _K: linda key args... KeysDB key
440 lua_rawget(_K, -3); // _K: KeysDB key KeyUD|nil 527 lua_rawget(_K, -2); // _K: linda key args... KeysDB KeyUD|nil
441 KeyUD* _key{ KeyUD::GetPtr(_K, -1) }; 528 if (lua_isnil(_K, -1)) {
442 if (_key == nullptr) { // _K: KeysDB key nil 529 lua_pop(_K, 1); // _K: linda key args... KeysDB
443 lua_pop(_K, 1); // _K: KeysDB key 530 std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key args... KeysDB KeyUD
444 _key = KeyUD::Create(_K); // _K: KeysDB key KeyUD 531 // KeysDB[key] = KeyUD
445 lua_rawset(_K, -3); // _K: KeysDB 532 lua_pushvalue(_K, 2); // _K: linda key args... KeysDB KeyUD key
533 lua_pushvalue(_K, -2); // _K: linda key args... KeysDB KeyUD key KeyUD
534 lua_rawset(_K, -4); // _K: linda key args... KeysDB KeyUD
446 } 535 }
447 // remove any clutter on the stack 536 lua_remove(_K, -2); // _K: linda key args... KeyUD
448 lua_settop(_K, 0); // _K: 537 STACK_CHECK(_K, 1);
449 // return true if we decide that blocked threads waiting to write on that key should be awakened 538 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
450 // this is the case if we detect the key was full but it is no longer the case 539 if (_key->limit >= 0 && _key->count + _n > _key->limit) { // not enough room?
451 // TODO: make this KeyUD::changeLimit() -> was full (bool) 540 // don't send anything
452 if ( 541 lua_settop(_K, 0); // _K:
453 ((_key->limit >= 0) && (_key->count >= _key->limit)) // the key was full if limited and count exceeded the previous limit 542 lua_pushboolean(_K, 0); // _K: false
454 && ((_limit < 0) || (_key->count < _limit)) // the key is not full if unlimited or count is lower than the new limit 543 } else {
455 ) { 544 // _key should remain unchanged
545 _key->prepareAccess(_K); // _K: linda key args... fifo
546 lua_replace(_K, 2); // _K: linda fifo args...
547 _key->push(_K, _n); // _K: linda fifo
548 lua_settop(_K, 0); // _K:
456 lua_pushboolean(_K, 1); // _K: true 549 lua_pushboolean(_K, 1); // _K: true
457 } 550 }
458 // set the new limit 551 return 1;
459 _key->limit = _limit;
460 // return 0 or 1 value
461 return lua_gettop(_K);
462} 552}
463 553
464// ################################################################################################# 554// #################################################################################################
@@ -519,95 +609,6 @@ int keepercall_set(lua_State* const L_)
519 609
520// ################################################################################################# 610// #################################################################################################
521 611
522// in: linda_ud key [count]
523// out: at most <count> values
524int keepercall_get(lua_State* const L_)
525{
526 KeeperState const _K{ L_ };
527 int _count{ 1 };
528 if (lua_gettop(_K) == 3) { // _K: linda key count
529 _count = static_cast<int>(lua_tointeger(_K, 3)); // linda:get() made sure _count >= 1
530 lua_pop(_K, 1); // _K: linda key
531 }
532 PushKeysDB(_K, 1); // _K: linda key KeysDB
533 lua_replace(_K, 1); // _K: KeysDB key
534 lua_rawget(_K, 1); // _K: KeysDB KeyUD
535 lua_remove(_K, 1); // _K: KeyUD
536 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
537 if (_key != nullptr) {
538 _key->peek(_K, _count); // _K: val...
539 } else {
540 // no fifo was ever registered for this key, or it is empty
541 lua_pop(_K, 1); // _K:
542 }
543 return lua_gettop(_K);
544}
545
546// #################################################################################################
547
548// in: linda_ud [, key [, ...]]
549int keepercall_count(lua_State* const L_)
550{
551 KeeperState const _K{ L_ };
552 switch (lua_gettop(_K)) {
553 // no key is specified: return a table giving the count of all known keys
554 case 1: // _K: linda
555 PushKeysDB(_K, 1); // _K: linda KeysDB
556 lua_newtable(_K); // _K: linda KeysDB out
557 lua_replace(_K, 1); // _K: out KeysDB
558 lua_pushnil(_K); // _K: out KeysDB nil
559 while (lua_next(_K, 2)) { // _K: out KeysDB key KeyUD
560 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
561 lua_pop(_K, 1); // _K: out KeysDB key
562 lua_pushvalue(_K, -1); // _K: out KeysDB key key
563 lua_pushinteger(_K, _key->count); // _K: out KeysDB key key count
564 lua_rawset(_K, -5); // _K: out KeysDB key
565 }
566 lua_pop(_K, 1); // _K: out
567 break;
568
569 // 1 key is specified: return its count
570 case 2: // _K: linda key
571 PushKeysDB(_K, 1); // _K: linda key KeysDB
572 lua_replace(_K, 1); // _K: KeysDB key
573 lua_rawget(_K, -2); // _K: KeysDB KeyUD|nil
574 if (lua_isnil(_K, -1)) { // the key is unknown // _K: KeysDB nil
575 lua_remove(_K, -2); // _K: nil
576 } else { // the key is known // _K: KeysDB KeyUD
577 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
578 lua_pushinteger(_K, _key->count); // _K: KeysDB KeyUD count
579 lua_replace(_K, -3); // _K: count KeyUD
580 lua_pop(_K, 1); // _K: count
581 }
582 break;
583
584 // a variable number of keys is specified: return a table of their counts
585 default: // _K: linda keys... key#1
586 lua_pushvalue(_K, 2); // duplicate the first key of the list // _K: linda keys... key#1
587 PushKeysDB(_K, 1); // _K: linda keys... key#1 KeysDB
588 lua_newtable(_K); // _K: linda keys... key#1 KeysDB out
589 lua_replace(_K, 1); // _K: out keys... key#1 KeysDB
590 lua_replace(_K, 2); // the list of keys is the same, but for key#1 moved at the end // _K: out KeysDB keys...
591 while (lua_gettop(_K) > 2) {
592 lua_pushvalue(_K, -1); // _K: out KeysDB keys... key
593 lua_rawget(_K, 2); // _K: out KeysDB keys... KeyUD|nil
594 KeyUD* const _key{ KeyUD::GetPtr(_K, -1) };
595 lua_pop(_K, 1); // _K: out KeysDB keys...
596 if (_key != nullptr) { // the key is known
597 lua_pushinteger(_K, _key->count); // _K: out KeysDB keys... count
598 lua_rawset(_K, 1); // _K: out KeysDB keys...
599 } else { // the key is unknown
600 lua_pop(_K, 1); // _K: out KeysDB keys...
601 }
602 } // all keys are exhausted // _K: out KeysDB
603 lua_pop(_K, 1); // _K: out
604 }
605 LUA_ASSERT(_K, lua_gettop(_K) == 1);
606 return 1;
607}
608
609// #################################################################################################
610
611/* 612/*
612 * Call a function ('func_name') in the keeper state, and pass on the returned 613 * Call a function ('func_name') in the keeper state, and pass on the returned
613 * values to 'L'. 614 * values to 'L'.
@@ -626,7 +627,7 @@ KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_,
626 LUA_ASSERT(L_, _top_K == 0); 627 LUA_ASSERT(L_, _top_K == 0);
627 628
628 STACK_GROW(K_, 2); 629 STACK_GROW(K_, 2);
629 PUSH_KEEPER_FUNC(K_, func_); // L: ... args... K_: func_ 630 lua_pushcclosure(K_, func_, 0); // L: ... args... K_: func_
630 lua_pushlightuserdata(K_, linda_); // L: ... args... K_: func_ linda 631 lua_pushlightuserdata(K_, linda_); // L: ... args... K_: func_ linda
631 if ( 632 if (
632 (_args == 0) || 633 (_args == 0) ||
@@ -649,7 +650,7 @@ KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_,
649 lua_settop(K_, _top_K); // L: ... args... result... K_: 650 lua_settop(K_, _top_K); // L: ... args... result... K_:
650 651
651 // don't do this for this particular function, as it is only called during Linda destruction, and we don't want to raise an error, ever 652 // don't do this for this particular function, as it is only called during Linda destruction, and we don't want to raise an error, ever
652 if (func_ != KEEPER_API(clear)) [[unlikely]] { 653 if (func_ != KEEPER_API(destruct)) [[unlikely]] {
653 // since keeper state GC is stopped, let's run a step once in a while if required 654 // since keeper state GC is stopped, let's run a step once in a while if required
654 int const _gc_threshold{ linda_->U->keepers.gc_threshold }; 655 int const _gc_threshold{ linda_->U->keepers.gc_threshold };
655 if (_gc_threshold == 0) [[unlikely]] { 656 if (_gc_threshold == 0) [[unlikely]] {
diff --git a/src/keeper.h b/src/keeper.h
index 682c710..1425a3b 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -87,16 +87,16 @@ static constexpr UniqueKey kNilSentinel{ 0xC457D4EDDB05B5E4ull, "lanes.null" };
87 87
88using keeper_api_t = lua_CFunction; 88using keeper_api_t = lua_CFunction;
89#define KEEPER_API(_op) keepercall_##_op 89#define KEEPER_API(_op) keepercall_##_op
90#define PUSH_KEEPER_FUNC lua_pushcfunction 90
91// lua_Cfunctions to run inside a keeper state 91// lua_Cfunctions to run inside a keeper state
92[[nodiscard]] int keepercall_clear(lua_State* L_); 92[[nodiscard]] int keepercall_count(lua_State* L_);
93[[nodiscard]] int keepercall_send(lua_State* L_); 93[[nodiscard]] int keepercall_destruct(lua_State* L_);
94[[nodiscard]] int keepercall_get(lua_State* L_);
95[[nodiscard]] int keepercall_limit(lua_State* L_);
94[[nodiscard]] int keepercall_receive(lua_State* L_); 96[[nodiscard]] int keepercall_receive(lua_State* L_);
95[[nodiscard]] int keepercall_receive_batched(lua_State* L_); 97[[nodiscard]] int keepercall_receive_batched(lua_State* L_);
96[[nodiscard]] int keepercall_limit(lua_State* L_); 98[[nodiscard]] int keepercall_send(lua_State* L_);
97[[nodiscard]] int keepercall_get(lua_State* L_);
98[[nodiscard]] int keepercall_set(lua_State* L_); 99[[nodiscard]] int keepercall_set(lua_State* L_);
99[[nodiscard]] int keepercall_count(lua_State* L_);
100 100
101using KeeperCallResult = Unique<std::optional<int>>; 101using KeeperCallResult = Unique<std::optional<int>>;
102[[nodiscard]] KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, int starting_index_); 102[[nodiscard]] KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, int starting_index_);
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp
index 6d26852..94dd3ab 100644
--- a/src/lindafactory.cpp
+++ b/src/lindafactory.cpp
@@ -79,7 +79,7 @@ void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) cons
79 // Clean associated structures in the keeper state. 79 // Clean associated structures in the keeper state.
80 Keeper* const _K{ _need_acquire_release ? _linda->acquireKeeper() : _myK }; 80 Keeper* const _K{ _need_acquire_release ? _linda->acquireKeeper() : _myK };
81 // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... 81 // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex...
82 [[maybe_unused]] KeeperCallResult const result{ keeper_call(_K->L, KEEPER_API(clear), L_, _linda, 0) }; 82 [[maybe_unused]] KeeperCallResult const result{ keeper_call(_K->L, KEEPER_API(destruct), L_, _linda, 0) };
83 LUA_ASSERT(L_, result.has_value() && result.value() == 0); 83 LUA_ASSERT(L_, result.has_value() && result.value() == 0);
84 if (_need_acquire_release) { 84 if (_need_acquire_release) {
85 _linda->releaseKeeper(_K); 85 _linda->releaseKeeper(_K);