aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/keeper.cpp8
-rw-r--r--src/keeper.h2
-rw-r--r--src/linda.cpp82
-rw-r--r--src/lindafactory.cpp13
4 files changed, 53 insertions, 52 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index 3e806f9..b8f2bd0 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -276,7 +276,7 @@ static void PushKeysDB(KeeperState const K_, int const idx_)
276int keeper_push_linda_storage(Linda& linda_, DestState L_) 276int keeper_push_linda_storage(Linda& linda_, DestState L_)
277{ 277{
278 Keeper* const _keeper{ linda_.whichKeeper() }; 278 Keeper* const _keeper{ linda_.whichKeeper() };
279 KeeperState const _K{ _keeper ? _keeper->L : nullptr }; 279 KeeperState const _K{ _keeper ? _keeper->K : nullptr };
280 if (_K == nullptr) { 280 if (_K == nullptr) {
281 return 0; 281 return 0;
282 } 282 }
@@ -710,7 +710,7 @@ void Keeper::operator delete[](void* p_, Universe* U_)
710// ################################################################################################# 710// #################################################################################################
711// ################################################################################################# 711// #################################################################################################
712 712
713void Keepers::DeleteKV::operator()(Keeper* k_) const 713void Keepers::DeleteKV::operator()(Keeper* const k_) const
714{ 714{
715 for (Keeper& _k : std::views::counted(k_, count)) { 715 for (Keeper& _k : std::views::counted(k_, count)) {
716 _k.~Keeper(); 716 _k.~Keeper();
@@ -733,7 +733,7 @@ void Keepers::close()
733 } 733 }
734 734
735 auto _closeOneKeeper = [](Keeper& keeper_) { 735 auto _closeOneKeeper = [](Keeper& keeper_) {
736 lua_State* const _K{ std::exchange(keeper_.L, KeeperState{ nullptr }) }; 736 lua_State* const _K{ std::exchange(keeper_.K, KeeperState{ nullptr }) };
737 if (_K) { 737 if (_K) {
738 lua_close(_K); 738 lua_close(_K);
739 } 739 }
@@ -824,7 +824,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, int const nbKeepers_, int
824 raise_luaL_error(L, "out of memory while creating keeper states"); 824 raise_luaL_error(L, "out of memory while creating keeper states");
825 } 825 }
826 826
827 keeper_.L = _K; 827 keeper_.K = _K;
828 828
829 // Give a name to the state 829 // Give a name to the state
830 std::ignore = luaG_pushstringview(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n" 830 std::ignore = luaG_pushstringview(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n"
diff --git a/src/keeper.h b/src/keeper.h
index 1425a3b..5cc7422 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -28,7 +28,7 @@ using KeeperState = Unique<lua_State*>;
28struct Keeper 28struct Keeper
29{ 29{
30 std::mutex mutex; 30 std::mutex mutex;
31 KeeperState L{ nullptr }; 31 KeeperState K{ nullptr };
32 32
33 [[nodiscard]] static void* operator new[](size_t size_, Universe* U_) noexcept; 33 [[nodiscard]] static void* operator new[](size_t size_, Universe* U_) noexcept;
34 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception 34 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
diff --git a/src/linda.cpp b/src/linda.cpp
index 3449f89..a7d7ee9 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -136,11 +136,11 @@ Linda::~Linda()
136Keeper* Linda::acquireKeeper() const 136Keeper* Linda::acquireKeeper() const
137{ 137{
138 // can be nullptr if this happens during main state shutdown (lanes is being GC'ed -> no keepers) 138 // can be nullptr if this happens during main state shutdown (lanes is being GC'ed -> no keepers)
139 Keeper* const _K{ whichKeeper() }; 139 Keeper* const _keeper{ whichKeeper() };
140 if (_K) { 140 if (_keeper) {
141 _K->mutex.lock(); 141 _keeper->mutex.lock();
142 } 142 }
143 return _K; 143 return _keeper;
144} 144}
145 145
146// ################################################################################################# 146// #################################################################################################
@@ -177,14 +177,14 @@ int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_)
177 Linda* const _linda{ ToLinda<false>(L_, 1) }; 177 Linda* const _linda{ ToLinda<false>(L_, 1) };
178 178
179 // acquire the keeper 179 // acquire the keeper
180 Keeper* const _K{ _linda->acquireKeeper() }; 180 Keeper* const _keeper{ _linda->acquireKeeper() };
181 lua_State* const _KL{ _K ? _K->L : nullptr }; 181 KeeperState const _K{ _keeper ? _keeper->K : nullptr };
182 if (_KL == nullptr) 182 if (_K == nullptr)
183 return 0; 183 return 0;
184 184
185 LUA_ASSERT_CODE(auto const _koip{ _linda->startKeeperOperation(L_) }); 185 LUA_ASSERT_CODE(auto const _koip{ _linda->startKeeperOperation(L_) });
186 // if we didn't do anything wrong, the keeper stack should be clean 186 // if we didn't do anything wrong, the keeper stack should be clean
187 LUA_ASSERT(L_, lua_gettop(_KL) == 0); 187 LUA_ASSERT(L_, lua_gettop(_K) == 0);
188 188
189 // push the function to be called and move it before the arguments 189 // push the function to be called and move it before the arguments
190 lua_pushcfunction(L_, f_); 190 lua_pushcfunction(L_, f_);
@@ -192,10 +192,10 @@ int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_)
192 // do a protected call 192 // do a protected call
193 LuaError const _rc{ lua_pcall(L_, lua_gettop(L_) - 1, LUA_MULTRET, 0) }; 193 LuaError const _rc{ lua_pcall(L_, lua_gettop(L_) - 1, LUA_MULTRET, 0) };
194 // whatever happens, the keeper state stack must be empty when we are done 194 // whatever happens, the keeper state stack must be empty when we are done
195 lua_settop(_KL, 0); 195 lua_settop(_K, 0);
196 196
197 // release the keeper 197 // release the keeper
198 _linda->releaseKeeper(_K); 198 _linda->releaseKeeper(_keeper);
199 199
200 // if there was an error, forward it 200 // if there was an error, forward it
201 if (_rc != LuaError::OK) { 201 if (_rc != LuaError::OK) {
@@ -207,11 +207,11 @@ int Linda::ProtectedCall(lua_State* L_, lua_CFunction f_)
207 207
208// ################################################################################################# 208// #################################################################################################
209 209
210void Linda::releaseKeeper(Keeper* const K_) const 210void Linda::releaseKeeper(Keeper* const keeper_) const
211{ 211{
212 if (K_) { // can be nullptr if we tried to acquire during shutdown 212 if (keeper_) { // can be nullptr if we tried to acquire during shutdown
213 assert(K_ == whichKeeper()); 213 assert(keeper_ == whichKeeper());
214 K_->mutex.unlock(); 214 keeper_->mutex.unlock();
215 } 215 }
216} 216}
217 217
@@ -316,8 +316,8 @@ LUAG_FUNC(linda_count)
316 // make sure the keys are of a valid type 316 // make sure the keys are of a valid type
317 check_key_types(L_, 2, lua_gettop(L_)); 317 check_key_types(L_, 2, lua_gettop(L_));
318 318
319 Keeper* const _K{ _linda->whichKeeper() }; 319 Keeper* const _keeper{ _linda->whichKeeper() };
320 KeeperCallResult const _pushed{ keeper_call(_K->L, KEEPER_API(count), L_, _linda, 2) }; 320 KeeperCallResult const _pushed{ keeper_call(_keeper->K, KEEPER_API(count), L_, _linda, 2) };
321 return OptionalValue(_pushed, L_, "tried to count an invalid key"); 321 return OptionalValue(_pushed, L_, "tried to count an invalid key");
322 }; 322 };
323 return Linda::ProtectedCall(L_, _count); 323 return Linda::ProtectedCall(L_, _count);
@@ -376,8 +376,8 @@ LUAG_FUNC(linda_get)
376 376
377 KeeperCallResult _pushed; 377 KeeperCallResult _pushed;
378 if (_linda->cancelRequest == CancelRequest::None) { 378 if (_linda->cancelRequest == CancelRequest::None) {
379 Keeper* const _K{ _linda->whichKeeper() }; 379 Keeper* const _keeper{ _linda->whichKeeper() };
380 _pushed = keeper_call(_K->L, KEEPER_API(get), L_, _linda, 2); 380 _pushed = keeper_call(_keeper->K, KEEPER_API(get), L_, _linda, 2);
381 } else { // linda is cancelled 381 } else { // linda is cancelled
382 // do nothing and return lanes.cancel_error 382 // do nothing and return lanes.cancel_error
383 kCancelError.pushKey(L_); 383 kCancelError.pushKey(L_);
@@ -415,8 +415,8 @@ LUAG_FUNC(linda_limit)
415 415
416 KeeperCallResult _pushed; 416 KeeperCallResult _pushed;
417 if (_linda->cancelRequest == CancelRequest::None) { 417 if (_linda->cancelRequest == CancelRequest::None) {
418 Keeper* const _K{ _linda->whichKeeper() }; 418 Keeper* const _keeper{ _linda->whichKeeper() };
419 _pushed = keeper_call(_K->L, KEEPER_API(limit), L_, _linda, 2); 419 _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, 2);
420 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 0 || _pushed.value() == 1)); // no error, optional boolean value saying if we should wake blocked writer threads 420 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 0 || _pushed.value() == 1)); // no error, optional boolean value saying if we should wake blocked writer threads
421 if (_pushed.value() == 1) { 421 if (_pushed.value() == 1) {
422 LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::BOOLEAN && lua_toboolean(L_, -1) == 1); 422 LUA_ASSERT(L_, luaG_type(L_, -1) == LuaType::BOOLEAN && lua_toboolean(L_, -1) == 1);
@@ -497,14 +497,14 @@ LUAG_FUNC(linda_receive)
497 } 497 }
498 498
499 Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; 499 Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) };
500 Keeper* const _K{ _linda->whichKeeper() }; 500 Keeper* const _keeper{ _linda->whichKeeper() };
501 KeeperState const _KL{ _K ? _K->L : nullptr }; 501 KeeperState const _K{ _keeper ? _keeper->K : nullptr };
502 if (_KL == nullptr) 502 if (_K == nullptr)
503 return 0; 503 return 0;
504 504
505 CancelRequest _cancel{ CancelRequest::None }; 505 CancelRequest _cancel{ CancelRequest::None };
506 KeeperCallResult _pushed{}; 506 KeeperCallResult _pushed{};
507 STACK_CHECK_START_REL(_KL, 0); 507 STACK_CHECK_START_REL(_K, 0);
508 for (bool _try_again{ true };;) { 508 for (bool _try_again{ true };;) {
509 if (_lane != nullptr) { 509 if (_lane != nullptr) {
510 _cancel = _lane->cancelRequest; 510 _cancel = _lane->cancelRequest;
@@ -517,7 +517,7 @@ LUAG_FUNC(linda_receive)
517 } 517 }
518 518
519 // all arguments of receive() but the first are passed to the keeper's receive function 519 // all arguments of receive() but the first are passed to the keeper's receive function
520 _pushed = keeper_call(_KL, _selected_keeper_receive, L_, _linda, _key_i); 520 _pushed = keeper_call(_K, _selected_keeper_receive, L_, _linda, _key_i);
521 if (!_pushed.has_value()) { 521 if (!_pushed.has_value()) {
522 break; 522 break;
523 } 523 }
@@ -543,9 +543,9 @@ LUAG_FUNC(linda_receive)
543 _lane->waiting_on = &_linda->writeHappened; 543 _lane->waiting_on = &_linda->writeHappened;
544 } 544 }
545 // not enough data to read: wakeup when data was sent, or when timeout is reached 545 // not enough data to read: wakeup when data was sent, or when timeout is reached
546 std::unique_lock<std::mutex> _keeper_lock{ _K->mutex, std::adopt_lock }; 546 std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock };
547 std::cv_status const _status{ _linda->writeHappened.wait_until(_keeper_lock, _until) }; 547 std::cv_status const _status{ _linda->writeHappened.wait_until(_guard, _until) };
548 _keeper_lock.release(); // we don't want to release the lock! 548 _guard.release(); // we don't want to unlock the mutex on exit!
549 _try_again = (_status == std::cv_status::no_timeout); // detect spurious wakeups 549 _try_again = (_status == std::cv_status::no_timeout); // detect spurious wakeups
550 if (_lane != nullptr) { 550 if (_lane != nullptr) {
551 _lane->waiting_on = nullptr; 551 _lane->waiting_on = nullptr;
@@ -553,7 +553,7 @@ LUAG_FUNC(linda_receive)
553 } 553 }
554 } 554 }
555 } 555 }
556 STACK_CHECK(_KL, 0); 556 STACK_CHECK(_K, 0);
557 557
558 if (!_pushed.has_value()) { 558 if (!_pushed.has_value()) {
559 raise_luaL_error(L_, "tried to copy unsupported types"); 559 raise_luaL_error(L_, "tried to copy unsupported types");
@@ -634,12 +634,12 @@ LUAG_FUNC(linda_send)
634 KeeperCallResult _pushed; 634 KeeperCallResult _pushed;
635 { 635 {
636 Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; 636 Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) };
637 Keeper* const _K{ _linda->whichKeeper() }; 637 Keeper* const _keeper{ _linda->whichKeeper() };
638 KeeperState const _KL{ _K ? _K->L : nullptr }; 638 KeeperState const _K{ _keeper ? _keeper->K : nullptr };
639 if (_KL == nullptr) 639 if (_K == nullptr)
640 return 0; 640 return 0;
641 641
642 STACK_CHECK_START_REL(_KL, 0); 642 STACK_CHECK_START_REL(_K, 0);
643 for (bool _try_again{ true };;) { 643 for (bool _try_again{ true };;) {
644 if (_lane != nullptr) { 644 if (_lane != nullptr) {
645 _cancel = _lane->cancelRequest; 645 _cancel = _lane->cancelRequest;
@@ -651,8 +651,8 @@ LUAG_FUNC(linda_send)
651 break; 651 break;
652 } 652 }
653 653
654 STACK_CHECK(_KL, 0); 654 STACK_CHECK(_K, 0);
655 _pushed = keeper_call(_KL, KEEPER_API(send), L_, _linda, _key_i); 655 _pushed = keeper_call(_K, KEEPER_API(send), L_, _linda, _key_i);
656 if (!_pushed.has_value()) { 656 if (!_pushed.has_value()) {
657 break; 657 break;
658 } 658 }
@@ -684,9 +684,9 @@ LUAG_FUNC(linda_send)
684 _lane->waiting_on = &_linda->readHappened; 684 _lane->waiting_on = &_linda->readHappened;
685 } 685 }
686 // could not send because no room: wait until some data was read before trying again, or until timeout is reached 686 // could not send because no room: wait until some data was read before trying again, or until timeout is reached
687 std::unique_lock<std::mutex> _keeper_lock{ _K->mutex, std::adopt_lock }; 687 std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock };
688 std::cv_status const status{ _linda->readHappened.wait_until(_keeper_lock, _until) }; 688 std::cv_status const status{ _linda->readHappened.wait_until(_guard, _until) };
689 _keeper_lock.release(); // we don't want to release the lock! 689 _guard.release(); // we don't want to unlock the mutex on exit!
690 _try_again = (status == std::cv_status::no_timeout); // detect spurious wakeups 690 _try_again = (status == std::cv_status::no_timeout); // detect spurious wakeups
691 if (_lane != nullptr) { 691 if (_lane != nullptr) {
692 _lane->waiting_on = nullptr; 692 _lane->waiting_on = nullptr;
@@ -694,7 +694,7 @@ LUAG_FUNC(linda_send)
694 } 694 }
695 } 695 }
696 } 696 }
697 STACK_CHECK(_KL, 0); 697 STACK_CHECK(_K, 0);
698 } 698 }
699 699
700 if (!_pushed.has_value()) { 700 if (!_pushed.has_value()) {
@@ -736,10 +736,10 @@ LUAG_FUNC(linda_set)
736 // make sure the key is of a valid type (throws an error if not the case) 736 // make sure the key is of a valid type (throws an error if not the case)
737 check_key_types(L_, 2, 2); 737 check_key_types(L_, 2, 2);
738 738
739 Keeper* const _K{ _linda->whichKeeper() }; 739 Keeper* const _keeper{ _linda->whichKeeper() };
740 KeeperCallResult _pushed; 740 KeeperCallResult _pushed;
741 if (_linda->cancelRequest == CancelRequest::None) { 741 if (_linda->cancelRequest == CancelRequest::None) {
742 _pushed = keeper_call(_K->L, KEEPER_API(set), L_, _linda, 2); 742 _pushed = keeper_call(_keeper->K, KEEPER_API(set), L_, _linda, 2);
743 if (_pushed.has_value()) { // no error? 743 if (_pushed.has_value()) { // no error?
744 LUA_ASSERT(L_, _pushed.value() == 0 || _pushed.value() == 1); 744 LUA_ASSERT(L_, _pushed.value() == 0 || _pushed.value() == 1);
745 745
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp
index 6a2b000..9a75b4f 100644
--- a/src/lindafactory.cpp
+++ b/src/lindafactory.cpp
@@ -70,19 +70,20 @@ void LindaFactory::deleteDeepObjectInternal(lua_State* L_, DeepPrelude* o_) cons
70{ 70{
71 Linda* const _linda{ static_cast<Linda*>(o_) }; 71 Linda* const _linda{ static_cast<Linda*>(o_) };
72 LUA_ASSERT(L_, _linda && !_linda->inKeeperOperation()); 72 LUA_ASSERT(L_, _linda && !_linda->inKeeperOperation());
73 Keeper* const _myK{ _linda->whichKeeper() }; 73 Keeper* const _myKeeper{ _linda->whichKeeper() };
74 // if collected after the universe, keepers are already destroyed, and there is nothing to clear 74 // if collected after the universe, keepers are already destroyed, and there is nothing to clear
75 if (_myK) { 75 if (_myKeeper) {
76 // if collected from my own keeper, we can't acquire/release it 76 // if collected from my own keeper, we can't acquire/release it
77 // because we are already inside a protected area, and trying to do so would deadlock! 77 // because we are already inside a protected area, and trying to do so would deadlock!
78 bool const _need_acquire_release{ _myK->L != L_ }; 78 bool const _need_acquire_release{ _myKeeper->K != L_ };
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 _keeper{ _need_acquire_release ? _linda->acquireKeeper() : _myKeeper };
81 LUA_ASSERT(L_, _keeper == _myKeeper); // should always be the same
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 // 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(destruct), L_, _linda, 0) }; 83 [[maybe_unused]] KeeperCallResult const result{ keeper_call(_keeper->K, KEEPER_API(destruct), L_, _linda, 0) };
83 LUA_ASSERT(L_, result.has_value() && result.value() == 0); 84 LUA_ASSERT(L_, result.has_value() && result.value() == 0);
84 if (_need_acquire_release) { 85 if (_need_acquire_release) {
85 _linda->releaseKeeper(_K); 86 _linda->releaseKeeper(_keeper);
86 } 87 }
87 } 88 }
88 89