diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2025-09-29 17:11:58 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2025-09-29 17:11:58 +0200 |
| commit | f011dcafb0f583c89ed9971238fd83ddcbdb5438 (patch) | |
| tree | e118ea27af987540fccb2cb1563cc8d9508b255c | |
| parent | 4e109a0c12d245b155bf03cb561c01b242666395 (diff) | |
| download | lanes-f011dcafb0f583c89ed9971238fd83ddcbdb5438.tar.gz lanes-f011dcafb0f583c89ed9971238fd83ddcbdb5438.tar.bz2 lanes-f011dcafb0f583c89ed9971238fd83ddcbdb5438.zip | |
Lift restriction on tables as table keys
As demonstrated by the unit tests, there is no problem with using a table as a table key
| -rw-r--r-- | CHANGES | 4 | ||||
| -rw-r--r-- | docs/index.html | 14 | ||||
| -rw-r--r-- | src/intercopycontext.cpp | 4 | ||||
| -rw-r--r-- | unit_tests/UnitTests.vcxproj | 1 | ||||
| -rw-r--r-- | unit_tests/UnitTests.vcxproj.filters | 3 | ||||
| -rw-r--r-- | unit_tests/linda_tests.cpp | 1 | ||||
| -rw-r--r-- | unit_tests/scripts/linda/send_receive_tables.lua | 41 |
7 files changed, 54 insertions, 14 deletions
| @@ -57,9 +57,11 @@ CHANGE 2: BGe 05-Jun-25 | |||
| 57 | - linda:wake() can wake up threads waiting for a Linda without doing any I/O on it. | 57 | - linda:wake() can wake up threads waiting for a Linda without doing any I/O on it. |
| 58 | - linda.status reads the cancel status of the Linda. | 58 | - linda.status reads the cancel status of the Linda. |
| 59 | - new function linda:collectgarbage() to force collection of all stale data in the associated keeper. | 59 | - new function linda:collectgarbage() to force collection of all stale data in the associated keeper. |
| 60 | - Deep userdata are an acceptable key to send data into (for example, another linda). | 60 | - Deep userdata are an acceptable slot to send data into (for example, another linda). |
| 61 | - Tables can be used as table keys in transferred data. | ||
| 61 | - Full userdata conversion: | 62 | - Full userdata conversion: |
| 62 | - __lanesconvert added. | 63 | - __lanesconvert added. |
| 64 | - global configuration convert_fallback and convert_max_attempts added. | ||
| 63 | - __lanesignore removed. Use __lanesconvert instead. | 65 | - __lanesignore removed. Use __lanesconvert instead. |
| 64 | 66 | ||
| 65 | CHANGE 1: BGe 9-Apr-24 | 67 | CHANGE 1: BGe 9-Apr-24 |
diff --git a/docs/index.html b/docs/index.html index eba39bb..452dcfa 100644 --- a/docs/index.html +++ b/docs/index.html | |||
| @@ -1936,13 +1936,12 @@ | |||
| 1936 | </p> | 1936 | </p> |
| 1937 | 1937 | ||
| 1938 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1938 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
| 1939 | int luaopen_module(lua_State *L ) | 1939 | int luaopen_module(lua_State* L) |
| 1940 | { | 1940 | { |
| 1941 | static char been_here; /* 0 by ANSI C */ | 1941 | static char been_here; /* 0 by ANSI C */ |
| 1942 | 1942 | ||
| 1943 | // Calls to 'require' serialized by Lanes; this is safe. | 1943 | // Calls to 'require' serialized by Lanes; this is safe. |
| 1944 | if (!been_here) | 1944 | if (!been_here) { |
| 1945 | { | ||
| 1946 | been_here= 1; | 1945 | been_here= 1; |
| 1947 | ... one time initializations ... | 1946 | ... one time initializations ... |
| 1948 | } | 1947 | } |
| @@ -1959,8 +1958,7 @@ | |||
| 1959 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1958 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
| 1960 | static int clonable_lanesclone(lua_State* L) | 1959 | static int clonable_lanesclone(lua_State* L) |
| 1961 | { | 1960 | { |
| 1962 | switch(lua_gettop(L)) | 1961 | switch(lua_gettop(L)) { |
| 1963 | { | ||
| 1964 | case 3: | 1962 | case 3: |
| 1965 | { | 1963 | { |
| 1966 | struct s_MyClonableUserdata* self = lua_touserdata(L, 1); | 1964 | struct s_MyClonableUserdata* self = lua_touserdata(L, 1); |
| @@ -1988,16 +1986,14 @@ int luaopen_deep_userdata_example(lua_State* L) | |||
| 1988 | luaL_newlib(L, deep_module); | 1986 | luaL_newlib(L, deep_module); |
| 1989 | 1987 | ||
| 1990 | // preregister the metatables for the types we can instanciate so that Lanes can know about them | 1988 | // preregister the metatables for the types we can instanciate so that Lanes can know about them |
| 1991 | if (luaL_newmetatable(L, "clonable")) | 1989 | if (luaL_newmetatable(L, "clonable")) { |
| 1992 | { | ||
| 1993 | luaL_setfuncs(L, clonable_mt, 0); | 1990 | luaL_setfuncs(L, clonable_mt, 0); |
| 1994 | lua_pushvalue(L, -1); | 1991 | lua_pushvalue(L, -1); |
| 1995 | lua_setfield(L, -2, "__index"); | 1992 | lua_setfield(L, -2, "__index"); |
| 1996 | } | 1993 | } |
| 1997 | lua_setfield(L, -2, "__clonableMT"); // actual name is not important | 1994 | lua_setfield(L, -2, "__clonableMT"); // actual name is not important |
| 1998 | 1995 | ||
| 1999 | if (luaL_newmetatable(L, "deep")) | 1996 | if (luaL_newmetatable(L, "deep")) { |
| 2000 | { | ||
| 2001 | luaL_setfuncs(L, deep_mt, 0); | 1997 | luaL_setfuncs(L, deep_mt, 0); |
| 2002 | lua_pushvalue(L, -1); | 1998 | lua_pushvalue(L, -1); |
| 2003 | lua_setfield(L, -2, "__index"); | 1999 | lua_setfield(L, -2, "__index"); |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index a8b3374..7fb2706 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
| @@ -1106,10 +1106,6 @@ void InterCopyContext::interCopyString() const | |||
| 1106 | [[nodiscard]] | 1106 | [[nodiscard]] |
| 1107 | InterCopyOneResult InterCopyContext::interCopyTable() const | 1107 | InterCopyOneResult InterCopyContext::interCopyTable() const |
| 1108 | { | 1108 | { |
| 1109 | if (vt == VT::KEY) { | ||
| 1110 | return InterCopyOneResult::NotCopied; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | STACK_CHECK_START_REL(L1, 0); | 1109 | STACK_CHECK_START_REL(L1, 0); |
| 1114 | STACK_CHECK_START_REL(L2, 0); | 1110 | STACK_CHECK_START_REL(L2, 0); |
| 1115 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "TABLE " << name << std::endl); | 1111 | DEBUGSPEW_CODE(DebugSpew(nullptr) << "TABLE " << name << std::endl); |
diff --git a/unit_tests/UnitTests.vcxproj b/unit_tests/UnitTests.vcxproj index d5edef9..300eb9b 100644 --- a/unit_tests/UnitTests.vcxproj +++ b/unit_tests/UnitTests.vcxproj | |||
| @@ -1160,6 +1160,7 @@ | |||
| 1160 | <None Include="scripts\lane\body_is_a_c_function.lua" /> | 1160 | <None Include="scripts\lane\body_is_a_c_function.lua" /> |
| 1161 | <None Include="scripts\lane\tasking_cancelling_with_hook.lua" /> | 1161 | <None Include="scripts\lane\tasking_cancelling_with_hook.lua" /> |
| 1162 | <None Include="scripts\linda\send_receive_func_and_string.lua" /> | 1162 | <None Include="scripts\linda\send_receive_func_and_string.lua" /> |
| 1163 | <None Include="scripts\linda\send_receive_tables.lua" /> | ||
| 1163 | <None Include="scripts\linda\wake_period.lua" /> | 1164 | <None Include="scripts\linda\wake_period.lua" /> |
| 1164 | <None Include="scripts\misc\deeptest.lua" /> | 1165 | <None Include="scripts\misc\deeptest.lua" /> |
| 1165 | <None Include="scripts\_utils54.lua" /> | 1166 | <None Include="scripts\_utils54.lua" /> |
diff --git a/unit_tests/UnitTests.vcxproj.filters b/unit_tests/UnitTests.vcxproj.filters index 5d2dad8..57d8918 100644 --- a/unit_tests/UnitTests.vcxproj.filters +++ b/unit_tests/UnitTests.vcxproj.filters | |||
| @@ -156,5 +156,8 @@ | |||
| 156 | <None Include="scripts\misc\deeptest.lua"> | 156 | <None Include="scripts\misc\deeptest.lua"> |
| 157 | <Filter>Scripts\misc</Filter> | 157 | <Filter>Scripts\misc</Filter> |
| 158 | </None> | 158 | </None> |
| 159 | <None Include="scripts\linda\send_receive_tables.lua"> | ||
| 160 | <Filter>Scripts\linda</Filter> | ||
| 161 | </None> | ||
| 159 | </ItemGroup> | 162 | </ItemGroup> |
| 160 | </Project> \ No newline at end of file | 163 | </Project> \ No newline at end of file |
diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp index 90630a7..dfba393 100644 --- a/unit_tests/linda_tests.cpp +++ b/unit_tests/linda_tests.cpp | |||
| @@ -398,6 +398,7 @@ TEST_CASE("scripted_tests." #DIR "." #FILE) \ | |||
| 398 | MAKE_TEST_CASE(linda, multiple_keepers) | 398 | MAKE_TEST_CASE(linda, multiple_keepers) |
| 399 | MAKE_TEST_CASE(linda, send_receive) | 399 | MAKE_TEST_CASE(linda, send_receive) |
| 400 | MAKE_TEST_CASE(linda, send_receive_func_and_string) | 400 | MAKE_TEST_CASE(linda, send_receive_func_and_string) |
| 401 | MAKE_TEST_CASE(linda, send_receive_tables) | ||
| 401 | MAKE_TEST_CASE(linda, send_registered_userdata) | 402 | MAKE_TEST_CASE(linda, send_registered_userdata) |
| 402 | MAKE_TEST_CASE(linda, wake_period) | 403 | MAKE_TEST_CASE(linda, wake_period) |
| 403 | 404 | ||
diff --git a/unit_tests/scripts/linda/send_receive_tables.lua b/unit_tests/scripts/linda/send_receive_tables.lua new file mode 100644 index 0000000..08b1f16 --- /dev/null +++ b/unit_tests/scripts/linda/send_receive_tables.lua | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | local lanes = require "lanes" | ||
| 2 | |||
| 3 | -- a newly created linda doesn't contain anything | ||
| 4 | local l = lanes.linda() | ||
| 5 | |||
| 6 | -- send a table with subtables, both as keys and values, making sure the structure is preserved | ||
| 7 | |||
| 8 | local t1 = {["name"] = "t1"} | ||
| 9 | local t2 = {["name"] = "t2"} | ||
| 10 | |||
| 11 | local t3 = { | ||
| 12 | ["name"] = "t3", | ||
| 13 | ["t1"] = t1, | ||
| 14 | [t1] = t2, -- table t1 as key, table t2 as value | ||
| 15 | ["t2"] = t2, | ||
| 16 | [t2] = t1 -- table t2 as key, table t1 as value | ||
| 17 | } | ||
| 18 | |||
| 19 | -- add recursivity for good measure | ||
| 20 | t3["t3"] = t3 | ||
| 21 | t3[t3] = t3 | ||
| 22 | t1["t3"] = t3 | ||
| 23 | t2["t3"] = t3 | ||
| 24 | |||
| 25 | l:send("data", t3) | ||
| 26 | local k, t = l:receive("data") | ||
| 27 | assert(k == "data" and type(t) == "table" and t.name == "t3") | ||
| 28 | -- when keys are strings | ||
| 29 | assert(t["t3"] == t) | ||
| 30 | assert(type(t["t1"]) == "table") | ||
| 31 | assert(t["t1"].name == "t1") | ||
| 32 | assert(type(t["t2"]) == "table") | ||
| 33 | assert(t["t2"].name == "t2") | ||
| 34 | assert(t["t1"].t3 == t) | ||
| 35 | assert(t["t2"].t3 == t) | ||
| 36 | -- when keys are tables | ||
| 37 | assert(t[t.t1] == t.t2) | ||
| 38 | assert(t[t.t1]["t3"] == t) | ||
| 39 | assert(t[t.t2] == t.t1) | ||
| 40 | assert(t[t.t2]["t3"] == t) | ||
| 41 | assert(t[t.t3] == t.t3) | ||
