aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-10 18:16:57 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-10 18:16:57 +0200
commit7d31e295dc782afc92f3215d1571e629a5407fbf (patch)
tree2be6f774be1b41f65dd4e8c015712dacee42c21b
parentae582acdb1bfb3fb4171682b884545d174e95aa9 (diff)
downloadlanes-7d31e295dc782afc92f3215d1571e629a5407fbf.tar.gz
lanes-7d31e295dc782afc92f3215d1571e629a5407fbf.tar.bz2
lanes-7d31e295dc782afc92f3215d1571e629a5407fbf.zip
Removed .demote_full_userdata
Diffstat (limited to '')
-rw-r--r--deep_test/deep_test.cpp2
-rw-r--r--deep_test/deeptest.lua13
-rw-r--r--docs/index.html52
-rw-r--r--src/intercopycontext.cpp19
-rw-r--r--src/lanes.lua2
-rw-r--r--src/universe.cpp4
-rw-r--r--src/universe.h2
7 files changed, 29 insertions, 65 deletions
diff --git a/deep_test/deep_test.cpp b/deep_test/deep_test.cpp
index 812019a..178075d 100644
--- a/deep_test/deep_test.cpp
+++ b/deep_test/deep_test.cpp
@@ -58,7 +58,7 @@ void MyDeepFactory::deleteDeepObjectInternal(lua_State* const L_, DeepPrelude* c
58{ 58{
59 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) }; 59 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L, 1)) };
60 _self->inUse.fetch_add(1, std::memory_order_seq_cst); 60 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
61 std::ignore = luaG_pushstring(L, "%p:deep(%d)", lua_topointer(L, 1), _self->val); 61 std::ignore = luaG_pushstring(L, "%p:deep(%d)", _self, _self->val);
62 _self->inUse.fetch_sub(1, std::memory_order_seq_cst); 62 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
63 return 1; 63 return 1;
64} 64}
diff --git a/deep_test/deeptest.lua b/deep_test/deeptest.lua
index 250eb98..bab91d9 100644
--- a/deep_test/deeptest.lua
+++ b/deep_test/deeptest.lua
@@ -38,9 +38,13 @@ local printDeep = function( prefix_, obj_, t_)
38 print ("uv #" .. uvi, type( uservalue), uservalue, type(uservalue) == "function" and uservalue() or "") 38 print ("uv #" .. uvi, type( uservalue), uservalue, type(uservalue) == "function" and uservalue() or "")
39 end 39 end
40 if t_ then 40 if t_ then
41 for k, v in pairs( t_) do 41 local count = 0
42 for k, v in ipairs( t_) do
42 print( "t["..tostring(k).."]", v) 43 print( "t["..tostring(k).."]", v)
44 count = count + 1
43 end 45 end
46 -- we should have only 2 indexed entries with the same value
47 assert(count == 2 and t_[1] == t_[2])
44 end 48 end
45 print() 49 print()
46end 50end
@@ -56,8 +60,11 @@ local performTest = function( obj_)
56 60
57 local t = 61 local t =
58 { 62 {
59 ["key"] = obj_, 63 -- two indices with an identical value: we should also have identical values on the other side (even if not the same as the original ones when they are clonables)
60 [obj_] = "val" -- this one won't transfer because we don't support full uservalue as keys 64 obj_,
65 obj_,
66 -- this one won't transfer because we don't support full uservalue as keys
67 [obj_] = "val"
61 } 68 }
62 69
63 -- read back the contents of the object 70 -- read back the contents of the object
diff --git a/docs/index.html b/docs/index.html
index 5675f65..4e8cc25 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -368,19 +368,6 @@
368 </tr> 368 </tr>
369 369
370 <tr valign=top> 370 <tr valign=top>
371 <td id="demote_full_userdata">
372 <code>.demote_full_userdata</code>
373 </td>
374 <td>
375 <tt>nil</tt>/<tt>false</tt>/<tt>true</tt>
376 </td>
377 <td>
378 If equal to <tt>false</tt> or <tt>nil</tt>, Lanes raises an error when attempting to transfer a non-deep full userdata, else it will be demoted to a light userdata in the destination.
379 Default is <tt>false</tt> (set to <tt>true</tt> to get the legacy behaviour).
380 </td>
381 </tr>
382
383 <tr valign=top>
384 <td id="track_lanes"> 371 <td id="track_lanes">
385 <code>.track_lanes</code> 372 <code>.track_lanes</code>
386 </td> 373 </td>
@@ -1547,47 +1534,36 @@ On the other side, you need to use a common Linda for waiting for multiple keys.
1547 1534
1548<p> 1535<p>
1549 Data passed between lanes (either as starting parameters, return values, upvalues or via Lindas) must conform to the following: 1536 Data passed between lanes (either as starting parameters, return values, upvalues or via Lindas) must conform to the following:
1550</p>
1551
1552<p>
1553 <ul> 1537 <ul>
1538 <li>Coroutines cannot be passed. A coroutine's Lua state is tied to the Lua state that created it, and there is no way the mixed C/Lua stack of a coroutine can be transfered from one Lua state to another.</li>
1539 <li>Lane handles cannot be passed between lanes.</li>
1554 <li>Booleans, numbers, strings, light userdata, Lua functions and tables of such can always be passed.</li> 1540 <li>Booleans, numbers, strings, light userdata, Lua functions and tables of such can always be passed.</li>
1555 <li> 1541 <li>
1556 Cyclic tables and/or duplicate references are allowed and reproduced appropriately, but only <u>within the same transmission</u>. 1542 Cyclic tables and/or duplicate references are allowed and reproduced appropriately, but only <u>within the same transmission</u>.
1557 <ul> 1543 Using the same source table in multiple <a href="#lindas">Linda</a> messages keeps no ties between the tables (this is the same reason why tables can't be used as keys).
1558 <li>Using the same source table in multiple <a href="#lindas">Linda</a> messages keeps no ties between the tables (this is the same reason why tables can't be used as keys).</li>
1559 </ul>
1560 </li> 1544 </li>
1561 <li> 1545 <li>
1562 Objects (tables with a metatable) are copyable between lanes. 1546 For tables and full userdata: before anything else, the metatable is searched for a <tt>__lanesconvert</tt> field. If found, the source object is converted as follows depending on <tt>__lanesconvert</tt>'s value:
1563 <ul> 1547 <ul>
1564 <li>Metatables are assumed to be immutable; they are internally indexed and only copied once per each type of objects per lane.</li> 1548 <li><tt>lanes.null</tt>: The value is converted to <tt>nil</tt>.</li>
1549 <li><tt>"decay"</tt>: The value is converted to a light userdata obtained from <tt>lua_topointer()</tt>.</li>
1550 <li>A function: The function is called as <tt>o:__lanesconvert(string)</tt>, where the argument is either <tt>"keeper"</tt> or <tt>"regular"</tt>, depending on the type of destination. Its (single) return value is the result of the conversion.</li>
1551 <li>Any other value raises an error.</li>
1565 </ul> 1552 </ul>
1566 </li> 1553 </li>
1567 <li> 1554 <li>
1568 C functions (<tt>lua_CFunction</tt>) referring to <tt>LUA_ENVIRONINDEX</tt> or <tt>LUA_REGISTRYINDEX</tt> might not do what you expect in the target, since they will actually use a different environment. 1555 Non-converted full userdata can be passed only if it is prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management.
1569 </li> 1556 </li>
1570 <li> 1557 <li>
1571 Lua 5.2 functions may have a special <tt>_ENV</tt> upvalue if they perform 'global namespace' lookups. Unless special care is taken, this upvalue defaults to the table found at <tt>LUA_RIDX_GLOBALS</tt>. 1558 Objects (tables with a metatable) are copyable between lanes. Metatables are assumed to be immutable; they are internally indexed and only copied once per each type of objects per lane.
1572 Obviously, we don't want to transfer the whole global table along with each Lua function. Therefore, any upvalue equal to the global table is not transfered by value, but simply bound
1573 to the global table in the destination state. Note that this also applies when Lanes is built for Lua 5.1, as it doesn't hurt.
1574 </li> 1559 </li>
1575 <li> 1560 <li>
1576 Full userdata can be passed only if it is prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management 1561 C functions (<tt>lua_CFunction</tt>) referring to <tt>LUA_ENVIRONINDEX</tt> or <tt>LUA_REGISTRYINDEX</tt> might not do what you expect in the target, since they will actually use a different environment.
1577 <ul>
1578 <li>In particular, lane handles cannot be passed between lanes.</li>
1579 <li>Lanes can either throw an error or attempt a <a href="#demote_full_userdata">light userdata demotion</a>.</li>
1580 </ul>
1581 </li> 1562 </li>
1582 <li>Coroutines cannot be passed. A coroutine's Lua state is tied to the Lua state that created it, and there is no way the mixed C/Lua stack of a coroutine can be transfered from one Lua state to another.</li>
1583 <li> 1563 <li>
1584 If the metatable contains <tt>__lanesconvert</tt>, the object is converted as follows depending on the value: 1564 Lua 5.2 functions may have a special <tt>_ENV</tt> upvalue if they perform 'global namespace' lookups. Unless special care is taken, this upvalue defaults to the table found at <tt>LUA_RIDX_GLOBALS</tt>.
1585 <ul> 1565 Obviously, we don't want to transfer the whole global table along with each Lua function. Therefore, any upvalue equal to the global table is not transfered by value, but simply bound
1586 <li><tt>lanes.null</tt>: The value is converted to <tt>nil</tt>.</li> 1566 to the global table in the destination state. Note that this also applies when Lanes is built for Lua 5.1, as it doesn't hurt.
1587 <li><tt>"decay"</tt>: The value is converted to a light userdata obtained from <tt>lua_topointer()</tt>.</li>
1588 <li>A function: The function is called as <tt>o:__lanesconvert(string)</tt>, where the argument is either <tt>"keeper"</tt> or <tt>"regular"</tt>, depending on the type of destination. Its (single) return value is the result of the conversion.</li>
1589 <li>Any other value raises an error.</li>
1590 </ul>
1591 </li> 1567 </li>
1592 </ul> 1568 </ul>
1593</p> 1569</p>
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index a5fd400..5be4304 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -718,6 +718,8 @@ LuaType InterCopyContext::processConversion() const
718 return false; 718 return false;
719 } 719 }
720 720
721 DEBUGSPEW_CODE(DebugSpew(U) << "CLONABLE USERDATA" << std::endl);
722
721 // we need to copy over the uservalues of the userdata as well 723 // we need to copy over the uservalues of the userdata as well
722 { 724 {
723 int const _mt{ luaG_absindex(L1, -2) }; // L1: ... mt __lanesclone 725 int const _mt{ luaG_absindex(L1, -2) }; // L1: ... mt __lanesclone
@@ -795,6 +797,7 @@ LuaType InterCopyContext::processConversion() const
795 return false; // not a deep userdata 797 return false; // not a deep userdata
796 } 798 }
797 799
800 DEBUGSPEW_CODE(DebugSpew(U) << "DEEP USERDATA" << std::endl);
798 STACK_CHECK_START_REL(L1, 0); 801 STACK_CHECK_START_REL(L1, 0);
799 STACK_CHECK_START_REL(L2, 0); 802 STACK_CHECK_START_REL(L2, 0);
800 803
@@ -1085,27 +1088,13 @@ LuaType InterCopyContext::processConversion() const
1085 STACK_CHECK(L2, 0); 1088 STACK_CHECK(L2, 0);
1086 1089
1087 // Allow only deep userdata entities to be copied across 1090 // Allow only deep userdata entities to be copied across
1088 DEBUGSPEW_CODE(DebugSpew(nullptr) << "USERDATA" << std::endl);
1089 if (tryCopyDeep()) { 1091 if (tryCopyDeep()) {
1090 STACK_CHECK(L1, 0); 1092 STACK_CHECK(L1, 0);
1091 STACK_CHECK(L2, 1); 1093 STACK_CHECK(L2, 1);
1092 return true; 1094 return true;
1093 } 1095 }
1094 1096
1095 STACK_CHECK(L1, 0); 1097 raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes");
1096 STACK_CHECK(L2, 0);
1097
1098 // Not a deep or clonable full userdata
1099 if (U->demoteFullUserdata) { // attempt demotion to light userdata
1100 void* const _lud{ lua_touserdata(L1, L1_i) };
1101 lua_pushlightuserdata(L2, _lud);
1102 } else { // raise an error
1103 raise_luaL_error(getErrL(), "can't copy non-deep full userdata across lanes");
1104 }
1105
1106 STACK_CHECK(L2, 1);
1107 STACK_CHECK(L1, 0);
1108 return true;
1109} 1098}
1110 1099
1111// ################################################################################################# 1100// #################################################################################################
diff --git a/src/lanes.lua b/src/lanes.lua
index 92e773a..1378412 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -92,7 +92,6 @@ local default_params =
92{ 92{
93 -- LuaJIT provides a thread-unsafe allocator by default, so we need to protect it when used in parallel lanes 93 -- LuaJIT provides a thread-unsafe allocator by default, so we need to protect it when used in parallel lanes
94 allocator = isLuaJIT and "protected" or nil, 94 allocator = isLuaJIT and "protected" or nil,
95 demote_full_userdata = nil,
96 -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation 95 -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation
97 internal_allocator = isLuaJIT and "libc" or "allocator", 96 internal_allocator = isLuaJIT and "libc" or "allocator",
98 keepers_gc_threshold = -1, 97 keepers_gc_threshold = -1,
@@ -119,7 +118,6 @@ local param_checkers =
119 -- can be nil, "protected", or a function 118 -- can be nil, "protected", or a function
120 return val_ and (type(val_) == "function" or val_ == "protected") or true 119 return val_ and (type(val_) == "function" or val_ == "protected") or true
121 end, 120 end,
122 demote_full_userdata = boolean_param_checker,
123 internal_allocator = function(val_) 121 internal_allocator = function(val_)
124 -- can be "libc" or "allocator" 122 -- can be "libc" or "allocator"
125 return val_ == "libc" or val_ == "allocator" 123 return val_ == "libc" or val_ == "allocator"
diff --git a/src/universe.cpp b/src/universe.cpp
index 9ab6019..82522f1 100644
--- a/src/universe.cpp
+++ b/src/universe.cpp
@@ -107,7 +107,6 @@ Universe::Universe()
107 lua_setmetatable(L_, -2); // L_: settings universe 107 lua_setmetatable(L_, -2); // L_: settings universe
108 lua_pop(L_, 1); // L_: settings 108 lua_pop(L_, 1); // L_: settings
109 109
110 // TODO: write some tests to see what happens when we trigger errors in stripped mode
111 std::ignore = luaG_getfield(L_, 1, "strip_functions"); // L_: settings strip_functions 110 std::ignore = luaG_getfield(L_, 1, "strip_functions"); // L_: settings strip_functions
112 _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; 111 _U->stripFunctions = lua_toboolean(L_, -1) ? true : false;
113 lua_pop(L_, 1); // L_: settings 112 lua_pop(L_, 1); // L_: settings
@@ -115,9 +114,6 @@ Universe::Universe()
115 std::ignore = luaG_getfield(L_, 1, "verbose_errors"); // L_: settings verbose_errors 114 std::ignore = luaG_getfield(L_, 1, "verbose_errors"); // L_: settings verbose_errors
116 _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; 115 _U->verboseErrors = lua_toboolean(L_, -1) ? true : false;
117 lua_pop(L_, 1); // L_: settings 116 lua_pop(L_, 1); // L_: settings
118 std::ignore = luaG_getfield(L_, 1, "demote_full_userdata"); // L_: settings demote_full_userdata
119 _U->demoteFullUserdata = lua_toboolean(L_, -1) ? true : false;
120 lua_pop(L_, 1); // L_: settings
121 117
122 // tracking 118 // tracking
123 std::ignore = luaG_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes 119 std::ignore = luaG_getfield(L_, 1, "track_lanes"); // L_: settings track_lanes
diff --git a/src/universe.h b/src/universe.h
index 2b8cdf2..f0975d8 100644
--- a/src/universe.h
+++ b/src/universe.h
@@ -128,8 +128,6 @@ class Universe
128 // for verbose errors 128 // for verbose errors
129 bool verboseErrors{ false }; 129 bool verboseErrors{ false };
130 130
131 bool demoteFullUserdata{ false };
132
133 bool stripFunctions{ true }; 131 bool stripFunctions{ true };
134 132
135 // before a state is created, this function will be called to obtain the allocator 133 // before a state is created, this function will be called to obtain the allocator