diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 16:21:31 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 16:21:31 +0200 |
| commit | 3f5c16116a3a7740ac4ac62b663661d772543c2e (patch) | |
| tree | 884df73600bd680929f7ad0ebdfadd087b4841e4 | |
| parent | 3763be94cdd1a5cf26fec0f09784b18188fd3054 (diff) | |
| download | lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.gz lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.bz2 lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.zip | |
Replaced __lanesignore with __lanesconvert
| -rw-r--r-- | docs/index.html | 91 | ||||
| -rw-r--r-- | src/intercopycontext.cpp | 87 | ||||
| -rw-r--r-- | src/intercopycontext.h | 3 | ||||
| -rw-r--r-- | tests/basic.lua | 4 |
4 files changed, 121 insertions, 64 deletions
diff --git a/docs/index.html b/docs/index.html index 60f4970..24c7c52 100644 --- a/docs/index.html +++ b/docs/index.html | |||
| @@ -546,7 +546,7 @@ | |||
| 546 | </td> | 546 | </td> |
| 547 | <td /> | 547 | <td /> |
| 548 | <td> | 548 | <td> |
| 549 | root level names, <tt>print</tt>, <tt>assert</tt>, <tt>unpack</tt> etc. | 549 | <tt>_G</tt> namespace (the default function environment): <tt>print</tt>, <tt>assert</tt>, <tt>dofile</tt>, etc. |
| 550 | </td> | 550 | </td> |
| 551 | </tr> | 551 | </tr> |
| 552 | <tr> | 552 | <tr> |
| @@ -1150,13 +1150,13 @@ | |||
| 1150 | <h2 id="lindas">Lindas</h2> | 1150 | <h2 id="lindas">Lindas</h2> |
| 1151 | 1151 | ||
| 1152 | <p> | 1152 | <p> |
| 1153 | Communications between lanes is completely detached from the lane handles themselves. By itself, a lane can only provide return values once it's finished, or throw an error. | 1153 | Communications between lanes is completely detached from the lane handles themselves. By itself, a lane can only provide return values once it is finished, or throw an error. |
| 1154 | Needs to communicate during runtime are handled by <a href="http://en.wikipedia.org/wiki/Linda_%28coordination_language%29" target="_blank">Linda objects</a>, which are | 1154 | Needs to communicate during runtime are handled by <a href="http://en.wikipedia.org/wiki/Linda_%28coordination_language%29" target="_blank">Linda objects</a>, which are |
| 1155 | <a href="#deep_userdata">deep userdata</a> instances. They can be provided to a lane as startup parameters, upvalues or in some other Linda's message. | 1155 | <a href="#deep_userdata">deep userdata</a> instances. They can be provided to a lane as startup parameters, upvalues or in some other Linda's message. |
| 1156 | </p> | 1156 | </p> |
| 1157 | 1157 | ||
| 1158 | <p> | 1158 | <p> |
| 1159 | Access to a Linda object means a lane can read or write to any of its data slots. Multiple lanes can be accessing the same Linda in parallel. No application level locking is required; each Linda operation is atomic. | 1159 | Access to a Linda object means a lane can read or write to any of its data slots. Multiple lanes can be accessing the same Linda simultaneously. Seen from Lua, no application level locking is required; each Linda operation is atomic. |
| 1160 | </p> | 1160 | </p> |
| 1161 | 1161 | ||
| 1162 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1162 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
| @@ -1212,35 +1212,53 @@ | |||
| 1212 | 1212 | ||
| 1213 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1213 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
| 1214 | h = lanes.linda([opt_name, [opt_group]]) | 1214 | h = lanes.linda([opt_name, [opt_group]]) |
| 1215 | </pre></td></tr></table> | ||
| 1215 | 1216 | ||
| 1216 | true|lanes.cancel_error = h:send([timeout_secs,] key, ...) | 1217 | <p> |
| 1218 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br/> | ||
| 1219 | If <tt>opt_name</tt> is omitted, it will evaluate to an hexadecimal number uniquely representing that Linda when the Linda is converted to a string. The value is the same as returned by <tt>linda:deep()</tt>.<br/> | ||
| 1220 | If <tt>opt_name</tt> is <tt>"auto"</tt>, Lanes will try to construct a name from the source location that called <tt>lanes.linda()</tt>. If that fails, the Linda name will be <tt>"<unresolved>"</tt>. | ||
| 1221 | </p> | ||
| 1217 | 1222 | ||
| 1218 | key, val = h:receive([timeout_secs,] key [, key...]) | 1223 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
| 1224 | true|lanes.cancel_error = h:limit(key, n_uint) | ||
| 1225 | </pre></td></tr></table> | ||
| 1219 | 1226 | ||
| 1220 | key, val [, val...] = h:receive(timeout, h.batched, key, n_uint_min[, n_uint_max]) | 1227 | <p> |
| 1228 | By default, queue sizes are unlimited but limits can be enforced using the <tt>limit()</tt> method. This can be useful to balance execution speeds in a producer/consumer scenario. <tt>nil</tt> removes the limit.<br/> | ||
| 1229 | A limit of 0 is allowed to block everything.<br/> | ||
| 1230 | If the key was full but the limit change added some room, <tt>limit()</tt> returns <tt>true</tt> and the Linda is signalled so that <tt>send()</tt>-blocked threads are awakened.<br/> | ||
| 1231 | </p> | ||
| 1221 | 1232 | ||
| 1222 | true|lanes.cancel_error = h:limit(key, n_uint) | 1233 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
| 1234 | true|lanes.cancel_error = h:send([timeout_secs,] key, ...) | ||
| 1223 | </pre></td></tr></table> | 1235 | </pre></td></tr></table> |
| 1224 | 1236 | ||
| 1225 | <p> | 1237 | <p> |
| 1226 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br/> | 1238 | Timeouts are given in seconds (>= 0, millisecond accuracy) or <tt>nil</tt>. Timeout can be omitted only if the first key is not a number (then it is equivalent to an infinite duration).<br/> |
| 1227 | If <tt>opt_name</tt> is omitted, it will evaluate to an hexadecimal number uniquely representing that Linda when the Linda is converted to a string. The value is the same as returned by <tt>linda:deep()</tt>.<br/> | 1239 | Each key acts as a FIFO queue. There is no limit to the number of keys a Linda may contain. Different Lindas can have identical keys, which are totally unrelated. |
| 1228 | If <tt>opt_name</tt> is <tt>"auto"</tt>, Lanes will try to construct a name from the source location that called <tt>lanes.linda()</tt>. If that fails, the Linda name will be <tt>"<unresolved>"</tt>. | ||
| 1229 | </p> | 1240 | </p> |
| 1230 | <p> | 1241 | <p> |
| 1231 | Timeouts are given in seconds (>= 0, millisecond accuracy) or <tt>nil</tt>. Timeout can be omitted only if the first key is not a number (then it's equivalent to an infinite duration). | 1242 | If no data is provided after the key, <tt>send()</tt> raises an error.<br/> |
| 1243 | Also, if <tt>linda.null</tt> or <tt>lanes.null</tt> is sent as data in a Linda, it will be read as a <tt>nil</tt>.<br/> | ||
| 1244 | <tt>send()</tt> returns <tt>true</tt> if the sending succeeded, and <tt>false</tt> if the queue limit was met, and the queue did not empty enough during the given timeout.<br/> | ||
| 1245 | <tt>send()</tt> returns <tt>lanes.cancel_error</tt> if interrupted by a soft cancel request.<br/> | ||
| 1232 | </p> | 1246 | </p> |
| 1233 | 1247 | ||
| 1248 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | ||
| 1249 | key, val = h:receive([timeout_secs,] key [, key...]) | ||
| 1250 | |||
| 1251 | key, val [, val...] = h:receive(timeout, h.batched, key, n_uint_min[, n_uint_max]) | ||
| 1252 | </pre></td></tr></table> | ||
| 1253 | |||
| 1254 | |||
| 1234 | <p> | 1255 | <p> |
| 1235 | The <tt>send()</tt> and <tt>receive()</tt> methods use Linda keys as FIFO stacks (first in, first out).<br/> | 1256 | The <tt>send()</tt> and <tt>receive()</tt> methods use Linda keys as FIFO stacks (first in, first out).<br/> |
| 1236 | By default, stack sizes are unlimited but limits can be enforced using the <tt>limit()</tt> method. This can be useful to balance execution speeds in a producer/consumer scenario. <tt>nil</tt> removes the limit.<br/> | ||
| 1237 | A limit of 0 is allowed to block everything.<br/> | ||
| 1238 | If the key was full but the limit change added some room, <tt>limit()</tt> returns <tt>true</tt> and the Linda is signalled so that <tt>send()</tt>-blocked threads are awakened.<br/> | ||
| 1239 | In batched mode, <tt>linda:receive()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. | 1257 | In batched mode, <tt>linda:receive()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. |
| 1240 | </p> | 1258 | </p> |
| 1241 | 1259 | ||
| 1242 | <p> | 1260 | <p> |
| 1243 | Note that any number of lanes can be reading or writing a Linda. There can be many producers, and many consumers. It's up to you. | 1261 | Note that any number of lanes can be reading or writing a Linda. There can be many producers, and many consumers. It is up to you. |
| 1244 | </p> | 1262 | </p> |
| 1245 | 1263 | ||
| 1246 | <p> | 1264 | <p> |
| @@ -1248,16 +1266,6 @@ | |||
| 1248 | </p> | 1266 | </p> |
| 1249 | 1267 | ||
| 1250 | <p> | 1268 | <p> |
| 1251 | <tt>send()</tt> returns <tt>true</tt> if the sending succeeded, and <tt>false</tt> if the queue limit was met, and the queue did not empty enough during the given timeout. | ||
| 1252 | <br/> | ||
| 1253 | <tt>send()</tt> returns <tt>lanes.cancel_error</tt> if interrupted by a soft cancel request. | ||
| 1254 | <br/> | ||
| 1255 | If no data is provided after the key, <tt>send()</tt> raises an error. | ||
| 1256 | <br/> | ||
| 1257 | Also, if <tt>linda.null</tt> or <tt>lanes.null</tt> is sent as data in a Linda, it will be read as a <tt>nil</tt>. | ||
| 1258 | </p> | ||
| 1259 | |||
| 1260 | <p> | ||
| 1261 | Equally, <tt>receive()</tt> returns a key and the value extracted from it. Note that <tt>nil</tt>s can be sent and received; the <tt>key</tt> value will tell it apart from a timeout.<br/> | 1269 | Equally, <tt>receive()</tt> returns a key and the value extracted from it. Note that <tt>nil</tt>s can be sent and received; the <tt>key</tt> value will tell it apart from a timeout.<br/> |
| 1262 | <tt>receive()</tt> returns <tt>nil, lanes.cancel_error</tt> if interrupted by a hard cancel request.<br/> | 1270 | <tt>receive()</tt> returns <tt>nil, lanes.cancel_error</tt> if interrupted by a hard cancel request.<br/> |
| 1263 | <tt>receive()</tt> returns <tt>nil, "timeout"</tt> if nothing was available. | 1271 | <tt>receive()</tt> returns <tt>nil, "timeout"</tt> if nothing was available. |
| @@ -1558,14 +1566,22 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
| 1558 | 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. | 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. |
| 1559 | </li> | 1567 | </li> |
| 1560 | <li> | 1568 | <li> |
| 1561 | Full userdata can be passed only if it's prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management | 1569 | 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 |
| 1562 | <ul> | 1570 | <ul> |
| 1563 | <li>In particular, lane handles cannot be passed between lanes.</li> | 1571 | <li>In particular, lane handles cannot be passed between lanes.</li> |
| 1564 | <li>Lanes can either throw an error or attempt a <a href="#demote_full_userdata">light userdata demotion</a>.</li> | 1572 | <li>Lanes can either throw an error or attempt a <a href="#demote_full_userdata">light userdata demotion</a>.</li> |
| 1565 | </ul> | 1573 | </ul> |
| 1566 | </li> | 1574 | </li> |
| 1567 | <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> | 1575 | <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> |
| 1568 | <li>If the metatable contains <tt>__lanesignore</tt>, the object is skipped and <tt>nil</tt> is transfered instead.</li> | 1576 | <li> |
| 1577 | If the metatable contains <tt>__lanesconvert</tt>, the object is converted as follows depending on the value: | ||
| 1578 | <ul> | ||
| 1579 | <li><tt>lanes.null</tt>: The value is converted to <tt>nil</tt>.</li> | ||
| 1580 | <li><tt>"decay"</tt>: The value is converted to a light userdata obtained from <tt>lua_topointer()</tt>.</li> | ||
| 1581 | <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> | ||
| 1582 | <li>Any other value raises an error.</li> | ||
| 1583 | </ul> | ||
| 1584 | </li> | ||
| 1569 | </ul> | 1585 | </ul> |
| 1570 | </p> | 1586 | </p> |
| 1571 | 1587 | ||
| @@ -1573,26 +1589,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
| 1573 | <h3 id="function_notes">Notes about passing C functions</h3> | 1589 | <h3 id="function_notes">Notes about passing C functions</h3> |
| 1574 | 1590 | ||
| 1575 | <p> | 1591 | <p> |
| 1576 | Originally, a C function was copied from one Lua state to another as follows: | 1592 | Functions are transfered as follows (more or less): |
| 1577 | </p> | ||
| 1578 | |||
| 1579 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | ||
| 1580 | // expects a C function on top of the source Lua stack | ||
| 1581 | copy_func(lua_State *dest, lua_State* source) | ||
| 1582 | { | ||
| 1583 | // extract C function pointer from source | ||
| 1584 | lua_CFunction func = lua_tocfunction(source, -1); | ||
| 1585 | // transfer upvalues | ||
| 1586 | int nup = transfer_upvalues(dest, source); | ||
| 1587 | // dest Lua stack contains a copy of all upvalues | ||
| 1588 | lua_pushcfunction(dest, func, nup); | ||
| 1589 | } | ||
| 1590 | </pre></td></tr></table> | ||
| 1591 | |||
| 1592 | <p> | ||
| 1593 | This has the main drawback of not being LuaJIT-compatible, because some functions registered by LuaJIT are not regular C functions, but specially optimized implementations. As a result, <tt>lua_tocfunction()</tt> returns <tt>nullptr</tt> for them. | ||
| 1594 | <br/> | ||
| 1595 | Therefore, Lanes no longer transfers functions that way. Instead, functions are transfered as follows (more or less): | ||
| 1596 | </p> | 1593 | </p> |
| 1597 | 1594 | ||
| 1598 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1595 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index c7fcf14..a5fd400 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
| @@ -532,6 +532,76 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
| 532 | 532 | ||
| 533 | // ################################################################################################# | 533 | // ################################################################################################# |
| 534 | 534 | ||
| 535 | LuaType InterCopyContext::processConversion() const | ||
| 536 | { | ||
| 537 | static constexpr int kPODmask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); | ||
| 538 | |||
| 539 | LuaType _val_type{ luaG_type(L1, L1_i) }; | ||
| 540 | |||
| 541 | STACK_CHECK_START_REL(L1, 0); | ||
| 542 | |||
| 543 | // it's a POD: nothing to do | ||
| 544 | if (((1 << static_cast<int>(_val_type)) & kPODmask) != 0) { | ||
| 545 | return _val_type; | ||
| 546 | } | ||
| 547 | |||
| 548 | // no metatable: nothing to do | ||
| 549 | if (!lua_getmetatable(L1, L1_i)) { // L1: ... | ||
| 550 | STACK_CHECK(L1, 0); | ||
| 551 | return _val_type; | ||
| 552 | } | ||
| 553 | // we have a metatable // L1: ... mt | ||
| 554 | static constexpr std::string_view kConvertField{ "__lanesconvert" }; | ||
| 555 | LuaType const _converterType{ luaG_getfield(L1, -1, kConvertField) }; // L1: ... mt kConvertField | ||
| 556 | switch (_converterType) { | ||
| 557 | case LuaType::NIL: | ||
| 558 | // no __lanesconvert, nothing to do | ||
| 559 | lua_pop(L1, 2); // L1: ... | ||
| 560 | break; | ||
| 561 | |||
| 562 | case LuaType::LIGHTUSERDATA: | ||
| 563 | if (kNilSentinel.equals(L1, -1)) { | ||
| 564 | DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaG_typename(L1, _val_type) << " to nil" << std::endl); | ||
| 565 | lua_replace(L1, L1_i); // L1: ... mt | ||
| 566 | lua_pop(L1, 1); // L1: ... | ||
| 567 | _val_type = _converterType; | ||
| 568 | } else { | ||
| 569 | raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data()); | ||
| 570 | } | ||
| 571 | break; | ||
| 572 | |||
| 573 | case LuaType::STRING: | ||
| 574 | // kConvertField == "decay" -> replace source value with it's pointer | ||
| 575 | if (std::string_view const _mode{ luaG_tostring(L1, -1) }; _mode == "decay") { | ||
| 576 | lua_pop(L1, 1); // L1: ... mt | ||
| 577 | lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed | ||
| 578 | lua_replace(L1, L1_i); // L1: ... mt | ||
| 579 | lua_pop(L1, 1); // L1: ... | ||
| 580 | _val_type = LuaType::LIGHTUSERDATA; | ||
| 581 | } else { | ||
| 582 | raise_luaL_error(getErrL(), "Invalid %s mode '%s'", kConvertField.data(), _mode.data()); | ||
| 583 | } | ||
| 584 | break; | ||
| 585 | |||
| 586 | case LuaType::FUNCTION: | ||
| 587 | lua_pushvalue(L1, L1_i); // L1: ... mt kConvertField val | ||
| 588 | std::ignore = luaG_pushstring(L1, mode == LookupMode::ToKeeper ? "keeper" : "regular"); // L1: ... mt kConvertField val string | ||
| 589 | lua_call(L1, 2, 1); // val:kConvertField(str) -> result // L1: ... mt kConvertField converted | ||
| 590 | lua_replace(L1, L1_i); // L1: ... mt | ||
| 591 | lua_pop(L1, 1); // L1: ... mt | ||
| 592 | _val_type = luaG_type(L1, L1_i); | ||
| 593 | break; | ||
| 594 | |||
| 595 | default: | ||
| 596 | raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data()); | ||
| 597 | } | ||
| 598 | STACK_CHECK(L1, 0); | ||
| 599 | LUA_ASSERT(getErrL(), luaG_type(L1, L1_i) == _val_type); | ||
| 600 | return _val_type; | ||
| 601 | } | ||
| 602 | |||
| 603 | // ################################################################################################# | ||
| 604 | |||
| 535 | [[nodiscard]] bool InterCopyContext::push_cached_metatable() const | 605 | [[nodiscard]] bool InterCopyContext::push_cached_metatable() const |
| 536 | { | 606 | { |
| 537 | STACK_CHECK_START_REL(L1, 0); | 607 | STACK_CHECK_START_REL(L1, 0); |
| @@ -1085,21 +1155,10 @@ namespace { | |||
| 1085 | DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl); | 1155 | DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl); |
| 1086 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); | 1156 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); |
| 1087 | 1157 | ||
| 1088 | LuaType _val_type{ luaG_type(L1, L1_i) }; | 1158 | // replace the value at L1_i with the result of a conversion if required |
| 1089 | DEBUGSPEW_CODE(DebugSpew(U) << local::sLuaTypeNames[static_cast<int>(_val_type)] << " " << local::sValueTypeNames[static_cast<int>(vt)] << ": "); | 1159 | LuaType const _val_type{ processConversion() }; |
| 1090 | |||
| 1091 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } | ||
| 1092 | if (((1 << static_cast<int>(_val_type)) & kPODmask) == 0) { | ||
| 1093 | if (lua_getmetatable(L1, L1_i)) { // L1: ... mt | ||
| 1094 | LuaType const _type{ luaG_getfield(L1, -1, "__lanesignore") }; // L1: ... mt ignore? | ||
| 1095 | if (_type == LuaType::BOOLEAN && lua_toboolean(L1, -1)) { | ||
| 1096 | DEBUGSPEW_CODE(DebugSpew(U) << "__lanesignore -> LUA_TNIL" << std::endl); | ||
| 1097 | _val_type = LuaType::NIL; | ||
| 1098 | } | ||
| 1099 | lua_pop(L1, 2); // L1: ... | ||
| 1100 | } | ||
| 1101 | } | ||
| 1102 | STACK_CHECK(L1, 0); | 1160 | STACK_CHECK(L1, 0); |
| 1161 | DEBUGSPEW_CODE(DebugSpew(U) << local::sLuaTypeNames[static_cast<int>(_val_type)] << " " << local::sValueTypeNames[static_cast<int>(vt)] << ": "); | ||
| 1103 | 1162 | ||
| 1104 | // Lets push nil to L2 if the object should be ignored | 1163 | // Lets push nil to L2 if the object should be ignored |
| 1105 | bool _ret{ true }; | 1164 | bool _ret{ true }; |
diff --git a/src/intercopycontext.h b/src/intercopycontext.h index ffa825f..459551e 100644 --- a/src/intercopycontext.h +++ b/src/intercopycontext.h | |||
| @@ -38,10 +38,11 @@ class InterCopyContext | |||
| 38 | char const* name; // that one can change when we reuse the context | 38 | char const* name; // that one can change when we reuse the context |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | [[nodiscard]] std::string_view findLookupName() const; | ||
| 41 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error | 42 | // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error |
| 42 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error | 43 | // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error |
| 43 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } | 44 | lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } |
| 44 | [[nodiscard]] std::string_view findLookupName() const; | 45 | [[nodiscard]] LuaType processConversion() const; |
| 45 | 46 | ||
| 46 | // for use in copy_cached_func | 47 | // for use in copy_cached_func |
| 47 | void copy_func() const; | 48 | void copy_func() const; |
diff --git a/tests/basic.lua b/tests/basic.lua index 20865cf..28f0334 100644 --- a/tests/basic.lua +++ b/tests/basic.lua | |||
| @@ -226,7 +226,7 @@ local chunk= function(linda) | |||
| 226 | k,v=receive(); WR("chunk ", v.." received (expecting 1)\n"); assert(v==1) | 226 | k,v=receive(); WR("chunk ", v.." received (expecting 1)\n"); assert(v==1) |
| 227 | k,v=receive(); WR("chunk ", v.." received (expecting 2)\n"); assert(v==2) | 227 | k,v=receive(); WR("chunk ", v.." received (expecting 2)\n"); assert(v==2) |
| 228 | k,v=receive(); WR("chunk ", v.." received (expecting 3)\n"); assert(v==3) | 228 | k,v=receive(); WR("chunk ", v.." received (expecting 3)\n"); assert(v==3) |
| 229 | k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil from __lanesignore)\n"); assert(v==nil) -- a table with __lanesignore was sent | 229 | k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil from __lanesconvert)\n"); assert(v==nil, "table with __lanesconvert==lanes.null should be received as nil, got " .. tostring(v)) -- a table with __lanesconvert was sent |
| 230 | k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil)\n"); assert(v==nil) | 230 | k,v=receive(); WR("chunk ", tostring(v).." received (expecting nil)\n"); assert(v==nil) |
| 231 | 231 | ||
| 232 | send(4,5,6); WR("chunk ", "4,5,6 sent\n") | 232 | send(4,5,6); WR("chunk ", "4,5,6 sent\n") |
| @@ -277,7 +277,7 @@ local comms_lane = lanes_gen("io", {gc_cb = gc_cb, name = "auto"}, chunk)(linda) | |||
| 277 | SEND(1); WR("main ", "1 sent\n") | 277 | SEND(1); WR("main ", "1 sent\n") |
| 278 | SEND(2); WR("main ", "2 sent\n") | 278 | SEND(2); WR("main ", "2 sent\n") |
| 279 | SEND(3); WR("main ", "3 sent\n") | 279 | SEND(3); WR("main ", "3 sent\n") |
| 280 | SEND(setmetatable({"should be ignored"},{__lanesignore=true})); WR("main ", "__lanesignore table sent\n") | 280 | SEND(setmetatable({"should be ignored"},{__lanesconvert=lanes.null})); WR("main ", "__lanesconvert table sent\n") |
| 281 | for i=1,40 do | 281 | for i=1,40 do |
| 282 | WR "." | 282 | WR "." |
| 283 | SLEEP(0.0001) | 283 | SLEEP(0.0001) |
