diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2021-06-23 12:38:01 +0200 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2021-06-23 12:38:01 +0200 |
commit | d1ef9b97e356805c622e4832ec76289bae391a6e (patch) | |
tree | e00a1a4b1c16bcc02d0e6c75d664d93e76f8d606 | |
parent | 5875fe44ba7a240dd101f954c7dc83337a0c2cef (diff) | |
download | lanes-d1ef9b97e356805c622e4832ec76289bae391a6e.tar.gz lanes-d1ef9b97e356805c622e4832ec76289bae391a6e.tar.bz2 lanes-d1ef9b97e356805c622e4832ec76289bae391a6e.zip |
__lanesclone now receives the original as light userdata the first time it is called
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | deep_test/deep_test.c | 12 | ||||
-rw-r--r-- | docs/index.html | 25 | ||||
-rw-r--r-- | src/tools.c | 10 |
4 files changed, 35 insertions, 17 deletions
@@ -1,7 +1,10 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 148: BGe 23-Jun-21 | ||
4 | * __lanesclone now receives the original as light userdata the first time it is called -> BREAKS CUSTOM DEEP USERDATA API | ||
5 | |||
3 | CHANGE 147: BGe 16-Jun-21 | 6 | CHANGE 147: BGe 16-Jun-21 |
4 | * changed lanes.threads() output so that several lanes with the same name don't clobber each other in the result table | 7 | * changed lanes.threads() output so that several lanes with the same name don't clobber each other in the result table -> BREAKS API |
5 | * bumped version to 3.15 because of the API change | 8 | * bumped version to 3.15 because of the API change |
6 | 9 | ||
7 | CHANGE 146: BGe 26-Apr-19 | 10 | CHANGE 146: BGe 26-Apr-19 |
diff --git a/deep_test/deep_test.c b/deep_test/deep_test.c index 9585a3c..61c81c5 100644 --- a/deep_test/deep_test.c +++ b/deep_test/deep_test.c | |||
@@ -166,8 +166,12 @@ static int clonable_lanesclone( lua_State* L) | |||
166 | { | 166 | { |
167 | switch( lua_gettop( L)) | 167 | switch( lua_gettop( L)) |
168 | { | 168 | { |
169 | case 0: | 169 | case 1: |
170 | lua_pushinteger( L, sizeof( struct s_MyClonableUserdata)); | 170 | { |
171 | // in case we need it to compute the amount of memory we need | ||
172 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); | ||
173 | lua_pushinteger( L, sizeof( struct s_MyClonableUserdata)); | ||
174 | } | ||
171 | return 1; | 175 | return 1; |
172 | 176 | ||
173 | case 2: | 177 | case 2: |
@@ -175,8 +179,8 @@ static int clonable_lanesclone( lua_State* L) | |||
175 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); | 179 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); |
176 | struct s_MyClonableUserdata* from = lua_touserdata( L, 2); | 180 | struct s_MyClonableUserdata* from = lua_touserdata( L, 2); |
177 | *self = *from; | 181 | *self = *from; |
178 | return 0; | ||
179 | } | 182 | } |
183 | return 0; | ||
180 | 184 | ||
181 | default: | 185 | default: |
182 | (void) luaL_error( L, "Lanes called clonable_lanesclone with unexpected parameters"); | 186 | (void) luaL_error( L, "Lanes called clonable_lanesclone with unexpected parameters"); |
@@ -223,7 +227,7 @@ extern int __declspec(dllexport) luaopen_deep_test(lua_State* L) | |||
223 | { | 227 | { |
224 | luaL_newlib( L, deep_module); // M | 228 | luaL_newlib( L, deep_module); // M |
225 | 229 | ||
226 | // preregister the metatables for the types we can instanciate so that Lanes can know about them | 230 | // preregister the metatables for the types we can instantiate so that Lanes can know about them |
227 | if( luaL_newmetatable( L, "clonable")) // M mt | 231 | if( luaL_newmetatable( L, "clonable")) // M mt |
228 | { | 232 | { |
229 | luaL_setfuncs( L, clonable_mt, 0); | 233 | luaL_setfuncs( L, clonable_mt, 0); |
diff --git a/docs/index.html b/docs/index.html index 49b862f..e9a313e 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -64,13 +64,13 @@ | |||
64 | <font size="-1"> | 64 | <font size="-1"> |
65 | <p> | 65 | <p> |
66 | <br/> | 66 | <br/> |
67 | <i>Copyright © 2007-19 Asko Kauppi, Benoit Germain. All rights reserved.</i> | 67 | <i>Copyright © 2007-21 Asko Kauppi, Benoit Germain. All rights reserved.</i> |
68 | <br/> | 68 | <br/> |
69 | Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3 and 5.4. | 69 | Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3 and 5.4. |
70 | </p> | 70 | </p> |
71 | 71 | ||
72 | <p> | 72 | <p> |
73 | This document was revised on 26-Apr-19, and applies to version <tt>3.14.0</tt>. | 73 | This document was revised on 23-Jun-21, and applies to version <tt>3.15.0</tt>. |
74 | </p> | 74 | </p> |
75 | </font> | 75 | </font> |
76 | </center> | 76 | </center> |
@@ -1548,23 +1548,31 @@ events to a common Linda, but... :).</font> | |||
1548 | 1548 | ||
1549 | <h3 id="clonable_userdata">Clonable full userdata in your own apps</h3> | 1549 | <h3 id="clonable_userdata">Clonable full userdata in your own apps</h3> |
1550 | <p> | 1550 | <p> |
1551 | Starting with version 3.13.0, a new way of passing full userdata across lanes uses a new <tt>__lanesclone</tt> metamethod. A typical implementation would look like: | 1551 | Starting with version 3.13.0, a new way of passing full userdata across lanes uses a new <tt>__lanesclone</tt> metamethod. |
1552 | When a deep userdata is cloned, Lanes calls <tt>__lanesclone</tt> twice, in the context of the source lane.</br> | ||
1553 | The first call receives the original as light userdata, as in <tt>ud:__lanesclone()</tt>, and should return the amount of memory used to create the cloned full userdata.</br> | ||
1554 | The second call receives the clone and original as light userdata, as in <tt>clone:__lanesclone(original)</tt>, and should perform the actual cloning.</br> | ||
1555 | A typical implementation would look like: | ||
1552 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1556 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1553 | static int clonable_lanesclone( lua_State* L) | 1557 | static int clonable_lanesclone( lua_State* L) |
1554 | { | 1558 | { |
1555 | switch( lua_gettop( L)) | 1559 | switch( lua_gettop( L)) |
1556 | { | 1560 | { |
1557 | case 0: | 1561 | case 1: // original:__lanesclone() |
1558 | lua_pushinteger( L, sizeof( struct s_MyClonableUserdata)); | 1562 | { |
1563 | // the original (as light userdata), in case you need it to compute the size of the clone | ||
1564 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); | ||
1565 | lua_pushinteger( L, sizeof( struct s_MyClonableUserdata)); | ||
1566 | } | ||
1559 | return 1; | 1567 | return 1; |
1560 | 1568 | ||
1561 | case 2: | 1569 | case 2: // clone:__lanesclone(original) |
1562 | { | 1570 | { |
1563 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); | 1571 | struct s_MyClonableUserdata* self = lua_touserdata( L, 1); |
1564 | struct s_MyClonableUserdata* from = lua_touserdata( L, 2); | 1572 | struct s_MyClonableUserdata* from = lua_touserdata( L, 2); |
1565 | *self = *from; | 1573 | *self = *from; |
1566 | return 0; | ||
1567 | } | 1574 | } |
1575 | return 0; | ||
1568 | 1576 | ||
1569 | default: | 1577 | default: |
1570 | (void) luaL_error( L, "Lanes called clonable_lanesclone with unexpected parameters"); | 1578 | (void) luaL_error( L, "Lanes called clonable_lanesclone with unexpected parameters"); |
@@ -1605,7 +1613,7 @@ int luaopen_deep_test(lua_State* L) | |||
1605 | </p> | 1613 | </p> |
1606 | 1614 | ||
1607 | <p> | 1615 | <p> |
1608 | Then a new clonable userdata instance can just do like any non-Lanes aware userdata, as long as its metatable contains the aforementionned <tt>__lanesclone</tt> method. Note that the current implementation doesn't support uservalues on such userdata. | 1616 | Then a new clonable userdata instance can just do like any non-Lanes aware userdata, as long as its metatable contains the aforementionned <tt>__lanesclone</tt> method. |
1609 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1617 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1610 | int luaD_new_clonable( lua_State* L) | 1618 | int luaD_new_clonable( lua_State* L) |
1611 | { | 1619 | { |
@@ -1746,3 +1754,4 @@ int luaD_new_clonable( lua_State* L) | |||
1746 | 1754 | ||
1747 | </body> | 1755 | </body> |
1748 | </html> | 1756 | </html> |
1757 | </pre></pre></pre></pre></pre></pre></pre> \ No newline at end of file | ||
diff --git a/src/tools.c b/src/tools.c index 02d51ae..f3ac236 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -1760,8 +1760,9 @@ static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_Stat | |||
1760 | void* const source = lua_touserdata( L, i); | 1760 | void* const source = lua_touserdata( L, i); |
1761 | void* clone = NULL; | 1761 | void* clone = NULL; |
1762 | lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone | 1762 | lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone |
1763 | // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone | 1763 | // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone |
1764 | lua_call( L, 0, 1); // ... mt __lanesclone size | 1764 | lua_pushlightuserdata( L, source); // ... mt __lanesclone __lanesclone source |
1765 | lua_call( L, 1, 1); // ... mt __lanesclone size | ||
1765 | STACK_MID( L, 3); | 1766 | STACK_MID( L, 3); |
1766 | userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size | 1767 | userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size |
1767 | lua_pop( L, 1); // ... mt __lanesclone | 1768 | lua_pop( L, 1); // ... mt __lanesclone |
@@ -1899,8 +1900,9 @@ static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i | |||
1899 | // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with | 1900 | // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with |
1900 | lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone | 1901 | lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone |
1901 | lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone | 1902 | lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone |
1902 | // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone | 1903 | // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone |
1903 | lua_call( L2, 0, 1); // ... mt __lanesclone size | 1904 | lua_pushlightuserdata( L2, source); // ... mt __lanesclone __lanesclone source |
1905 | lua_call( L2, 1, 1); // ... mt __lanesclone size | ||
1904 | userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size | 1906 | userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size |
1905 | lua_pop( L2, 1); // ... mt __lanesclone | 1907 | lua_pop( L2, 1); // ... mt __lanesclone |
1906 | lua_pushnil( L2); // ... mt __lanesclone nil | 1908 | lua_pushnil( L2); // ... mt __lanesclone nil |