diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-02 11:53:09 +0100 |
commit | ca7657e24549acb8a2dd45fa81c309b5bf9f61ee (patch) | |
tree | 0124afa9a67d5f9d64fdbad4724bc715b7b502fb /docs | |
parent | 0728e80bc2d3f5609f19b76f2bcf10412ce029b4 (diff) | |
download | lanes-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.html | 58 |
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 | ||