aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-12-02 11:53:09 +0100
committerBenoit Germain <benoit.germain@ubisoft.com>2024-12-02 11:53:09 +0100
commitca7657e24549acb8a2dd45fa81c309b5bf9f61ee (patch)
tree0124afa9a67d5f9d64fdbad4724bc715b7b502fb /docs
parent0728e80bc2d3f5609f19b76f2bcf10412ce029b4 (diff)
downloadlanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.gz
lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.tar.bz2
lanes-ca7657e24549acb8a2dd45fa81c309b5bf9f61ee.zip
Data transfer supports registered non-deep full userdata
Diffstat (limited to 'docs')
-rw-r--r--docs/index.html58
1 files changed, 30 insertions, 28 deletions
diff --git a/docs/index.html b/docs/index.html
index 9ac36b6..7432c53 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -436,11 +436,11 @@
436</p> 436</p>
437 437
438<p> 438<p>
439 Once Lanes is configured, one should register with Lanes the modules exporting functions that will be transferred either during lane generation or through <a href="#lindas">lindas</a>. 439 Once Lanes is configured, one should register with Lanes the modules exporting functions/userdata that will be transferred either during lane generation or through <a href="#lindas">lindas</a>.
440 <br /> 440 <br />
441 Use <tt>lanes.require()</tt> for this purpose. This will call the original <tt>require()</tt>, then add the result to the lookup databases. 441 Use <tt>lanes.require()</tt> for this purpose. This will call the original <tt>require()</tt>, then add the result to the lookup databases.
442 <br /> 442 <br />
443 It is also possible to register a given module <i>a posteriori</i> with <tt>lanes.register()</tt>. This function will raise an error if the registered module is not a function or table.<br /> 443 It is also possible to register a given module <i>a posteriori</i> with <tt>lanes.register()</tt>. This function will raise an error if the registered module is not a function, table, or full userdata.<br />
444 Embedders can call the equivalent function <tt>lanes_register()</tt> from the C side, through <tt>lua_call()</tt> or similar. 444 Embedders can call the equivalent function <tt>lanes_register()</tt> from the C side, through <tt>lua_call()</tt> or similar.
445</p> 445</p>
446 446
@@ -715,7 +715,7 @@
715 </td> 715 </td>
716 <td>table</td> 716 <td>table</td>
717 <td> 717 <td>
718 Lists modules that have to be required in order to be able to transfer functions they exposed. Non-Lua functions are <a href="#function_notes">searched in lookup tables</a>. 718 Lists modules that have to be required in order to be able to transfer functions/userdata they exposed. Non-Lua functions are <a href="#function_notes">searched in lookup tables</a>.
719 These tables are built from the modules listed here. <tt>required</tt> must be an array of strings, each one being the name of a module to be required. Each module is required with <tt>require()</tt> before the lanes function is invoked. 719 These tables are built from the modules listed here. <tt>required</tt> must be an array of strings, each one being the name of a module to be required. Each module is required with <tt>require()</tt> before the lanes function is invoked.
720 So, from the required module's point of view, requiring it manually from inside the lane body or having it required this way doesn't change anything. From the lane body's point of view, the only difference is that a module not creating a global won't be accessible. 720 So, from the required module's point of view, requiring it manually from inside the lane body or having it required this way doesn't change anything. From the lane body's point of view, the only difference is that a module not creating a global won't be accessible.
721 Therefore, a lane body will also have to require a module manually, but this won't do anything more (see Lua's <tt>require</tt> documentation). <br /> 721 Therefore, a lane body will also have to require a module manually, but this won't do anything more (see Lua's <tt>require</tt> documentation). <br />
@@ -785,8 +785,8 @@
785</p> 785</p>
786 786
787<p> 787<p>
788 If a lane body pulls a C function imported by a module required before Lanes itself (thus not through a hooked <tt>require()</tt>), the lane generator creation will raise an error. 788 If a lane body pulls a C function or userdata exposed by a module required before Lanes itself (thus not through a hooked <tt>require()</tt>), the lane generator creation will raise an error.
789 The function name it shows is a path where it was found by scanning <tt>_G</tt> and the registry. As a utility, the name guessing functionality is exposed as such: 789 The name in the message is a path where it was found by scanning <tt>_G</tt> and the registry. As a utility, the name guessing functionality is exposed as such:
790 790
791 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> 791 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%">
792 <tr> 792 <tr>
@@ -1233,10 +1233,10 @@
1233 Characteristics of the Lanes implementation of lindas are: 1233 Characteristics of the Lanes implementation of lindas are:
1234 1234
1235 <ul> 1235 <ul>
1236 <li>Keys can be of boolean, number, string, light userdata, and deep userdata type. Tables and functions can't be keys because their identity isn't preserved when transfered from one Lua state to another.</li> 1236 <li>Keys can be of boolean, number, string, light userdata, and deep userdata type. Tables, functions and non-deep userdata can't be keys because their identity isn't preserved when transfered from one Lua state to another.</li>
1237 <li>values can be any type supported by inter-state copying (same <a href="#limitations">limits</a> as for function arguments and upvalues).</li> 1237 <li>Values can be any type supported by inter-state copying (same <a href="#limitations">limits</a> as for function arguments and upvalues).</li>
1238 <li> 1238 <li>
1239 Registered functions transiting into a Keeper state are converted to a special dummy function that holds its actual identity. On transit out, the identity is used to find the real function in the destination. 1239 Registered functions and userdata transiting into a Keeper state are converted to a special dummy closure that holds its actual identity. On transit out, the identity is used to find the real function or userdata in the destination.
1240 For that reason, it is not possible to run user code inside a Keeper state. The only exception is <a href="#on_state_create"><tt>on_state_create</tt></a>, which is handled in a special way. 1240 For that reason, it is not possible to run user code inside a Keeper state. The only exception is <a href="#on_state_create"><tt>on_state_create</tt></a>, which is handled in a special way.
1241 </li> 1241 </li>
1242 <li>Consuming method is <tt>:receive</tt> (not in).</li> 1242 <li>Consuming method is <tt>:receive</tt> (not in).</li>
@@ -1644,7 +1644,7 @@
1644 </ul> 1644 </ul>
1645 </li> 1645 </li>
1646 <li> 1646 <li>
1647 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. 1647 Non-converted full userdata can be passed only if it registered, or prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management.
1648 </li> 1648 </li>
1649 <li> 1649 <li>
1650 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. 1650 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.
@@ -1661,55 +1661,57 @@
1661</p> 1661</p>
1662 1662
1663 1663
1664<h3 id="function_notes">Notes about passing C functions</h3> 1664<h3 id="function_notes">Notes about passing C functions and full userdata</h3>
1665 1665
1666<p> 1666<p>
1667 Functions are transfered as follows (more or less): 1667 C functions and full userdata are transfered as follows (more or less):
1668</p> 1668</p>
1669 1669
1670<table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> 1670<table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre>
1671 // expects a C function on top of the source Lua stack 1671 // expects a C function or full userdata on top of the source Lua stack
1672 copyFunction(lua_State *dest, lua_State* source) 1672 copyValue(lua_State *dest, lua_State* source)
1673 { 1673 {
1674 // fetch function 'name' from source lookup database 1674 // fetch function 'name' from source lookup database
1675 char const* funcname = lookup_func_name(source, -1); 1675 char const* valuename = lookup_name(source, -1);
1676 // lookup a function bound to this name in the destination state, and push it on the stack 1676 // lookup a function or userdata bound to this name in the destination state, and push it on the stack
1677 push_resolved_func(dest, funcname); 1677 push_resolved_value(dest, valuename);
1678 } 1678 }
1679</pre></td></tr></table> 1679</pre></td></tr></table>
1680 1680
1681<p> 1681<p>
1682 The devil lies in the details: what does "function lookup" mean? 1682 The devil lies in the details: what does "lookup" mean?
1683</p> 1683</p>
1684 1684
1685<p> 1685<p>
1686 Since functions are first class values, they don't have a name. All we know for sure is that when a C module registers some functions, they are accessible to the script that required the module through some exposed variables. 1686 Since functions and full userdata are first class values, they don't have a name. All we know for sure is that when a C module registers some functions or full userdata, they are accessible to the script that required the module through some exposed variables.
1687 <br /> 1687 <br />
1688 For example, loading the <tt>string</tt> base library creates a table accessible when indexing the global environment with key <tt>"string"</tt>. Indexing this table with <tt>"match"</tt>, <tt>"gsub"</tt>, etc. will give us a function. 1688 For example, loading the <tt>string</tt> base library creates a table accessible when indexing the global environment with key <tt>"string"</tt>. Indexing this table with <tt>"match"</tt>, <tt>"gsub"</tt>, etc. will give us a function.
1689 <br /> 1689 <br />
1690 When a lane generator creates a lane and performs initializations described by the list of base libraries and the list of required modules, it recursively scans the table created by the initialisation of the module, looking for all values that are C functions. 1690 Similarly, loading the <tt>io</tt> base library creates a table accessible when indexing the global environment with key <tt>"io"</tt>. Indexing this table with <tt>"open"</tt>, will give us a function, and <tt>"stdin"</tt> will give us a full userdata.
1691 <br /> 1691 <br />
1692 Each time a function is encountered, the sequence of keys that reached that function is contatenated in a (hopefully) unique name. The [name, function] and [function, name] pairs are both stored in a lookup table in all involved Lua states (main Lua state and lanes states). 1692 When a lane generator creates a lane and performs initializations described by the list of base libraries and the list of required modules, it recursively scans the table created by the initialisation of the module, looking for all values that are C functions and full userdata.
1693 <br /> 1693 <br />
1694 Then when a function is transfered from one state to another, all we have to do is retrieve the name associated to a function in the source Lua state, then with that name retrieve the equivalent function that already exists in the destination state. 1694 Each time a function or full userdata is encountered, the sequence of keys traversed to reach it is contatenated in a (hopefully) unique name. The [name, value] and [value, name] pairs are both stored in a lookup table in all involved Lua states (main Lua state and lanes states).
1695 <br /> 1695 <br />
1696 Note that there is no need to transfer upvalues, as they are already bound to the function registered in the destination state. (And in any event, it is not possible to create a closure from a C function pushed on the stack, it can only be created with a <tt>lua_CFunction</tt> pointer). 1696 Then, when a function or full userdata is transfered from one state to another, all we have to do is retrieve the name associated to this value in the source Lua state, then with that name retrieve the equivalent value that already exists in the destination state.
1697 <br />
1698 Note that there is no need to transfer upvalues/uservalues, as they are already bound to the value registered in the destination state. (And in any event, it is not possible to create a closure from a C function pushed on the stack, it can only be created with a <tt>lua_CFunction</tt> pointer).
1697</p> 1699</p>
1698 1700
1699<p> 1701<p>
1700 There are several issues here: 1702 There are several issues here:
1701 <ul> 1703 <ul>
1702 <li> 1704 <li>
1703 Some base libraries register some C functions in the global environment. Because of that, Lanes must scan the global namespace to find all C functions (such as <tt>error</tt>, <tt>print</tt>, etc.).<br /> 1705 Some base libraries register some C functions in the global environment. Because of that, Lanes must scan the global namespace to find all C functions (such as <tt>error</tt>, <tt>print</tt>, <tt>require</tt>, etc.).<br />
1704 This happens a single time, when <a href="#initialization"><tt>lanes.configure()</tt></a> is called. Therefore, if some base libraries are not loaded before that point, it will not be possible to send values that reference stuff they offer unless they are manually registered with <tt>lanes.register()</tt>. 1706 This happens a single time, when <a href="#initialization"><tt>lanes.configure()</tt></a> is called. Therefore, if some base libraries are not loaded before that point, it will not be possible to send values that reference stuff they offer unless they are manually registered with <tt>lanes.register()</tt>.
1705 </li> 1707 </li>
1706 <li> 1708 <li>
1707 Nothing prevents a script to create other references to a C function. For example one could do 1709 Nothing prevents a script to create other references to a C function or full userdata. For example one could do
1708 <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> 1710 <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre>
1709 string2 = string 1711 string2 = string
1710 </pre></td></tr></table> 1712 </pre></td></tr></table>
1711 When iterating over all keys of the global table, Lanes has no guarantee that it will hit <tt>"string"</tt> before or after <tt>"string2"</tt>. However, the values associated to <tt>string.match</tt> and <tt>string2.match</tt> are the same C function. 1713 When iterating over all keys of the global table, Lanes has no guarantee that it will hit <tt>"string"</tt> before or after <tt>"string2"</tt>. However, the values associated to <tt>string.match</tt> and <tt>string2.match</tt> are the same C function.
1712 Lanes doesn't normally expect a C function value to be encountered more than once. In the event it occurs, the shortest name that was computed is retained. 1714 Lanes doesn't normally expect a C function or full userdata value to be encountered more than once. In the event it occurs, the shortest name that was computed is retained.
1713 If Lanes processed <tt>"string2"</tt> first, it means that if the Lua state that contains the <tt>"string2"</tt> global name sends function <tt>string.match</tt>, <tt>lookup_func_name</tt> would return name <tt>"string2.match"</tt>, with the obvious effect that <tt>push_resolved_func</tt> 1715 If Lanes processed <tt>"string2"</tt> first, it means that if the Lua state that contains the <tt>"string2"</tt> global name sends function <tt>string.match</tt>, <tt>lookup_func_name</tt> would return name <tt>"string2.match"</tt>, with the obvious effect that <tt>push_resolved_func</tt>
1714 won't find <tt>"string2.match"</tt> in the destination lookup database, thus failing the transfer (even though this function exists, but is referenced under name <tt>"string.match"</tt>). 1716 won't find <tt>"string2.match"</tt> in the destination lookup database, thus failing the transfer (even though this function exists, but is referenced under name <tt>"string.match"</tt>).
1715 </li> 1717 </li>
@@ -1721,9 +1723,9 @@
1721 To circumvent this, Lanes has to select one name among all candidates, and the rule for this is to keep the 'smaller' one: first in byte count, then in lexical order. 1723 To circumvent this, Lanes has to select one name among all candidates, and the rule for this is to keep the 'smaller' one: first in byte count, then in lexical order.
1722 </li> 1724 </li>
1723 </ul> 1725 </ul>
1724 Another more immediate reason of failed transfer is when the destination state doesn't know about the C function that has to be transferred. This occurs if a function is transferred in a lane before it had a chance to scan the module. 1726 Another more immediate reason of failed transfer is when the destination state doesn't know about the C function or full userdata that has to be transferred. This occurs if a value is transferred in a lane before it had a chance to scan the module that exposed it.
1725 If the C function is sent through a <a href="#lindas">linda</a>, it is enough for the destination lane body to have required the module before the function is sent. 1727 If the C function or full userdata is sent through a <a href="#lindas">linda</a>, it is sufficient for the destination lane body to have required the module before the function is sent.
1726 But if the lane body provided to the generator has a C function as upvalue, the transfer itself must succeed, therefore the module that imported that C function must be required in the destination lane before the lane body starts executing. This is where the <a href = "#.required"><tt>.required</tt></a> options play their role. 1728 But if the lane body provided to the generator has a C function or full userdata as upvalue, the transfer itself must succeed, therefore the module that exposed that C function or full userdata must be required in the destination lane before the lane body starts executing. This is where the <a href = "#.required"><tt>.required</tt></a> options play their role.
1727</p> 1729</p>
1728 1730
1729 1731