aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intercopycontext.cpp15
-rw-r--r--src/keeper.cpp20
-rw-r--r--src/keeper.h1
-rw-r--r--src/linda.cpp13
-rw-r--r--tests/basic.lua42
5 files changed, 35 insertions, 56 deletions
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index 0301382..6ebbbb0 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -28,6 +28,7 @@ THE SOFTWARE.
28 28
29#include "debugspew.h" 29#include "debugspew.h"
30#include "deep.h" 30#include "deep.h"
31#include "keeper.h"
31#include "universe.h" 32#include "universe.h"
32 33
33// ################################################################################################# 34// #################################################################################################
@@ -887,7 +888,12 @@ void InterCopyContext::inter_copy_keyvaluepair() const
887{ 888{
888 void* const _p{ lua_touserdata(L1, L1_i) }; 889 void* const _p{ lua_touserdata(L1, L1_i) };
889 DEBUGSPEW_CODE(fprintf(stderr, "%p\n", _p)); 890 DEBUGSPEW_CODE(fprintf(stderr, "%p\n", _p));
890 lua_pushlightuserdata(L2, _p); 891 // when copying a nil sentinel in a non-keeper, write a nil in the destination
892 if (mode != LookupMode::ToKeeper && kNilSentinel.equals(L1, L1_i)) {
893 lua_pushnil(L2);
894 } else {
895 lua_pushlightuserdata(L2, _p);
896 }
891 return true; 897 return true;
892} 898}
893 899
@@ -898,7 +904,12 @@ void InterCopyContext::inter_copy_keyvaluepair() const
898 if (vt == VT::KEY) { 904 if (vt == VT::KEY) {
899 return false; 905 return false;
900 } 906 }
901 lua_pushnil(L2); 907 // when copying a nil in a keeper, write a nil sentinel in the destination
908 if (mode == LookupMode::ToKeeper) {
909 kNilSentinel.pushKey(L2);
910 } else {
911 lua_pushnil(L2);
912 }
902 return true; 913 return true;
903} 914}
904 915
diff --git a/src/keeper.cpp b/src/keeper.cpp
index 9bde2d5..b0ed062 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -569,26 +569,6 @@ void Linda::releaseKeeper(Keeper* K_) const
569 569
570// ################################################################################################# 570// #################################################################################################
571 571
572void keeper_toggle_nil_sentinels(lua_State* L_, int start_, LookupMode const mode_)
573{
574 int const _n{ lua_gettop(L_) };
575 for (int _i = start_; _i <= _n; ++_i) {
576 if (mode_ == LookupMode::ToKeeper) {
577 if (lua_isnil(L_, _i)) {
578 kNilSentinel.pushKey(L_);
579 lua_replace(L_, _i);
580 }
581 } else {
582 if (kNilSentinel.equals(L_, _i)) {
583 lua_pushnil(L_);
584 lua_replace(L_, _i);
585 }
586 }
587 }
588}
589
590// #################################################################################################
591
592/* 572/*
593 * Call a function ('func_name') in the keeper state, and pass on the returned 573 * Call a function ('func_name') in the keeper state, and pass on the returned
594 * values to 'L'. 574 * values to 'L'.
diff --git a/src/keeper.h b/src/keeper.h
index 62d9ec8..a902caa 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -40,7 +40,6 @@ struct Keepers
40// xxh64 of string "kNilSentinel" generated at https://www.pelock.com/products/hash-calculator 40// xxh64 of string "kNilSentinel" generated at https://www.pelock.com/products/hash-calculator
41static constexpr UniqueKey kNilSentinel{ 0xC457D4EDDB05B5E4ull, "lanes.null" }; 41static constexpr UniqueKey kNilSentinel{ 0xC457D4EDDB05B5E4ull, "lanes.null" };
42 42
43void keeper_toggle_nil_sentinels(lua_State* L_, int start_, LookupMode const mode_);
44[[nodiscard]] int keeper_push_linda_storage(Linda& linda_, DestState L_); 43[[nodiscard]] int keeper_push_linda_storage(Linda& linda_, DestState L_);
45 44
46using keeper_api_t = lua_CFunction; 45using keeper_api_t = lua_CFunction;
diff --git a/src/linda.cpp b/src/linda.cpp
index 1916629..4bd4553 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -344,9 +344,6 @@ LUAG_FUNC(linda_get)
344 if (_linda->cancelRequest == CancelRequest::None) { 344 if (_linda->cancelRequest == CancelRequest::None) {
345 Keeper* const _K{ _linda->whichKeeper() }; 345 Keeper* const _K{ _linda->whichKeeper() };
346 _pushed = keeper_call(_K->L, KEEPER_API(get), L_, _linda, 2); 346 _pushed = keeper_call(_K->L, KEEPER_API(get), L_, _linda, 2);
347 if (_pushed.value_or(0) > 0) {
348 keeper_toggle_nil_sentinels(L_, lua_gettop(L_) - _pushed.value(), LookupMode::FromKeeper);
349 }
350 } else { // linda is cancelled 347 } else { // linda is cancelled
351 // do nothing and return lanes.cancel_error 348 // do nothing and return lanes.cancel_error
352 kCancelError.pushKey(L_); 349 kCancelError.pushKey(L_);
@@ -492,10 +489,6 @@ LUAG_FUNC(linda_receive)
492 } 489 }
493 if (_pushed.value() > 0) { 490 if (_pushed.value() > 0) {
494 LUA_ASSERT(L_, _pushed.value() >= _expected_pushed_min && _pushed.value() <= _expected_pushed_max); 491 LUA_ASSERT(L_, _pushed.value() >= _expected_pushed_min && _pushed.value() <= _expected_pushed_max);
495 // replace sentinels with real nils
496 keeper_toggle_nil_sentinels(L_, lua_gettop(L_) - _pushed.value(), LookupMode::FromKeeper);
497 // To be done from within the 'K' locking area
498 //
499 _linda->readHappened.notify_all(); 492 _linda->readHappened.notify_all();
500 break; 493 break;
501 } 494 }
@@ -589,8 +582,6 @@ LUAG_FUNC(linda_send)
589 raise_luaL_error(L_, "no data to send"); 582 raise_luaL_error(L_, "no data to send");
590 } 583 }
591 584
592 // convert nils to some special non-nil sentinel in sent values
593 keeper_toggle_nil_sentinels(L_, _key_i + 1, LookupMode::ToKeeper);
594 bool _ret{ false }; 585 bool _ret{ false };
595 CancelRequest _cancel{ CancelRequest::None }; 586 CancelRequest _cancel{ CancelRequest::None };
596 KeeperCallResult _pushed; 587 KeeperCallResult _pushed;
@@ -701,10 +692,6 @@ LUAG_FUNC(linda_set)
701 Keeper* const _K{ _linda->whichKeeper() }; 692 Keeper* const _K{ _linda->whichKeeper() };
702 KeeperCallResult _pushed; 693 KeeperCallResult _pushed;
703 if (_linda->cancelRequest == CancelRequest::None) { 694 if (_linda->cancelRequest == CancelRequest::None) {
704 if (_has_value) {
705 // convert nils to some special non-nil sentinel in sent values
706 keeper_toggle_nil_sentinels(L_, 3, LookupMode::ToKeeper);
707 }
708 _pushed = keeper_call(_K->L, KEEPER_API(set), L_, _linda, 2); 695 _pushed = keeper_call(_K->L, KEEPER_API(set), L_, _linda, 2);
709 if (_pushed.has_value()) { // no error? 696 if (_pushed.has_value()) { // no error?
710 LUA_ASSERT(L_, _pushed.value() == 0 || _pushed.value() == 1); 697 LUA_ASSERT(L_, _pushed.value() == 0 || _pushed.value() == 1);
diff --git a/tests/basic.lua b/tests/basic.lua
index d65728e..5a905e7 100644
--- a/tests/basic.lua
+++ b/tests/basic.lua
@@ -214,26 +214,27 @@ local chunk= function(linda)
214 local function receive() return linda:receive("->") end 214 local function receive() return linda:receive("->") end
215 local function send(...) linda:send("<-", ...) end 215 local function send(...) linda:send("<-", ...) end
216 216
217 WR("Lane starts!\n") 217 WR("chunk ", "Lane starts!\n")
218 218
219 local k,v 219 local k,v
220 k,v=receive(); WR(v.." received\n"); assert(v==1) 220 k,v=receive(); WR("chunk ", v.." received (expecting 1)\n"); assert(v==1)
221 k,v=receive(); WR(v.." received\n"); assert(v==2) 221 k,v=receive(); WR("chunk ", v.." received (expecting 2)\n"); assert(v==2)
222 k,v=receive(); WR(v.." received\n"); assert(v==3) 222 k,v=receive(); WR("chunk ", v.." received (expecting 3)\n"); assert(v==3)
223 k,v=receive(); WR(tostring(v).." received\n"); assert(v==nil) 223 k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil from __lanesignore)\n"); assert(v==nil) -- a table with __lanesignore was sent
224 k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil)\n"); assert(v==nil)
224 225
225 send(1,2,3); WR("1,2,3 sent\n") 226 send(4,5,6); WR("chunk ", "4,5,6 sent\n")
226 send 'a'; WR("'a' sent\n") 227 send 'aaa'; WR("chunk ", "'aaa' sent\n")
227 send(nil); WR("nil sent\n") 228 send(nil); WR("chunk ", "nil sent\n")
228 send { 'a', 'b', 'c', d=10 }; WR("{'a','b','c',d=10} sent\n") 229 send { 'a', 'b', 'c', d=10 }; WR("chunk ","{'a','b','c',d=10} sent\n")
229 230
230 k,v=receive(); WR(v.." received\n"); assert(v==4) 231 k,v=receive(); WR("chunk ", v.." received\n"); assert(v==4)
231 232
232 local subT1 = { "subT1"} 233 local subT1 = { "subT1"}
233 local subT2 = { "subT2"} 234 local subT2 = { "subT2"}
234 send { subT1, subT2, subT1, subT2}; WR("{ subT1, subT2, subT1, subT2} sent\n") 235 send { subT1, subT2, subT1, subT2}; WR("chunk ", "{ subT1, subT2, subT1, subT2} sent\n")
235 236
236 WR("Lane ends!\n") 237 WR("chunk ", "Lane ends!\n")
237end 238end
238 239
239local linda = lanes_linda("communications") 240local linda = lanes_linda("communications")
@@ -248,15 +249,16 @@ local function RECEIVE() local k,v = linda:receive(1, "<-") return v end
248 249
249local comms_lane = lanes_gen("io", {gc_cb = gc_cb, name = "auto"}, chunk)(linda) -- prepare & launch 250local comms_lane = lanes_gen("io", {gc_cb = gc_cb, name = "auto"}, chunk)(linda) -- prepare & launch
250 251
251SEND(1); WR("1 sent\n") 252SEND(1); WR("main ", "1 sent\n")
252SEND(2); WR("2 sent\n") 253SEND(2); WR("main ", "2 sent\n")
253SEND(3); WR("3 sent\n") 254SEND(3); WR("main ", "3 sent\n")
255SEND(setmetatable({"should be ignored"},{__lanesignore=true})); WR("main ", "__lanesignore table sent\n")
254for i=1,100 do 256for i=1,100 do
255 WR "." 257 WR "."
256 lanes.sleep(0.0001) 258 lanes.sleep(0.0001)
257 assert(PEEK() == nil) -- nothing coming in, yet 259 assert(PEEK() == nil) -- nothing coming in, yet
258end 260end
259SEND(nil); WR("\nnil sent\n") 261SEND(nil); WR("\nmain ", "nil sent\n")
260 262
261local a,b,c = RECEIVE(), RECEIVE(), RECEIVE() 263local a,b,c = RECEIVE(), RECEIVE(), RECEIVE()
262 264
@@ -264,13 +266,13 @@ print("lane status: " .. comms_lane.status)
264if comms_lane.status == "error" then 266if comms_lane.status == "error" then
265 print(comms_lane:join()) 267 print(comms_lane:join())
266else 268else
267 WR(a..", "..b..", "..c.." received\n") 269 WR("main ", tostring(a)..", "..tostring(b)..", "..tostring(c).." received\n")
268end 270end
269 271
270assert(a==1 and b==2 and c==3) 272assert(a==4 and b==5 and c==6)
271 273
272local a = RECEIVE(); WR(a.." received\n") 274local aaa = RECEIVE(); WR("main ", aaa.." received\n")
273assert(a=='a') 275assert(aaa=='aaa')
274 276
275local null = RECEIVE(); WR(tostring(null).." received\n") 277local null = RECEIVE(); WR(tostring(null).." received\n")
276assert(null==nil) 278assert(null==nil)