diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-28 11:09:02 +0100 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-28 11:09:02 +0100 |
| commit | dce4fbc640fc41241c77aaf31da51b8fcc0f11d9 (patch) | |
| tree | a0bdf4412bc7556c0b1c24f1e5f401c1960eb8c4 /src | |
| parent | caf556e2dcb3df4992dd386a2b37535df42fc880 (diff) | |
| download | lanes-dce4fbc640fc41241c77aaf31da51b8fcc0f11d9.tar.gz lanes-dce4fbc640fc41241c77aaf31da51b8fcc0f11d9.tar.bz2 lanes-dce4fbc640fc41241c77aaf31da51b8fcc0f11d9.zip | |
C++ migration: less kludgy Linda name management with a std::variant
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.cpp | 4 | ||||
| -rw-r--r-- | src/lanes_private.h | 2 | ||||
| -rw-r--r-- | src/linda.cpp | 226 |
3 files changed, 158 insertions, 74 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 72652ef..a378a88 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -142,8 +142,6 @@ static constexpr UniqueKey STACKTRACE_REGKEY{ 0x534af7d3226a429full }; | |||
| 142 | // crc64/we of string "FINALIZER_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | 142 | // crc64/we of string "FINALIZER_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
| 143 | static constexpr UniqueKey FINALIZER_REGKEY{ 0x188fccb8bf348e09ull }; | 143 | static constexpr UniqueKey FINALIZER_REGKEY{ 0x188fccb8bf348e09ull }; |
| 144 | 144 | ||
| 145 | struct s_Linda; | ||
| 146 | |||
| 147 | /* | 145 | /* |
| 148 | * Push a table stored in registry onto Lua stack. | 146 | * Push a table stored in registry onto Lua stack. |
| 149 | * | 147 | * |
| @@ -892,7 +890,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) | |||
| 892 | lua_setglobal( L, "set_finalizer"); | 890 | lua_setglobal( L, "set_finalizer"); |
| 893 | 891 | ||
| 894 | // Tie "set_debug_threadname()" to the state | 892 | // Tie "set_debug_threadname()" to the state |
| 895 | // But don't register it in the lookup database because of the s_lane pointer upvalue | 893 | // But don't register it in the lookup database because of the Lane pointer upvalue |
| 896 | lua_pushlightuserdata( L, s); | 894 | lua_pushlightuserdata( L, s); |
| 897 | lua_pushcclosure( L, LG_set_debug_threadname, 1); | 895 | lua_pushcclosure( L, LG_set_debug_threadname, 1); |
| 898 | lua_setglobal( L, "set_debug_threadname"); | 896 | lua_setglobal( L, "set_debug_threadname"); |
diff --git a/src/lanes_private.h b/src/lanes_private.h index 5d6d25c..85b3c52 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h | |||
| @@ -83,7 +83,7 @@ static inline Lane* get_lane_from_registry( lua_State* L) | |||
| 83 | STACK_GROW( L, 1); | 83 | STACK_GROW( L, 1); |
| 84 | STACK_CHECK_START_REL(L, 0); | 84 | STACK_CHECK_START_REL(L, 0); |
| 85 | CANCEL_TEST_KEY.query_registry(L); | 85 | CANCEL_TEST_KEY.query_registry(L); |
| 86 | Lane* const s{ lua_tolightuserdata<Lane>(L, -1) }; // lightuserdata (true 's_lane' pointer) / nil | 86 | Lane* const s{ lua_tolightuserdata<Lane>(L, -1) }; // lightuserdata (true 'Lane' pointer) / nil |
| 87 | lua_pop( L, 1); | 87 | lua_pop( L, 1); |
| 88 | STACK_CHECK( L, 0); | 88 | STACK_CHECK( L, 0); |
| 89 | return s; | 89 | return s; |
diff --git a/src/linda.cpp b/src/linda.cpp index b28a126..2830593 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
| @@ -42,32 +42,120 @@ THE SOFTWARE. | |||
| 42 | #include "deep.h" | 42 | #include "deep.h" |
| 43 | #include "lanes_private.h" | 43 | #include "lanes_private.h" |
| 44 | 44 | ||
| 45 | #include <array> | ||
| 46 | #include <bit> | ||
| 47 | #include <variant> | ||
| 48 | |||
| 45 | /* | 49 | /* |
| 46 | * Actual data is kept within a keeper state, which is hashed by the 's_Linda' | 50 | * Actual data is kept within a keeper state, which is hashed by the 'Linda' |
| 47 | * pointer (which is same to all userdatas pointing to it). | 51 | * pointer (which is same to all userdatas pointing to it). |
| 48 | */ | 52 | */ |
| 49 | struct s_Linda | 53 | struct Linda : public DeepPrelude // Deep userdata MUST start with this header |
| 50 | { | 54 | { |
| 51 | DeepPrelude prelude; // Deep userdata MUST start with this header | 55 | private: |
| 56 | |||
| 57 | static constexpr size_t kEmbeddedNameLength = 24; | ||
| 58 | using EmbeddedName = std::array<char, kEmbeddedNameLength>; | ||
| 59 | struct AllocatedName | ||
| 60 | { | ||
| 61 | size_t len{ 0 }; | ||
| 62 | char* name{ nullptr }; | ||
| 63 | }; | ||
| 64 | |||
| 65 | public: | ||
| 66 | |||
| 52 | SIGNAL_T read_happened; | 67 | SIGNAL_T read_happened; |
| 53 | SIGNAL_T write_happened; | 68 | SIGNAL_T write_happened; |
| 54 | Universe* U; // the universe this linda belongs to | 69 | Universe* const U; // the universe this linda belongs to |
| 55 | ptrdiff_t group; // a group to control keeper allocation between lindas | 70 | ptrdiff_t const group; // a group to control keeper allocation between lindas |
| 56 | CancelRequest simulate_cancel; | 71 | CancelRequest simulate_cancel{ CancelRequest::None }; |
| 57 | char name[1]; | 72 | std::variant<AllocatedName, EmbeddedName> m_name; |
| 58 | }; | ||
| 59 | #define LINDA_KEEPER_HASHSEED( linda) (linda->group ? linda->group : (ptrdiff_t)linda) | ||
| 60 | 73 | ||
| 74 | public: | ||
| 75 | |||
| 76 | Linda(Universe* U_, ptrdiff_t group_, char const* name_, size_t len_) | ||
| 77 | : U{ U_ } | ||
| 78 | , group{ group_ << KEEPER_MAGIC_SHIFT } | ||
| 79 | { | ||
| 80 | SIGNAL_INIT(&read_happened); | ||
| 81 | SIGNAL_INIT(&write_happened); | ||
| 82 | |||
| 83 | setName(name_, len_); | ||
| 84 | } | ||
| 85 | |||
| 86 | ~Linda() | ||
| 87 | { | ||
| 88 | // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right? | ||
| 89 | SIGNAL_FREE(&read_happened); | ||
| 90 | SIGNAL_FREE(&write_happened); | ||
| 91 | if (std::holds_alternative<AllocatedName>(m_name)) | ||
| 92 | { | ||
| 93 | AllocatedName& name = std::get<AllocatedName>(m_name); | ||
| 94 | U->internal_allocator.free(name.name, name.len); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | private: | ||
| 99 | |||
| 100 | void setName(char const* name_, size_t len_) | ||
| 101 | { | ||
| 102 | // keep default | ||
| 103 | if (!name_ || len_ == 0) | ||
| 104 | { | ||
| 105 | return; | ||
| 106 | } | ||
| 107 | ++len_; // don't forget terminating 0 | ||
| 108 | if (len_ < kEmbeddedNameLength) | ||
| 109 | { | ||
| 110 | m_name.emplace<EmbeddedName>(); | ||
| 111 | char* const name{ std::get<EmbeddedName>(m_name).data() }; | ||
| 112 | memcpy(name, name_, len_); | ||
| 113 | } | ||
| 114 | else | ||
| 115 | { | ||
| 116 | AllocatedName& name = std::get<AllocatedName>(m_name); | ||
| 117 | name.name = static_cast<char*>(U->internal_allocator.alloc(len_)); | ||
| 118 | name.len = len_; | ||
| 119 | memcpy(name.name, name_, len_); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | public: | ||
| 124 | |||
| 125 | ptrdiff_t hashSeed() const { return group ? group : std::bit_cast<ptrdiff_t>(this); } | ||
| 126 | |||
| 127 | char const* getName() const | ||
| 128 | { | ||
| 129 | if (std::holds_alternative<AllocatedName>(m_name)) | ||
| 130 | { | ||
| 131 | AllocatedName const& name = std::get<AllocatedName>(m_name); | ||
| 132 | return name.name; | ||
| 133 | } | ||
| 134 | if (std::holds_alternative<EmbeddedName>(m_name)) | ||
| 135 | { | ||
| 136 | char const* const name{ std::get<EmbeddedName>(m_name).data() }; | ||
| 137 | return name; | ||
| 138 | } | ||
| 139 | return nullptr; | ||
| 140 | } | ||
| 141 | }; | ||
| 61 | static void* linda_id( lua_State*, DeepOp); | 142 | static void* linda_id( lua_State*, DeepOp); |
| 62 | 143 | ||
| 63 | static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_) | 144 | template<bool OPT> |
| 145 | static inline Linda* lua_toLinda(lua_State* L, int idx_) | ||
| 64 | { | 146 | { |
| 65 | struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_); | 147 | Linda* const linda{ static_cast<Linda*>(luaG_todeep(L, linda_id, idx_)) }; |
| 66 | luaL_argcheck( L, linda != nullptr, idx_, "expecting a linda object"); | 148 | if (!OPT) |
| 149 | { | ||
| 150 | luaL_argcheck(L, linda != nullptr, idx_, "expecting a linda object"); | ||
| 151 | } | ||
| 152 | ASSERT_L(linda->U == universe_get(L)); | ||
| 67 | return linda; | 153 | return linda; |
| 68 | } | 154 | } |
| 69 | 155 | ||
| 70 | static void check_key_types( lua_State* L, int start_, int end_) | 156 | // ################################################################################################# |
| 157 | |||
| 158 | static void check_key_types(lua_State* L, int start_, int end_) | ||
| 71 | { | 159 | { |
| 72 | int i; | 160 | int i; |
| 73 | for( i = start_; i <= end_; ++ i) | 161 | for( i = start_; i <= end_; ++ i) |
| @@ -81,13 +169,14 @@ static void check_key_types( lua_State* L, int start_, int end_) | |||
| 81 | } | 169 | } |
| 82 | } | 170 | } |
| 83 | 171 | ||
| 84 | LUAG_FUNC( linda_protected_call) | 172 | // ################################################################################################# |
| 173 | |||
| 174 | LUAG_FUNC(linda_protected_call) | ||
| 85 | { | 175 | { |
| 86 | int rc = LUA_OK; | 176 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 87 | struct s_Linda* linda = lua_toLinda( L, 1); | ||
| 88 | 177 | ||
| 89 | // acquire the keeper | 178 | // acquire the keeper |
| 90 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)); | 179 | Keeper* K = keeper_acquire( linda->U->keepers, linda->hashSeed()); |
| 91 | lua_State* KL = K ? K->L : nullptr; | 180 | lua_State* KL = K ? K->L : nullptr; |
| 92 | if( KL == nullptr) return 0; | 181 | if( KL == nullptr) return 0; |
| 93 | 182 | ||
| @@ -95,7 +184,7 @@ LUAG_FUNC( linda_protected_call) | |||
| 95 | lua_pushvalue( L, lua_upvalueindex( 1)); | 184 | lua_pushvalue( L, lua_upvalueindex( 1)); |
| 96 | lua_insert( L, 1); | 185 | lua_insert( L, 1); |
| 97 | // do a protected call | 186 | // do a protected call |
| 98 | rc = lua_pcall( L, lua_gettop( L) - 1, LUA_MULTRET, 0); | 187 | int const rc{ lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) }; |
| 99 | 188 | ||
| 100 | // release the keeper | 189 | // release the keeper |
| 101 | keeper_release( K); | 190 | keeper_release( K); |
| @@ -109,6 +198,8 @@ LUAG_FUNC( linda_protected_call) | |||
| 109 | return lua_gettop( L); | 198 | return lua_gettop( L); |
| 110 | } | 199 | } |
| 111 | 200 | ||
| 201 | // ################################################################################################# | ||
| 202 | |||
| 112 | /* | 203 | /* |
| 113 | * bool= linda_send( linda_ud, [timeout_secs=-1,] [linda.null,] key_num|str|bool|lightuserdata, ... ) | 204 | * bool= linda_send( linda_ud, [timeout_secs=-1,] [linda.null,] key_num|str|bool|lightuserdata, ... ) |
| 114 | * | 205 | * |
| @@ -120,7 +211,7 @@ LUAG_FUNC( linda_protected_call) | |||
| 120 | */ | 211 | */ |
| 121 | LUAG_FUNC( linda_send) | 212 | LUAG_FUNC( linda_send) |
| 122 | { | 213 | { |
| 123 | struct s_Linda* linda = lua_toLinda( L, 1); | 214 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 124 | bool ret{ false }; | 215 | bool ret{ false }; |
| 125 | CancelRequest cancel{ CancelRequest::None }; | 216 | CancelRequest cancel{ CancelRequest::None }; |
| 126 | int pushed; | 217 | int pushed; |
| @@ -167,8 +258,8 @@ LUAG_FUNC( linda_send) | |||
| 167 | keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); | 258 | keeper_toggle_nil_sentinels( L, key_i + 1, eLM_ToKeeper); |
| 168 | 259 | ||
| 169 | { | 260 | { |
| 170 | Lane* const s = get_lane_from_registry( L); | 261 | Lane* const s{ get_lane_from_registry(L) }; |
| 171 | Keeper* const K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 262 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 172 | lua_State* KL = K ? K->L : nullptr; | 263 | lua_State* KL = K ? K->L : nullptr; |
| 173 | if( KL == nullptr) return 0; | 264 | if( KL == nullptr) return 0; |
| 174 | STACK_CHECK_START_REL(KL, 0); | 265 | STACK_CHECK_START_REL(KL, 0); |
| @@ -256,6 +347,7 @@ LUAG_FUNC( linda_send) | |||
| 256 | } | 347 | } |
| 257 | } | 348 | } |
| 258 | 349 | ||
| 350 | // ################################################################################################# | ||
| 259 | 351 | ||
| 260 | /* | 352 | /* |
| 261 | * 2 modes of operation | 353 | * 2 modes of operation |
| @@ -271,7 +363,7 @@ LUAG_FUNC( linda_send) | |||
| 271 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" | 363 | #define BATCH_SENTINEL "270e6c9d-280f-4983-8fee-a7ecdda01475" |
| 272 | LUAG_FUNC( linda_receive) | 364 | LUAG_FUNC( linda_receive) |
| 273 | { | 365 | { |
| 274 | struct s_Linda* linda = lua_toLinda( L, 1); | 366 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 275 | int pushed, expected_pushed_min, expected_pushed_max; | 367 | int pushed, expected_pushed_min, expected_pushed_max; |
| 276 | CancelRequest cancel{ CancelRequest::None }; | 368 | CancelRequest cancel{ CancelRequest::None }; |
| 277 | keeper_api_t keeper_receive; | 369 | keeper_api_t keeper_receive; |
| @@ -326,8 +418,8 @@ LUAG_FUNC( linda_receive) | |||
| 326 | } | 418 | } |
| 327 | 419 | ||
| 328 | { | 420 | { |
| 329 | Lane* const s = get_lane_from_registry( L); | 421 | Lane* const s{ get_lane_from_registry(L) }; |
| 330 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 422 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 331 | if( K == nullptr) return 0; | 423 | if( K == nullptr) return 0; |
| 332 | for (bool try_again{ true };;) | 424 | for (bool try_again{ true };;) |
| 333 | { | 425 | { |
| @@ -409,6 +501,7 @@ LUAG_FUNC( linda_receive) | |||
| 409 | } | 501 | } |
| 410 | } | 502 | } |
| 411 | 503 | ||
| 504 | // ################################################################################################# | ||
| 412 | 505 | ||
| 413 | /* | 506 | /* |
| 414 | * [true|lanes.cancel_error] = linda_set( linda_ud, key_num|str|bool|lightuserdata [, value [, ...]]) | 507 | * [true|lanes.cancel_error] = linda_set( linda_ud, key_num|str|bool|lightuserdata [, value [, ...]]) |
| @@ -420,7 +513,7 @@ LUAG_FUNC( linda_receive) | |||
| 420 | */ | 513 | */ |
| 421 | LUAG_FUNC( linda_set) | 514 | LUAG_FUNC( linda_set) |
| 422 | { | 515 | { |
| 423 | struct s_Linda* const linda = lua_toLinda( L, 1); | 516 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 424 | int pushed; | 517 | int pushed; |
| 425 | bool const has_value{ lua_gettop(L) > 2 }; | 518 | bool const has_value{ lua_gettop(L) > 2 }; |
| 426 | 519 | ||
| @@ -428,7 +521,7 @@ LUAG_FUNC( linda_set) | |||
| 428 | check_key_types( L, 2, 2); | 521 | check_key_types( L, 2, 2); |
| 429 | 522 | ||
| 430 | { | 523 | { |
| 431 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 524 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 432 | 525 | ||
| 433 | if (linda->simulate_cancel == CancelRequest::None) | 526 | if (linda->simulate_cancel == CancelRequest::None) |
| 434 | { | 527 | { |
| @@ -467,6 +560,7 @@ LUAG_FUNC( linda_set) | |||
| 467 | return (pushed < 0) ? luaL_error( L, "tried to copy unsupported types") : pushed; | 560 | return (pushed < 0) ? luaL_error( L, "tried to copy unsupported types") : pushed; |
| 468 | } | 561 | } |
| 469 | 562 | ||
| 563 | // ################################################################################################# | ||
| 470 | 564 | ||
| 471 | /* | 565 | /* |
| 472 | * [val] = linda_count( linda_ud, [key [, ...]]) | 566 | * [val] = linda_count( linda_ud, [key [, ...]]) |
| @@ -475,14 +569,14 @@ LUAG_FUNC( linda_set) | |||
| 475 | */ | 569 | */ |
| 476 | LUAG_FUNC( linda_count) | 570 | LUAG_FUNC( linda_count) |
| 477 | { | 571 | { |
| 478 | struct s_Linda* linda = lua_toLinda( L, 1); | 572 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 479 | int pushed; | 573 | int pushed; |
| 480 | 574 | ||
| 481 | // make sure the keys are of a valid type | 575 | // make sure the keys are of a valid type |
| 482 | check_key_types( L, 2, lua_gettop( L)); | 576 | check_key_types( L, 2, lua_gettop( L)); |
| 483 | 577 | ||
| 484 | { | 578 | { |
| 485 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 579 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 486 | pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2); | 580 | pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2); |
| 487 | if( pushed < 0) | 581 | if( pushed < 0) |
| 488 | { | 582 | { |
| @@ -492,6 +586,7 @@ LUAG_FUNC( linda_count) | |||
| 492 | return pushed; | 586 | return pushed; |
| 493 | } | 587 | } |
| 494 | 588 | ||
| 589 | // ################################################################################################# | ||
| 495 | 590 | ||
| 496 | /* | 591 | /* |
| 497 | * [val [, ...]] = linda_get( linda_ud, key_num|str|bool|lightuserdata [, count = 1]) | 592 | * [val [, ...]] = linda_get( linda_ud, key_num|str|bool|lightuserdata [, count = 1]) |
| @@ -500,7 +595,7 @@ LUAG_FUNC( linda_count) | |||
| 500 | */ | 595 | */ |
| 501 | LUAG_FUNC( linda_get) | 596 | LUAG_FUNC( linda_get) |
| 502 | { | 597 | { |
| 503 | struct s_Linda* const linda = lua_toLinda( L, 1); | 598 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 504 | int pushed; | 599 | int pushed; |
| 505 | lua_Integer count = luaL_optinteger( L, 3, 1); | 600 | lua_Integer count = luaL_optinteger( L, 3, 1); |
| 506 | luaL_argcheck( L, count >= 1, 3, "count should be >= 1"); | 601 | luaL_argcheck( L, count >= 1, 3, "count should be >= 1"); |
| @@ -509,7 +604,7 @@ LUAG_FUNC( linda_get) | |||
| 509 | // make sure the key is of a valid type (throws an error if not the case) | 604 | // make sure the key is of a valid type (throws an error if not the case) |
| 510 | check_key_types( L, 2, 2); | 605 | check_key_types( L, 2, 2); |
| 511 | { | 606 | { |
| 512 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 607 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 513 | 608 | ||
| 514 | if (linda->simulate_cancel == CancelRequest::None) | 609 | if (linda->simulate_cancel == CancelRequest::None) |
| 515 | { | 610 | { |
| @@ -535,6 +630,7 @@ LUAG_FUNC( linda_get) | |||
| 535 | return pushed; | 630 | return pushed; |
| 536 | } | 631 | } |
| 537 | 632 | ||
| 633 | // ################################################################################################# | ||
| 538 | 634 | ||
| 539 | /* | 635 | /* |
| 540 | * [true] = linda_limit( linda_ud, key_num|str|bool|lightuserdata, int) | 636 | * [true] = linda_limit( linda_ud, key_num|str|bool|lightuserdata, int) |
| @@ -544,7 +640,7 @@ LUAG_FUNC( linda_get) | |||
| 544 | */ | 640 | */ |
| 545 | LUAG_FUNC( linda_limit) | 641 | LUAG_FUNC( linda_limit) |
| 546 | { | 642 | { |
| 547 | struct s_Linda* linda = lua_toLinda( L, 1); | 643 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 548 | int pushed; | 644 | int pushed; |
| 549 | 645 | ||
| 550 | // make sure we got 3 arguments: the linda, a key and a limit | 646 | // make sure we got 3 arguments: the linda, a key and a limit |
| @@ -555,7 +651,7 @@ LUAG_FUNC( linda_limit) | |||
| 555 | check_key_types( L, 2, 2); | 651 | check_key_types( L, 2, 2); |
| 556 | 652 | ||
| 557 | { | 653 | { |
| 558 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 654 | Keeper* const K{ which_keeper(linda->U->keepers, linda->hashSeed()) }; |
| 559 | 655 | ||
| 560 | if (linda->simulate_cancel == CancelRequest::None) | 656 | if (linda->simulate_cancel == CancelRequest::None) |
| 561 | { | 657 | { |
| @@ -578,6 +674,7 @@ LUAG_FUNC( linda_limit) | |||
| 578 | return pushed; | 674 | return pushed; |
| 579 | } | 675 | } |
| 580 | 676 | ||
| 677 | // ################################################################################################# | ||
| 581 | 678 | ||
| 582 | /* | 679 | /* |
| 583 | * (void) = linda_cancel( linda_ud, "read"|"write"|"both"|"none") | 680 | * (void) = linda_cancel( linda_ud, "read"|"write"|"both"|"none") |
| @@ -586,7 +683,7 @@ LUAG_FUNC( linda_limit) | |||
| 586 | */ | 683 | */ |
| 587 | LUAG_FUNC( linda_cancel) | 684 | LUAG_FUNC( linda_cancel) |
| 588 | { | 685 | { |
| 589 | struct s_Linda* linda = lua_toLinda( L, 1); | 686 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 590 | char const* who = luaL_optstring( L, 2, "both"); | 687 | char const* who = luaL_optstring( L, 2, "both"); |
| 591 | 688 | ||
| 592 | // make sure we got 3 arguments: the linda, a key and a limit | 689 | // make sure we got 3 arguments: the linda, a key and a limit |
| @@ -617,6 +714,7 @@ LUAG_FUNC( linda_cancel) | |||
| 617 | return 0; | 714 | return 0; |
| 618 | } | 715 | } |
| 619 | 716 | ||
| 717 | // ################################################################################################# | ||
| 620 | 718 | ||
| 621 | /* | 719 | /* |
| 622 | * lightuserdata= linda_deep( linda_ud ) | 720 | * lightuserdata= linda_deep( linda_ud ) |
| @@ -630,11 +728,12 @@ LUAG_FUNC( linda_cancel) | |||
| 630 | */ | 728 | */ |
| 631 | LUAG_FUNC( linda_deep) | 729 | LUAG_FUNC( linda_deep) |
| 632 | { | 730 | { |
| 633 | struct s_Linda* linda= lua_toLinda( L, 1); | 731 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 634 | lua_pushlightuserdata( L, linda); // just the address | 732 | lua_pushlightuserdata( L, linda); // just the address |
| 635 | return 1; | 733 | return 1; |
| 636 | } | 734 | } |
| 637 | 735 | ||
| 736 | // ################################################################################################# | ||
| 638 | 737 | ||
| 639 | /* | 738 | /* |
| 640 | * string = linda:__tostring( linda_ud) | 739 | * string = linda:__tostring( linda_ud) |
| @@ -644,19 +743,16 @@ LUAG_FUNC( linda_deep) | |||
| 644 | * Useful for concatenation or debugging purposes | 743 | * Useful for concatenation or debugging purposes |
| 645 | */ | 744 | */ |
| 646 | 745 | ||
| 647 | static int linda_tostring( lua_State* L, int idx_, bool opt_) | 746 | template <bool OPT> |
| 747 | static int linda_tostring(lua_State* L, int idx_) | ||
| 648 | { | 748 | { |
| 649 | struct s_Linda* linda = (struct s_Linda*) luaG_todeep( L, linda_id, idx_); | 749 | Linda* const linda{ lua_toLinda<OPT>(L, idx_) }; |
| 650 | if( !opt_) | ||
| 651 | { | ||
| 652 | luaL_argcheck( L, linda, idx_, "expecting a linda object"); | ||
| 653 | } | ||
| 654 | if( linda != nullptr) | 750 | if( linda != nullptr) |
| 655 | { | 751 | { |
| 656 | char text[128]; | 752 | char text[128]; |
| 657 | int len; | 753 | int len; |
| 658 | if( linda->name[0]) | 754 | if( linda->getName()) |
| 659 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->name); | 755 | len = sprintf( text, "Linda: %.*s", (int)sizeof(text) - 8, linda->getName()); |
| 660 | else | 756 | else |
| 661 | len = sprintf( text, "Linda: %p", linda); | 757 | len = sprintf( text, "Linda: %p", linda); |
| 662 | lua_pushlstring( L, text, len); | 758 | lua_pushlstring( L, text, len); |
| @@ -667,9 +763,10 @@ static int linda_tostring( lua_State* L, int idx_, bool opt_) | |||
| 667 | 763 | ||
| 668 | LUAG_FUNC( linda_tostring) | 764 | LUAG_FUNC( linda_tostring) |
| 669 | { | 765 | { |
| 670 | return linda_tostring( L, 1, false); | 766 | return linda_tostring<false>(L, 1); |
| 671 | } | 767 | } |
| 672 | 768 | ||
| 769 | // ################################################################################################# | ||
| 673 | 770 | ||
| 674 | /* | 771 | /* |
| 675 | * string = linda:__concat( a, b) | 772 | * string = linda:__concat( a, b) |
| @@ -682,12 +779,12 @@ LUAG_FUNC( linda_concat) | |||
| 682 | { // linda1? linda2? | 779 | { // linda1? linda2? |
| 683 | bool atLeastOneLinda{ false }; | 780 | bool atLeastOneLinda{ false }; |
| 684 | // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. | 781 | // Lua semantics enforce that one of the 2 arguments is a Linda, but not necessarily both. |
| 685 | if( linda_tostring( L, 1, true)) | 782 | if( linda_tostring<true>( L, 1)) |
| 686 | { | 783 | { |
| 687 | atLeastOneLinda = true; | 784 | atLeastOneLinda = true; |
| 688 | lua_replace( L, 1); | 785 | lua_replace( L, 1); |
| 689 | } | 786 | } |
| 690 | if( linda_tostring( L, 2, true)) | 787 | if( linda_tostring<true>( L, 2)) |
| 691 | { | 788 | { |
| 692 | atLeastOneLinda = true; | 789 | atLeastOneLinda = true; |
| 693 | lua_replace( L, 2); | 790 | lua_replace( L, 2); |
| @@ -700,15 +797,16 @@ LUAG_FUNC( linda_concat) | |||
| 700 | return 1; | 797 | return 1; |
| 701 | } | 798 | } |
| 702 | 799 | ||
| 800 | // ################################################################################################# | ||
| 801 | |||
| 703 | /* | 802 | /* |
| 704 | * table = linda:dump() | 803 | * table = linda:dump() |
| 705 | * return a table listing all pending data inside the linda | 804 | * return a table listing all pending data inside the linda |
| 706 | */ | 805 | */ |
| 707 | LUAG_FUNC( linda_dump) | 806 | LUAG_FUNC( linda_dump) |
| 708 | { | 807 | { |
| 709 | struct s_Linda* linda = lua_toLinda( L, 1); | 808 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 710 | ASSERT_L( linda->U == universe_get( L)); | 809 | return keeper_push_linda_storage(linda->U, L, linda, linda->hashSeed()); |
| 711 | return keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda)); | ||
| 712 | } | 810 | } |
| 713 | 811 | ||
| 714 | /* | 812 | /* |
| @@ -717,14 +815,12 @@ LUAG_FUNC( linda_dump) | |||
| 717 | */ | 815 | */ |
| 718 | LUAG_FUNC( linda_towatch) | 816 | LUAG_FUNC( linda_towatch) |
| 719 | { | 817 | { |
| 720 | struct s_Linda* linda = lua_toLinda( L, 1); | 818 | Linda* const linda{ lua_toLinda<false>(L, 1) }; |
| 721 | int pushed; | 819 | int pushed{ keeper_push_linda_storage(linda->U, L, linda, linda->hashSeed()) }; |
| 722 | ASSERT_L( linda->U == universe_get( L)); | 820 | if (pushed == 0) |
| 723 | pushed = keeper_push_linda_storage( linda->U, L, linda, LINDA_KEEPER_HASHSEED( linda)); | ||
| 724 | if( pushed == 0) | ||
| 725 | { | 821 | { |
| 726 | // if the linda is empty, don't return nil | 822 | // if the linda is empty, don't return nil |
| 727 | pushed = linda_tostring( L, 1, false); | 823 | pushed = linda_tostring<false>(L, 1); |
| 728 | } | 824 | } |
| 729 | return pushed; | 825 | return pushed; |
| 730 | } | 826 | } |
| @@ -791,28 +887,21 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
| 791 | * just don't use L's allocF because we don't know which state will get the honor of GCing the linda | 887 | * just don't use L's allocF because we don't know which state will get the honor of GCing the linda |
| 792 | */ | 888 | */ |
| 793 | Universe* const U{ universe_get(L) }; | 889 | Universe* const U{ universe_get(L) }; |
| 794 | struct s_Linda* s{ static_cast<struct s_Linda*>(U->internal_allocator.alloc(sizeof(struct s_Linda) + name_len)) }; // terminating 0 is already included | 890 | Linda* s{ static_cast<Linda*>(U->internal_allocator.alloc(sizeof(Linda))) }; // terminating 0 is already included |
| 795 | if (s) | 891 | if (s) |
| 796 | { | 892 | { |
| 797 | s->prelude.DeepPrelude::DeepPrelude(); | 893 | s->Linda::Linda(U, linda_group, linda_name, name_len); |
| 798 | SIGNAL_INIT( &s->read_happened); | ||
| 799 | SIGNAL_INIT( &s->write_happened); | ||
| 800 | s->U = U; | ||
| 801 | s->simulate_cancel = CancelRequest::None; | ||
| 802 | s->group = linda_group << KEEPER_MAGIC_SHIFT; | ||
| 803 | s->name[0] = 0; | ||
| 804 | memcpy( s->name, linda_name, name_len ? name_len + 1 : 0); | ||
| 805 | } | 894 | } |
| 806 | return s; | 895 | return s; |
| 807 | } | 896 | } |
| 808 | 897 | ||
| 809 | case eDO_delete: | 898 | case eDO_delete: |
| 810 | { | 899 | { |
| 811 | struct s_Linda* const linda{ lua_tolightuserdata<struct s_Linda>(L, 1) }; | 900 | Linda* const linda{ lua_tolightuserdata<Linda>(L, 1) }; |
| 812 | ASSERT_L( linda); | 901 | ASSERT_L( linda); |
| 813 | 902 | ||
| 814 | // Clean associated structures in the keeper state. | 903 | // Clean associated structures in the keeper state. |
| 815 | Keeper* const K{ keeper_acquire(linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)) }; | 904 | Keeper* const K{ keeper_acquire(linda->U->keepers, linda->hashSeed()) }; |
| 816 | if( K && K->L) // can be nullptr if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) | 905 | if( K && K->L) // can be nullptr if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup) |
| 817 | { | 906 | { |
| 818 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... | 907 | // hopefully this won't ever raise an error as we would jump to the closest pcall site while forgetting to release the keeper mutex... |
| @@ -820,11 +909,8 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
| 820 | } | 909 | } |
| 821 | keeper_release( K); | 910 | keeper_release( K); |
| 822 | 911 | ||
| 823 | // There aren't any lanes waiting on these lindas, since all proxies have been gc'ed. Right? | 912 | linda->Linda::~Linda(); |
| 824 | SIGNAL_FREE( &linda->read_happened); | 913 | linda->U->internal_allocator.free(linda, sizeof(Linda)); |
| 825 | SIGNAL_FREE( &linda->write_happened); | ||
| 826 | linda->prelude.DeepPrelude::~DeepPrelude(); | ||
| 827 | linda->U->internal_allocator.free(linda, sizeof(struct s_Linda) + strlen(linda->name)); | ||
| 828 | return nullptr; | 914 | return nullptr; |
| 829 | } | 915 | } |
| 830 | 916 | ||
