aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lanes.cpp4
-rw-r--r--src/lanes_private.h2
-rw-r--r--src/linda.cpp226
-rw-r--r--tests/fifo.lua2
-rw-r--r--tests/keeper.lua9
5 files changed, 168 insertions, 75 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/
143static constexpr UniqueKey FINALIZER_REGKEY{ 0x188fccb8bf348e09ull }; 143static constexpr UniqueKey FINALIZER_REGKEY{ 0x188fccb8bf348e09ull };
144 144
145struct 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*/
49struct s_Linda 53struct 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};
61static void* linda_id( lua_State*, DeepOp); 142static void* linda_id( lua_State*, DeepOp);
62 143
63static inline struct s_Linda* lua_toLinda( lua_State* L, int idx_) 144template<bool OPT>
145static 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
70static void check_key_types( lua_State* L, int start_, int end_) 156// #################################################################################################
157
158static 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
84LUAG_FUNC( linda_protected_call) 172// #################################################################################################
173
174LUAG_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*/
121LUAG_FUNC( linda_send) 212LUAG_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"
272LUAG_FUNC( linda_receive) 364LUAG_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*/
421LUAG_FUNC( linda_set) 514LUAG_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 */
476LUAG_FUNC( linda_count) 570LUAG_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*/
501LUAG_FUNC( linda_get) 596LUAG_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*/
545LUAG_FUNC( linda_limit) 641LUAG_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*/
587LUAG_FUNC( linda_cancel) 684LUAG_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*/
631LUAG_FUNC( linda_deep) 729LUAG_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
647static int linda_tostring( lua_State* L, int idx_, bool opt_) 746template <bool OPT>
747static 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
668LUAG_FUNC( linda_tostring) 764LUAG_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 */
707LUAG_FUNC( linda_dump) 806LUAG_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 */
718LUAG_FUNC( linda_towatch) 816LUAG_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
diff --git a/tests/fifo.lua b/tests/fifo.lua
index 3d6e140..498f540 100644
--- a/tests/fifo.lua
+++ b/tests/fifo.lua
@@ -52,7 +52,7 @@ for key,count in pairs(fifo_linda:count(A.channel, B.channel)) do
52 print("channel " .. key .. " contains " .. count .. " entries.") 52 print("channel " .. key .. " contains " .. count .. " entries.")
53 -- print(i, key_count[1], key_count[2]) 53 -- print(i, key_count[1], key_count[2])
54end 54end
55print "Dumping linda stats.. [3]" -- count everything 55print "Dumping linda stats.. [4]" -- count everything
56for key,contents in pairs(fifo_linda:dump()) do 56for key,contents in pairs(fifo_linda:dump()) do
57 print("channel " .. key .. ": limit=".. contents.limit, " first=" .. contents.first, " count=" .. contents.count) 57 print("channel " .. key .. ": limit=".. contents.limit, " first=" .. contents.first, " count=" .. contents.count)
58 for k,v in pairs(contents.fifo) do 58 for k,v in pairs(contents.fifo) do
diff --git a/tests/keeper.lua b/tests/keeper.lua
index 11bbe17..9b38f02 100644
--- a/tests/keeper.lua
+++ b/tests/keeper.lua
@@ -6,6 +6,14 @@
6 6
7local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 200} 7local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 200}
8 8
9do
10 print "Linda names test:"
11 local unnamedLinda = lanes.linda()
12 local unnamedLinda2 = lanes.linda("")
13 local veeeerrrryyyylooongNamedLinda= lanes.linda( "veeeerrrryyyylooongNamedLinda", 1)
14 print(unnamedLinda, unnamedLinda2, veeeerrrryyyylooongNamedLinda)
15end
16
9local print_id = 0 17local print_id = 0
10local PRINT = function(...) 18local PRINT = function(...)
11 print_id = print_id + 1 19 print_id = print_id + 1
@@ -33,6 +41,7 @@ local B= keeper( lindaB )
33 41
34local lindaC= lanes.linda( "C", 3) 42local lindaC= lanes.linda( "C", 3)
35local C= keeper( lindaC ) 43local C= keeper( lindaC )
44print("Created", lindaA, lindaB, lindaC)
36 45
37A.some= 1 46A.some= 1
38PRINT("A.some == " .. A.some ) 47PRINT("A.some == " .. A.some )