diff options
Diffstat (limited to '')
-rw-r--r-- | docs/index.html | 231 | ||||
-rw-r--r-- | src/lanes.lua | 2 | ||||
-rw-r--r-- | tests/appendud.lua | 1 | ||||
-rw-r--r-- | tests/atomic.lua | 1 | ||||
-rw-r--r-- | tests/basic.lua | 5 | ||||
-rw-r--r-- | tests/cyclic.lua | 1 | ||||
-rw-r--r-- | tests/deadlock.lua | 49 | ||||
-rw-r--r-- | tests/ehynes.lua | 1 | ||||
-rw-r--r-- | tests/fibonacci.lua | 2 | ||||
-rw-r--r-- | tests/hangtest.lua | 1 | ||||
-rw-r--r-- | tests/irayo_closure.lua | 1 | ||||
-rw-r--r-- | tests/irayo_recursive.lua | 2 | ||||
-rw-r--r-- | tests/launchtest.lua | 1 | ||||
-rw-r--r-- | tests/objects.lua | 1 | ||||
-rw-r--r-- | tests/parallel_os_calls.lua | 2 | ||||
-rw-r--r-- | tests/pingpong.lua | 2 | ||||
-rw-r--r-- | tests/recursive.lua | 8 |
17 files changed, 151 insertions, 160 deletions
diff --git a/docs/index.html b/docs/index.html index 73753d7..5f9a0fb 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -63,9 +63,9 @@ | |||
63 | 63 | ||
64 | <font size="-1"> | 64 | <font size="-1"> |
65 | <p> | 65 | <p> |
66 | <br/> | 66 | <br /> |
67 | <i>Copyright © 2007-24 Asko Kauppi, Benoit Germain. All rights reserved.</i> | 67 | <i>Copyright © 2007-24 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 | ||
@@ -184,7 +184,7 @@ | |||
184 | </table> | 184 | </table> |
185 | <p> | 185 | <p> |
186 | <tt>luaopen_lanes_embedded</tt> leaves the module table on the stack. <a href="#initialization"><tt>lanes.configure()</tt></a> must still be called in order to use Lanes. | 186 | <tt>luaopen_lanes_embedded</tt> leaves the module table on the stack. <a href="#initialization"><tt>lanes.configure()</tt></a> must still be called in order to use Lanes. |
187 | <br/> | 187 | <br /> |
188 | If <tt>_luaopen_lanes</tt> is <tt>nullptr</tt>, a default loader will simply attempt the equivalent of <tt>luaL_dofile(L, "lanes.lua")</tt>. | 188 | If <tt>_luaopen_lanes</tt> is <tt>nullptr</tt>, a default loader will simply attempt the equivalent of <tt>luaL_dofile(L, "lanes.lua")</tt>. |
189 | </p> | 189 | </p> |
190 | 190 | ||
@@ -197,17 +197,17 @@ | |||
197 | <tr> | 197 | <tr> |
198 | <td> | 198 | <td> |
199 | <pre> #include "lanes.h"</pre> | 199 | <pre> #include "lanes.h"</pre> |
200 | <br/> | 200 | <br /> |
201 | <pre> int load_lanes_lua(lua_State* L)</pre> | 201 | <pre> int load_lanes_lua(lua_State* L)</pre> |
202 | <pre> {</pre> | 202 | <pre> {</pre> |
203 | <pre> // retrieve lanes.lua from wherever it is stored and return the result of its execution</pre> | 203 | <pre> // retrieve lanes.lua from wherever it is stored and return the result of its execution</pre> |
204 | <pre> // trivial example 1:</pre> | 204 | <pre> // trivial example 1:</pre> |
205 | <pre> luaL_dofile(L, "lanes.lua");</pre> | 205 | <pre> luaL_dofile(L, "lanes.lua");</pre> |
206 | <br/> | 206 | <br /> |
207 | <pre> // trivial example 2:</pre> | 207 | <pre> // trivial example 2:</pre> |
208 | <pre> luaL_dostring(L, bin2c_lanes_lua);</pre> | 208 | <pre> luaL_dostring(L, bin2c_lanes_lua);</pre> |
209 | <pre> }</pre> | 209 | <pre> }</pre> |
210 | <br/> | 210 | <br /> |
211 | <pre> void embed_lanes(lua_State* L)</pre> | 211 | <pre> void embed_lanes(lua_State* L)</pre> |
212 | <pre> {</pre> | 212 | <pre> {</pre> |
213 | <pre> // we need base libraries for Lanes for work</pre> | 213 | <pre> // we need base libraries for Lanes for work</pre> |
@@ -219,7 +219,7 @@ | |||
219 | <pre> // another example with a custom loader</pre> | 219 | <pre> // another example with a custom loader</pre> |
220 | <pre> luaopen_lanes_embedded(L, load_lanes_lua);</pre> | 220 | <pre> luaopen_lanes_embedded(L, load_lanes_lua);</pre> |
221 | <pre> lua_pop(L, 1);</pre> | 221 | <pre> lua_pop(L, 1);</pre> |
222 | <br/> | 222 | <br /> |
223 | <pre> // a little test to make sure things work as expected</pre> | 223 | <pre> // a little test to make sure things work as expected</pre> |
224 | <pre> luaL_dostring(L, "local lanes = require 'lanes'.configure{with_timers = false}; local l = lanes.linda()");</pre> | 224 | <pre> luaL_dostring(L, "local lanes = require 'lanes'.configure{with_timers = false}; local l = lanes.linda()");</pre> |
225 | <pre> }</pre> | 225 | <pre> }</pre> |
@@ -240,26 +240,25 @@ | |||
240 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> | 240 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> |
241 | <tr> | 241 | <tr> |
242 | <td> | 242 | <td> |
243 | <pre> local lanes = require "lanes".configure()</pre> | 243 | <pre> local lanes = require "lanes".configure(options|nil)</pre> |
244 | </td> | 244 | </td> |
245 | </tr> | 245 | </tr> |
246 | </table> | 246 | </table> |
247 | 247 | ||
248 | <p> | 248 | <p> |
249 | Requiring the module follows Lua 5.2+ rules: the module is not available under the global name "lanes", but has to be accessed through <tt>require</tt>'s return value.<br/> | 249 | Requiring the module follows Lua 5.2+ rules: the module is not available under the global name "lanes", but has to be accessed through <tt>require</tt>'s return value.<br /> |
250 | Lanes needs <tt>"base"</tt>, <tt>"string"</tt> and <tt>"table"</tt> to be initialized beforehand (plus <tt>"jit"</tt> for LuaJIT). | 250 | Lanes needs <tt>"base"</tt>, <tt>"string"</tt> and <tt>"table"</tt> to be initialized beforehand (plus <tt>"jit"</tt> for LuaJIT). |
251 | </p> | 251 | </p> |
252 | <p> | 252 | <p> |
253 | After lanes is required, it is necessary to call <tt>lanes.configure()</tt>, which is the only function exposed by the module at this point. Calling <tt>lanes.configure()</tt> will perform one-time initializations and make the rest of the API available.<br/> | 253 | After lanes is required, it is recommended to call <tt>lanes.configure()</tt>, which is the only function exposed by the module at this point. Calling <tt>lanes.configure()</tt> will perform one-time initializations and make the rest of the API available.<br /> |
254 | At the same time, <tt>lanes.configure()</tt> itself will be replaced by another function that raises an error if called again with differing arguments, if any. | 254 | If <tt>lanes.configure()</tt> is not called before starting to use Lanes, it will be called automatically for you with default settings.<br /> |
255 | Only the first occurence of <tt>require "lanes"</tt> must be followed by a call to <tt>lanes.configure()</tt>. From this point, a simple <tt>require "lanes"</tt> will be enough wherever you need to require lanes again.<br /> | ||
256 | After being called, <tt>lanes.configure()</tt> itself is replaced by another function that does nothing with the argument it receives, in case it happens to be called again. | ||
255 | </p> | 257 | </p> |
256 | <p> | 258 | <p> |
257 | Also, once Lanes is initialized, <tt>require()</tt> is replaced by another one that wraps it inside a mutex, both in the main state and in all created lanes. This prevents multiple thread-unsafe module initializations from several lanes to occur simultaneously. | 259 | Also, once Lanes is initialized, <tt>require()</tt> is replaced by another one that wraps it inside a mutex, both in the main state and in all created lanes. This prevents multiple thread-unsafe module initializations from several lanes to occur simultaneously. |
258 | It remains to be seen whether this is actually useful or not: If a module is already threadsafe, protecting its initialization isn't useful. And if it is not, any parallel operation may crash without Lanes being able to do anything about it. | 260 | It remains to be seen whether this is actually useful or not: If a module is already threadsafe, protecting its initialization isn't useful. And if it is not, any parallel operation may crash without Lanes being able to do anything about it. |
259 | </p> | 261 | </p> |
260 | <p> | ||
261 | <b>IMPORTANT NOTE:</b> Only the first occurence of <tt>require "lanes"</tt> must be followed by a call to <tt>lanes.configure()</tt>. From this point, a simple <tt>require "lanes"</tt> will be enough wherever you need to require lanes again. | ||
262 | </p> | ||
263 | 262 | ||
264 | <p> | 263 | <p> |
265 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> | 264 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> |
@@ -285,8 +284,8 @@ | |||
285 | </td> | 284 | </td> |
286 | <td>integer in [0,100]</td> | 285 | <td>integer in [0,100]</td> |
287 | <td> | 286 | <td> |
288 | Controls the number of "user" <a href="#keepers">Keeper state</a> used internally by <a href="#lindas">Linda</a>) objects to transfer data between lanes. Default is <tt>0</tt>.<br/> | 287 | Controls the number of "user" <a href="#keepers">Keeper state</a> used internally by <a href="#lindas">Linda</a>) objects to transfer data between lanes. Default is <tt>0</tt>.<br /> |
289 | Lanes always creates at least one keeper state (of group <tt>0</tt> for the internal timer <a href="#lindas">Linda</a>. If <tt>nb_user_keepers</tt> is <tt>0</tt>, the other lindas you create will share this keeper by necessity.<br/> | 288 | Lanes always creates at least one keeper state (of group <tt>0</tt> for the internal timer <a href="#lindas">Linda</a>. If <tt>nb_user_keepers</tt> is <tt>0</tt>, the other lindas you create will share this keeper by necessity.<br /> |
290 | If there is more than one <a href="#keepers">Keeper state</a> (in total), <a href="#lindas">Linda</a> creation must specify the group it belongs to. | 289 | If there is more than one <a href="#keepers">Keeper state</a> (in total), <a href="#lindas">Linda</a> creation must specify the group it belongs to. |
291 | </td> | 290 | </td> |
292 | </tr> | 291 | </tr> |
@@ -297,8 +296,8 @@ | |||
297 | </td> | 296 | </td> |
298 | <td>integer</td> | 297 | <td>integer</td> |
299 | <td> | 298 | <td> |
300 | If <0, GC runs automatically. This is the default.<br/> | 299 | If <0, GC runs automatically. This is the default.<br /> |
301 | If 0, GC runs after *every* <a href="#keepers">Keeper</a> operation.<br/> | 300 | If 0, GC runs after *every* <a href="#keepers">Keeper</a> operation.<br /> |
302 | If >0, <a href="#keepers">Keeper states</a> run GC manually with <tt>lua_gc(LUA_GCCOLLECT)</tt> whenever memory usage reported by <tt>lua_gc(LUA_GCCOUNT)</tt> reaches this threshold. Check is made after every operation (see <a href="#lindas">below</a>). If memory usage remains above threshold after the GC cycle, an error is raised. | 301 | If >0, <a href="#keepers">Keeper states</a> run GC manually with <tt>lua_gc(LUA_GCCOLLECT)</tt> whenever memory usage reported by <tt>lua_gc(LUA_GCCOUNT)</tt> reaches this threshold. Check is made after every operation (see <a href="#lindas">below</a>). If memory usage remains above threshold after the GC cycle, an error is raised. |
303 | </td> | 302 | </td> |
304 | </tr> | 303 | </tr> |
@@ -337,8 +336,8 @@ | |||
337 | <tt>nil</tt>/<tt>"protected"</tt>/function | 336 | <tt>nil</tt>/<tt>"protected"</tt>/function |
338 | </td> | 337 | </td> |
339 | <td> | 338 | <td> |
340 | If <tt>nil</tt>, Lua states are created with <tt>lua_newstate()</tt> and reuse the allocator from the master state.<br/> | 339 | If <tt>nil</tt>, Lua states are created with <tt>lua_newstate()</tt> and reuse the allocator from the master state.<br /> |
341 | If <tt>"protected"</tt>, The default allocator obtained from <tt>lua_getallocf()</tt> in the master state is wrapped inside a critical section and used in all newly created states.<br/> | 340 | If <tt>"protected"</tt>, The default allocator obtained from <tt>lua_getallocf()</tt> in the master state is wrapped inside a critical section and used in all newly created states.<br /> |
342 | If a <tt>function</tt>, this function is called prior to creating the state. It should return a full userdata containing the following structure: | 341 | If a <tt>function</tt>, this function is called prior to creating the state. It should return a full userdata containing the following structure: |
343 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> | 342 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> |
344 | <tr> | 343 | <tr> |
@@ -361,8 +360,8 @@ | |||
361 | </td> | 360 | </td> |
362 | <td> | 361 | <td> |
363 | Controls which allocator is used for Lanes internal allocations (for <a href="#keepers">Keeper state</a>, <a href="#lindas">Linda</a> and lane management). | 362 | Controls which allocator is used for Lanes internal allocations (for <a href="#keepers">Keeper state</a>, <a href="#lindas">Linda</a> and lane management). |
364 | If <tt>"libc"</tt>, Lanes uses <tt>realloc</tt> and <tt>free</tt>.<br/> | 363 | If <tt>"libc"</tt>, Lanes uses <tt>realloc</tt> and <tt>free</tt>.<br /> |
365 | If <tt>"allocator"</tt>, Lanes uses whatever was obtained from the <tt>"allocator"</tt> setting.<br/> | 364 | If <tt>"allocator"</tt>, Lanes uses whatever was obtained from the <tt>"allocator"</tt> setting.<br /> |
366 | This option is mostly useful for embedders that want control all memory allocations, but have issues when Lanes tries to use the Lua State allocator for internal purposes (especially with LuaJIT). | 365 | This option is mostly useful for embedders that want control all memory allocations, but have issues when Lanes tries to use the Lua State allocator for internal purposes (especially with LuaJIT). |
367 | </td> | 366 | </td> |
368 | </tr> | 367 | </tr> |
@@ -388,16 +387,16 @@ | |||
388 | function/<tt>nil</tt> | 387 | function/<tt>nil</tt> |
389 | </td> | 388 | </td> |
390 | <td> | 389 | <td> |
391 | If provided, will be called in every created Lua state right after initializing the base libraries, with a single string argument, either <tt>"lane"</tt> or <tt>"keeper"</tt>.<br/> | 390 | If provided, will be called in every created Lua state right after initializing the base libraries, with a single string argument, either <tt>"lane"</tt> or <tt>"keeper"</tt>.<br /> |
392 | If it is a C function, a C closure will be reconstructed in the created state from the C pointer. Lanes will raise an error if the function has upvalues.<br/> | 391 | If it is a C function, a C closure will be reconstructed in the created state from the C pointer. Lanes will raise an error if the function has upvalues.<br /> |
393 | Keeper states will call it as well, but only if it is a C function (<a href="#keepers">Keeper states</a> are not able to execute any user Lua code).<br/> | 392 | Keeper states will call it as well, but only if it is a C function (<a href="#keepers">Keeper states</a> are not able to execute any user Lua code).<br /> |
394 | Typical usage is twofold: | 393 | Typical usage is twofold: |
395 | <ul> | 394 | <ul> |
396 | <li>Tweak <tt>package.loaders</tt></li> | 395 | <li>Tweak <tt>package.loaders</tt></li> |
397 | <li>Load some additional C functions in the global space (of course only a C function will be able to do this).</li> | 396 | <li>Load some additional C functions in the global space (of course only a C function will be able to do this).</li> |
398 | </ul> | 397 | </ul> |
399 | That way, all changes in the state can be properly taken into account when building the function lookup database. Default is <tt>nil</tt>.<br/> | 398 | That way, all changes in the state can be properly taken into account when building the function lookup database. Default is <tt>nil</tt>.<br /> |
400 | If <tt>on_state_create()</tt> is a Lua function, it will be transfered normally before the call.<br/> | 399 | If <tt>on_state_create()</tt> is a Lua function, it will be transfered normally before the call.<br /> |
401 | </td> | 400 | </td> |
402 | </tr> | 401 | </tr> |
403 | 402 | ||
@@ -439,9 +438,9 @@ | |||
439 | 438 | ||
440 | <p> | 439 | <p> |
441 | 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>. | 440 | 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>. |
442 | <br/> | 441 | <br /> |
443 | 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 | Use <tt>lanes.require()</tt> for this purpose. This will call the original <tt>require()</tt>, then add the result to the lookup databases. |
444 | <br/> | 443 | <br /> |
445 | It is also possible to register a given module with <tt>lanes.register()</tt>. This function will raise an error if the registered module is not a function or table. | 444 | It is also possible to register a given module with <tt>lanes.register()</tt>. This function will raise an error if the registered module is not a function or table. |
446 | </p> | 445 | </p> |
447 | 446 | ||
@@ -469,9 +468,9 @@ | |||
469 | </p> | 468 | </p> |
470 | 469 | ||
471 | <p> | 470 | <p> |
472 | An error will be raised if you attempt to do this from inside a lane, or on bad arguments (non-function, or too many arguments).<br/> | 471 | An error will be raised if you attempt to do this from inside a lane, or on bad arguments (non-function, or too many arguments).<br /> |
473 | Only the last registered finalizer is kept. It can be cleared by passing <tt>nil</tt> or nothing.<br/> | 472 | Only the last registered finalizer is kept. It can be cleared by passing <tt>nil</tt> or nothing.<br /> |
474 | The installed function is called after all free-running lanes are terminated, but before lindas become unusable.<br/> | 473 | The installed function is called after all free-running lanes are terminated, but before lindas become unusable.<br /> |
475 | If an error occurs inside this finalizer, it is silently swallowed, since it happens only during state shutdown, and you can't do anything about it. | 474 | If an error occurs inside this finalizer, it is silently swallowed, since it happens only during state shutdown, and you can't do anything about it. |
476 | </p> | 475 | </p> |
477 | 476 | ||
@@ -485,17 +484,17 @@ | |||
485 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> | 484 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> |
486 | <tr> | 485 | <tr> |
487 | <td> | 486 | <td> |
488 | <pre> local lanes = require "lanes".configure()</pre> | 487 | <pre> local lanes = require "lanes"</pre> |
489 | <br/> | 488 | <br /> |
490 | <pre> f = lanes.gen(function(n) return 2 * n end)</pre> | 489 | <pre> f = lanes.gen(function(n) return 2 * n end)</pre> |
491 | <pre> a = f(1)</pre> | 490 | <pre> a = f(1)</pre> |
492 | <pre> b = f(2)</pre> | 491 | <pre> b = f(2)</pre> |
493 | <br/> | 492 | <br /> |
494 | <pre> print(a[1], b[1]) -- 2 4</pre> | 493 | <pre> print(a[1], b[1]) -- 2 4</pre> |
495 | </td> | 494 | </td> |
496 | </tr> | 495 | </tr> |
497 | </table> | 496 | </table> |
498 | <br/> | 497 | <br /> |
499 | <table border=1 bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> | 498 | <table border=1 bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> |
500 | <tr> | 499 | <tr> |
501 | <td> | 500 | <td> |
@@ -507,7 +506,7 @@ | |||
507 | 506 | ||
508 | <p> | 507 | <p> |
509 | The function returned by <tt>lanes.gen()</tt> is a "generator" for launching any number of lanes. They will share code, options, initial globals, but the particular arguments may vary. Only calling the generator function actually launches a lane, and provides a handle for controlling it. | 508 | The function returned by <tt>lanes.gen()</tt> is a "generator" for launching any number of lanes. They will share code, options, initial globals, but the particular arguments may vary. Only calling the generator function actually launches a lane, and provides a handle for controlling it. |
510 | <br/> | 509 | <br /> |
511 | Alternatively, <tt>lane_func</tt> may be a string, in which case it will be compiled in the lane. This was to be able to launch lanes with older versions of LuaJIT, which didn't not support <tt>lua_dump</tt>, used internally to transfer functions to the lane. | 510 | Alternatively, <tt>lane_func</tt> may be a string, in which case it will be compiled in the lane. This was to be able to launch lanes with older versions of LuaJIT, which didn't not support <tt>lua_dump</tt>, used internally to transfer functions to the lane. |
512 | </p> | 511 | </p> |
513 | 512 | ||
@@ -680,7 +679,7 @@ | |||
680 | </p> | 679 | </p> |
681 | 680 | ||
682 | <p> | 681 | <p> |
683 | Any non-<tt>nil</tt> value causes initialization of <tt>"base"</tt> and <tt>"jit"</tt> (the latter only for LuaJIT-based builds).<br/> | 682 | Any non-<tt>nil</tt> value causes initialization of <tt>"base"</tt> and <tt>"jit"</tt> (the latter only for LuaJIT-based builds).<br /> |
684 | Initializing the standard libs takes a bit of time at each lane invocation. This is the main reason why "no libraries" is the default. | 683 | Initializing the standard libs takes a bit of time at each lane invocation. This is the main reason why "no libraries" is the default. |
685 | </p> | 684 | </p> |
686 | 685 | ||
@@ -702,7 +701,7 @@ | |||
702 | </td> | 701 | </td> |
703 | <td>table</td> | 702 | <td>table</td> |
704 | <td> | 703 | <td> |
705 | Sets the globals table for the launched threads. This can be used for giving them constants. The key/value pairs of <tt>table</tt> are transfered in the lane globals after the libraries have been loaded and the modules required.<br/> | 704 | Sets the globals table for the launched threads. This can be used for giving them constants. The key/value pairs of <tt>table</tt> are transfered in the lane globals after the libraries have been loaded and the modules required.<br /> |
706 | The global values of different lanes are in no manner connected; modifying one will only affect the particular lane. | 705 | The global values of different lanes are in no manner connected; modifying one will only affect the particular lane. |
707 | </td> | 706 | </td> |
708 | </tr> | 707 | </tr> |
@@ -715,7 +714,7 @@ | |||
715 | 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>. | 714 | 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>. |
716 | 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. | 715 | 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. |
717 | 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. | 716 | 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. |
718 | 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/> | 717 | 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 /> |
719 | ATTEMPTING TO TRANSFER A FUNCTION REGISTERED BY A MODULE NOT LISTED HERE WILL RAISE AN ERROR. | 718 | ATTEMPTING TO TRANSFER A FUNCTION REGISTERED BY A MODULE NOT LISTED HERE WILL RAISE AN ERROR. |
720 | </td> | 719 | </td> |
721 | </tr> | 720 | </tr> |
@@ -725,8 +724,8 @@ | |||
725 | </td> | 724 | </td> |
726 | <td>string</td> | 725 | <td>string</td> |
727 | <td> | 726 | <td> |
728 | Sets the error reporting mode. One of <tt>"minimal"</tt> (the default), <tt>"basic"</tt>, <tt>"extended"</tt>.<br/> | 727 | Sets the error reporting mode. One of <tt>"minimal"</tt> (the default), <tt>"basic"</tt>, <tt>"extended"</tt>.<br /> |
729 | <tt>"minimal"</tt> yields only the location of the error.<br/> | 728 | <tt>"minimal"</tt> yields only the location of the error.<br /> |
730 | The other 2 yield a full stack trace, with different amounts of data extracted from the debug infos. See <a href="#results">Results</a>. | 729 | The other 2 yield a full stack trace, with different amounts of data extracted from the debug infos. See <a href="#results">Results</a>. |
731 | </td> | 730 | </td> |
732 | </tr> | 731 | </tr> |
@@ -755,8 +754,8 @@ | |||
755 | <td>integer</td> | 754 | <td>integer</td> |
756 | <td> | 755 | <td> |
757 | The priority of lanes generated in the range -3..+3 (default is 0). | 756 | The priority of lanes generated in the range -3..+3 (default is 0). |
758 | These values are a mapping over the actual priority range of the underlying implementation.<br/> | 757 | These values are a mapping over the actual priority range of the underlying implementation.<br /> |
759 | Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.<br/> | 758 | Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.<br /> |
760 | A lane can also change its own thread priority dynamically with <a href="#priority"><tt>lanes.set_thread_priority()</tt></a>. | 759 | A lane can also change its own thread priority dynamically with <a href="#priority"><tt>lanes.set_thread_priority()</tt></a>. |
761 | </td> | 760 | </td> |
762 | </tr> | 761 | </tr> |
@@ -766,7 +765,7 @@ | |||
766 | </td> | 765 | </td> |
767 | <td> table</td> | 766 | <td> table</td> |
768 | <td> | 767 | <td> |
769 | Specifying it when <code>libs_str</code> doesn't cause the <code>package</code> library to be loaded will generate an error.<br/> | 768 | Specifying it when <code>libs_str</code> doesn't cause the <code>package</code> library to be loaded will generate an error.<br /> |
770 | If not specified, the created lane will receive the current values of <tt>package</tt>. Only <tt>path</tt>, <tt>cpath</tt>, <tt>preload</tt> and <tt>loaders</tt> (Lua 5.1)/<tt>searchers</tt> (Lua 5.2) are transfered. | 769 | If not specified, the created lane will receive the current values of <tt>package</tt>. Only <tt>path</tt>, <tt>cpath</tt>, <tt>preload</tt> and <tt>loaders</tt> (Lua 5.1)/<tt>searchers</tt> (Lua 5.2) are transfered. |
771 | </td> | 770 | </td> |
772 | </tr> | 771 | </tr> |
@@ -774,14 +773,14 @@ | |||
774 | 773 | ||
775 | <p> | 774 | <p> |
776 | Each lane gets a global function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says. Supported debuggers are Microsoft Visual Studio (for the C side) and <a href="https://github.com/unknownworlds/decoda">Decoda</a> (for the Lua side).<br /> | 775 | Each lane gets a global function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says. Supported debuggers are Microsoft Visual Studio (for the C side) and <a href="https://github.com/unknownworlds/decoda">Decoda</a> (for the Lua side).<br /> |
777 | Change <tt>HAVE_DECODA_SUPPORT()</tt> in <tt>lanesconf.h</tt> to enable the Decoda support, that sets a special global variable <tt>decoda_name</tt> in the lane's state.<br/> | 776 | Change <tt>HAVE_DECODA_SUPPORT()</tt> in <tt>lanesconf.h</tt> to enable the Decoda support, that sets a special global variable <tt>decoda_name</tt> in the lane's state.<br /> |
778 | The name is stored inside the Lua state registry so that it is available for error reporting. Changing <tt>decoda_name</tt> doesn't affect this hidden name or the OS thread name reported by MSVC.<br/> | 777 | The name is stored inside the Lua state registry so that it is available for error reporting. Changing <tt>decoda_name</tt> doesn't affect this hidden name or the OS thread name reported by MSVC.<br /> |
779 | When Lanes is initialized by the first <a href="#initialization"><tt>lanes.configure()</tt></a> call, <tt>"main"</tt> is stored in the registry in the same fashion (but <tt>decoda_name</tt> and the OS thread name are left unchanged).<br /> | 778 | When Lanes is initialized by the first <a href="#initialization"><tt>lanes.configure()</tt></a> call, <tt>"main"</tt> is stored in the registry in the same fashion (but <tt>decoda_name</tt> and the OS thread name are left unchanged).<br /> |
780 | The lane also has a method <tt>lane:get_debug_threadname()</tt> that gives access to that name from the caller side (returns <tt>"<unnamed>"</tt> if unset, <tt>"<closed>"</tt> if the internal Lua state is closed). | 779 | The lane also has a method <tt>lane:get_debug_threadname()</tt> that gives access to that name from the caller side (returns <tt>"<unnamed>"</tt> if unset, <tt>"<closed>"</tt> if the internal Lua state is closed). |
781 | </p> | 780 | </p> |
782 | 781 | ||
783 | <p> | 782 | <p> |
784 | 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. | 783 | 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. |
785 | 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: | 784 | 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: |
786 | 785 | ||
787 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> | 786 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> |
@@ -823,7 +822,7 @@ | |||
823 | </table> | 822 | </table> |
824 | <p> | 823 | <p> |
825 | Besides setting a default priority in the generator <a href="#generator_settings">settings</a>, each thread can change its own priority at will. This is also true for the main Lua state. | 824 | Besides setting a default priority in the generator <a href="#generator_settings">settings</a>, each thread can change its own priority at will. This is also true for the main Lua state. |
826 | <br/> | 825 | <br /> |
827 | The priority must be in the range <tt>[-3,+3]</tt>. | 826 | The priority must be in the range <tt>[-3,+3]</tt>. |
828 | </p> | 827 | </p> |
829 | 828 | ||
@@ -886,53 +885,53 @@ | |||
886 | </td> | 885 | </td> |
887 | </tr> | 886 | </tr> |
888 | <tr> | 887 | <tr> |
889 | <td/> | 888 | <td /> |
890 | <td> | 889 | <td> |
891 | <tt> | 890 | <tt> |
892 | "running" | 891 | "running" |
893 | </tt> | 892 | </tt> |
894 | </td> | 893 | </td> |
895 | <td/> | 894 | <td /> |
896 | <td> | 895 | <td> |
897 | running, not suspended on a <a href="#lindas">Linda</a> call. | 896 | running, not suspended on a <a href="#lindas">Linda</a> call. |
898 | </td> | 897 | </td> |
899 | </tr> | 898 | </tr> |
900 | <tr> | 899 | <tr> |
901 | <td/> | 900 | <td /> |
902 | <td> | 901 | <td> |
903 | <tt>"waiting"</tt> | 902 | <tt>"waiting"</tt> |
904 | </td> | 903 | </td> |
905 | <td/> | 904 | <td /> |
906 | <td> | 905 | <td> |
907 | waiting at a <a href="#lindas">Linda</a> <tt>:receive()</tt> or <tt>:send()</tt> | 906 | waiting at a <a href="#lindas">Linda</a> <tt>:receive()</tt> or <tt>:send()</tt> |
908 | </td> | 907 | </td> |
909 | </tr> | 908 | </tr> |
910 | <tr> | 909 | <tr> |
911 | <td/> | 910 | <td /> |
912 | <td> | 911 | <td> |
913 | <tt>"done"</tt> | 912 | <tt>"done"</tt> |
914 | </td> | 913 | </td> |
915 | <td/> | 914 | <td /> |
916 | <td> | 915 | <td> |
917 | finished executing (results are ready) | 916 | finished executing (results are ready) |
918 | </td> | 917 | </td> |
919 | </tr> | 918 | </tr> |
920 | <tr> | 919 | <tr> |
921 | <td/> | 920 | <td /> |
922 | <td> | 921 | <td> |
923 | <tt>"error"</tt> | 922 | <tt>"error"</tt> |
924 | </td> | 923 | </td> |
925 | <td/> | 924 | <td /> |
926 | <td> | 925 | <td> |
927 | met an error (reading results will propagate it) | 926 | met an error (reading results will propagate it) |
928 | </td> | 927 | </td> |
929 | </tr> | 928 | </tr> |
930 | <tr> | 929 | <tr> |
931 | <td/> | 930 | <td /> |
932 | <td> | 931 | <td> |
933 | <tt>"cancelled"</tt> | 932 | <tt>"cancelled"</tt> |
934 | </td> | 933 | </td> |
935 | <td/> | 934 | <td /> |
936 | <td> | 935 | <td> |
937 | received <a href="#cancelling">cancellation</a> and finished itself. | 936 | received <a href="#cancelling">cancellation</a> and finished itself. |
938 | </td> | 937 | </td> |
@@ -959,7 +958,7 @@ | |||
959 | 958 | ||
960 | <p> | 959 | <p> |
961 | Only available if lane tracking is enabled by setting <a href="#track_lanes"><tt>track_lanes</tt></a>. | 960 | Only available if lane tracking is enabled by setting <a href="#track_lanes"><tt>track_lanes</tt></a>. |
962 | <br/> | 961 | <br /> |
963 | Returns an array table where each entry is a table containing a lane's name and status. Returns <tt>nil</tt> if no lane is running. | 962 | Returns an array table where each entry is a table containing a lane's name and status. Returns <tt>nil</tt> if no lane is running. |
964 | </p> | 963 | </p> |
965 | 964 | ||
@@ -982,7 +981,7 @@ | |||
982 | 981 | ||
983 | <p> | 982 | <p> |
984 | Makes sure lane has finished, and gives its first (maybe only) return value. Other return values will be available in other <tt>lane_h</tt> indices. | 983 | Makes sure lane has finished, and gives its first (maybe only) return value. Other return values will be available in other <tt>lane_h</tt> indices. |
985 | <br/> | 984 | <br /> |
986 | If the lane ended in an error, it is propagated to master state at this place. | 985 | If the lane ended in an error, it is propagated to master state at this place. |
987 | </p> | 986 | </p> |
988 | 987 | ||
@@ -991,14 +990,14 @@ | |||
991 | </pre></td></tr></table> | 990 | </pre></td></tr></table> |
992 | 991 | ||
993 | <p> | 992 | <p> |
994 | <tt>timeout</tt> is an optional number >= 0 (the default if unspecified).<br/> | 993 | <tt>timeout</tt> is an optional number >= 0 (the default if unspecified).<br /> |
995 | Waits until the lane finishes, or <tt>timeout</tt> seconds have passed.<br/> | 994 | Waits until the lane finishes, or <tt>timeout</tt> seconds have passed.<br /> |
996 | Unlike in reading the results in table fashion, errors are not propagated.<br/> | 995 | Unlike in reading the results in table fashion, errors are not propagated.<br /> |
997 | Possible return values are: | 996 | Possible return values are: |
998 | <ul> | 997 | <ul> |
999 | <li><tt>nil, "timeout"</tt> on timeout.</li> | 998 | <li><tt>nil, "timeout"</tt> on timeout.</li> |
1000 | <li> | 999 | <li> |
1001 | <tt>nil,err,stack_tbl</tt> if the lane hit an error. The contents of <tt>stack_tbl</tt> change with <a href="#.error_trace_level"><tt>error_trace_level</tt></a>.<br/> | 1000 | <tt>nil,err,stack_tbl</tt> if the lane hit an error. The contents of <tt>stack_tbl</tt> change with <a href="#.error_trace_level"><tt>error_trace_level</tt></a>.<br /> |
1002 | <ul> | 1001 | <ul> |
1003 | <li><tt>"minimal"</tt>: <tt>stack_tbl</tt> is <tt>nil</tt>.</li> | 1002 | <li><tt>"minimal"</tt>: <tt>stack_tbl</tt> is <tt>nil</tt>.</li> |
1004 | <li><tt>"basic"</tt>: <tt>stack_tbl</tt> is an array of <tt>"<filename>:<line>"</tt> strings. You can use <tt>table.concat()</tt> to format it to your liking (or just ignore it).</li> | 1003 | <li><tt>"basic"</tt>: <tt>stack_tbl</tt> is an array of <tt>"<filename>:<line>"</tt> strings. You can use <tt>table.concat()</tt> to format it to your liking (or just ignore it).</li> |
@@ -1012,7 +1011,7 @@ | |||
1012 | </p> | 1011 | </p> |
1013 | 1012 | ||
1014 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1013 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1015 | local lanes = require "lanes".configure() | 1014 | local lanes = require "lanes" |
1016 | 1015 | ||
1017 | f = lanes.gen(function() error "!!!" end) | 1016 | f = lanes.gen(function() error "!!!" end) |
1018 | a = f(1) | 1017 | a = f(1) |
@@ -1030,7 +1029,7 @@ | |||
1030 | </p> | 1029 | </p> |
1031 | 1030 | ||
1032 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1031 | <table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1033 | local lanes = require "lanes".configure() | 1032 | local lanes = require "lanes" |
1034 | 1033 | ||
1035 | local sync_linda = lanes.linda() | 1034 | local sync_linda = lanes.linda() |
1036 | f = lanes.gen(function() dostuff() sync_linda:send("done", true) end) | 1035 | f = lanes.gen(function() dostuff() sync_linda:send("done", true) end) |
@@ -1053,25 +1052,25 @@ | |||
1053 | 1052 | ||
1054 | <p> | 1053 | <p> |
1055 | <tt>timeout</tt> is an optional number >= 0. Defaults to 0 if left unspecified or <tt>nil</tt>. | 1054 | <tt>timeout</tt> is an optional number >= 0. Defaults to 0 if left unspecified or <tt>nil</tt>. |
1056 | <br/> | 1055 | <br /> |
1057 | <tt>cancel()</tt> sends a cancellation request to the lane. | 1056 | <tt>cancel()</tt> sends a cancellation request to the lane. |
1058 | <br/> | 1057 | <br /> |
1059 | First argument is a <tt>mode</tt> can be one of <tt>"hard"</tt>, <tt>"soft"</tt>, <tt>"call"</tt>, <tt>"ret"</tt>, <tt>"line"</tt>, <tt>"count"</tt>. | 1058 | First argument is a <tt>mode</tt> can be one of <tt>"hard"</tt>, <tt>"soft"</tt>, <tt>"call"</tt>, <tt>"ret"</tt>, <tt>"line"</tt>, <tt>"count"</tt>. |
1060 | If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>. | 1059 | If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>. |
1061 | If <tt>wake_lane</tt> is <tt>true</tt>, the lane is also signalled so that execution returns from any pending <a href="#lindas">Linda</a> operation. <a href="#lindas">Linda</a> operations detecting the cancellation request return <tt>lanes.cancel_error</tt>. | 1060 | If <tt>wake_lane</tt> is <tt>true</tt>, the lane is also signalled so that execution returns from any pending <a href="#lindas">Linda</a> operation. <a href="#lindas">Linda</a> operations detecting the cancellation request return <tt>lanes.cancel_error</tt>. |
1062 | </p> | 1061 | </p> |
1063 | <p> | 1062 | <p> |
1064 | If <tt>mode</tt> is <tt>"soft"</tt>, cancellation will only cause <tt>cancel_test()</tt> to return <tt>true</tt>, so that the lane can cleanup manually.<br/> | 1063 | If <tt>mode</tt> is <tt>"soft"</tt>, cancellation will only cause <tt>cancel_test()</tt> to return <tt>true</tt>, so that the lane can cleanup manually.<br /> |
1065 | </p> | 1064 | </p> |
1066 | <p> | 1065 | <p> |
1067 | If <tt>mode</tt> is <tt>"hard"</tt>, waits for the request to be processed, or a timeout to occur. <a href="#lindas">Linda</a> operations detecting the cancellation request will raise a special cancellation error (meaning they won't return in that case).<br/> | 1066 | If <tt>mode</tt> is <tt>"hard"</tt>, waits for the request to be processed, or a timeout to occur. <a href="#lindas">Linda</a> operations detecting the cancellation request will raise a special cancellation error (meaning they won't return in that case).<br /> |
1068 | <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified. | 1067 | <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified. |
1069 | </p> | 1068 | </p> |
1070 | <p> | 1069 | <p> |
1071 | Other values of <tt>mode</tt> will asynchronously install the corresponding hook, then behave as <tt>"hard"</tt>. | 1070 | Other values of <tt>mode</tt> will asynchronously install the corresponding hook, then behave as <tt>"hard"</tt>. |
1072 | </p> | 1071 | </p> |
1073 | <p> | 1072 | <p> |
1074 | Returns <tt>true, lane_h.status</tt> if lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within <tt>timeout_secs</tt> timeout period.<br/> | 1073 | Returns <tt>true, lane_h.status</tt> if lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within <tt>timeout_secs</tt> timeout period.<br /> |
1075 | Returns <tt>false, "timeout"</tt> otherwise. | 1074 | Returns <tt>false, "timeout"</tt> otherwise. |
1076 | </p> | 1075 | </p> |
1077 | <p> | 1076 | <p> |
@@ -1079,11 +1078,11 @@ | |||
1079 | </p> | 1078 | </p> |
1080 | <p> | 1079 | <p> |
1081 | Cancellation is tested <u>before</u> going to sleep in <tt>receive()</tt> or <tt>send()</tt> calls and after executing <tt>cancelstep</tt> Lua statements. A pending <tt>receive()</tt>or <tt>send()</tt> call is awakened. | 1080 | Cancellation is tested <u>before</u> going to sleep in <tt>receive()</tt> or <tt>send()</tt> calls and after executing <tt>cancelstep</tt> Lua statements. A pending <tt>receive()</tt>or <tt>send()</tt> call is awakened. |
1082 | <br/> | 1081 | <br /> |
1083 | This means the execution of the lane will resume although the operation has not completed, to give the lane a chance to detect cancellation (even in the case the code waits on a <a href="#lindas">Linda</a> with infinite timeout). | 1082 | This means the execution of the lane will resume although the operation has not completed, to give the lane a chance to detect cancellation (even in the case the code waits on a <a href="#lindas">Linda</a> with infinite timeout). |
1084 | <br/> | 1083 | <br /> |
1085 | The code should be able to handle this situation appropriately if required (in other words, it should gracefully handle the fact that it didn't receive the expected values). | 1084 | The code should be able to handle this situation appropriately if required (in other words, it should gracefully handle the fact that it didn't receive the expected values). |
1086 | <br/> | 1085 | <br /> |
1087 | It is also possible to manually test for cancel requests with <tt>cancel_test()</tt>. | 1086 | It is also possible to manually test for cancel requests with <tt>cancel_test()</tt>. |
1088 | </p> | 1087 | </p> |
1089 | 1088 | ||
@@ -1146,7 +1145,7 @@ | |||
1146 | </p> | 1145 | </p> |
1147 | 1146 | ||
1148 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1147 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1149 | local lanes = require "lanes".configure() | 1148 | local lanes = require "lanes" |
1150 | 1149 | ||
1151 | local linda = lanes.linda("my linda") | 1150 | local linda = lanes.linda("my linda") |
1152 | 1151 | ||
@@ -1201,8 +1200,8 @@ | |||
1201 | </pre></td></tr></table> | 1200 | </pre></td></tr></table> |
1202 | 1201 | ||
1203 | <p> | 1202 | <p> |
1204 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br/> | 1203 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br /> |
1205 | 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/> | 1204 | 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 /> |
1206 | 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>. | 1205 | 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>. |
1207 | </p> | 1206 | </p> |
1208 | 1207 | ||
@@ -1211,9 +1210,9 @@ | |||
1211 | </pre></td></tr></table> | 1210 | </pre></td></tr></table> |
1212 | 1211 | ||
1213 | <p> | 1212 | <p> |
1214 | 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/> | 1213 | 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 /> |
1215 | A limit of 0 is allowed to block everything.<br/> | 1214 | A limit of 0 is allowed to block everything.<br /> |
1216 | 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/> | 1215 | 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 /> |
1217 | </p> | 1216 | </p> |
1218 | 1217 | ||
1219 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1218 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
@@ -1221,7 +1220,7 @@ | |||
1221 | </pre></td></tr></table> | 1220 | </pre></td></tr></table> |
1222 | 1221 | ||
1223 | <p> | 1222 | <p> |
1224 | 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/> | 1223 | 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 /> |
1225 | 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. | 1224 | 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. |
1226 | </p> | 1225 | </p> |
1227 | 1226 | ||
@@ -1231,8 +1230,8 @@ | |||
1231 | </p> | 1230 | </p> |
1232 | 1231 | ||
1233 | <p> | 1232 | <p> |
1234 | If no data is provided after the key, <tt>send()</tt> raises an error.<br/> | 1233 | If no data is provided after the key, <tt>send()</tt> raises an error.<br /> |
1235 | 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/> | 1234 | 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 /> |
1236 | <tt>send()</tt> return values can be: | 1235 | <tt>send()</tt> return values can be: |
1237 | <ul> | 1236 | <ul> |
1238 | <li><tt>true</tt> on success.</li> | 1237 | <li><tt>true</tt> on success.</li> |
@@ -1280,19 +1279,19 @@ | |||
1280 | </pre></td></tr></table> | 1279 | </pre></td></tr></table> |
1281 | 1280 | ||
1282 | <p> | 1281 | <p> |
1283 | The table access methods are for accessing a slot without queuing or consuming. They can be used for making shared tables of storage among the lanes.<br/> | 1282 | The table access methods are for accessing a slot without queuing or consuming. They can be used for making shared tables of storage among the lanes.<br /> |
1284 | Writing to a slot never blocks because it ignores the limit. It overwrites existing value and clears any possible queued entries.<br/> | 1283 | Writing to a slot never blocks because it ignores the limit. It overwrites existing value and clears any possible queued entries.<br /> |
1285 | Reading doesn't block either because <tt>get()</tt> returns whatever is available (which can be nothing), up to the specified count.<br/> | 1284 | Reading doesn't block either because <tt>get()</tt> returns whatever is available (which can be nothing), up to the specified count.<br /> |
1286 | Table access and <tt>send()</tt>/<tt>receive()</tt> can be used together; reading a slot essentially peeks the next outcoming value of a queue. | 1285 | Table access and <tt>send()</tt>/<tt>receive()</tt> can be used together; reading a slot essentially peeks the next outcoming value of a queue. |
1287 | </p> | 1286 | </p> |
1288 | 1287 | ||
1289 | <p> | 1288 | <p> |
1290 | <tt>set()</tt> signals the Linda for write if a value is stored. If nothing special happens, <tt>set() </tt>returns nothing.<br/> | 1289 | <tt>set()</tt> signals the Linda for write if a value is stored. If nothing special happens, <tt>set() </tt>returns nothing.<br /> |
1291 | If the key was full but the new data count of the key after <tt>set()</tt> is below its limit, <tt>set()</tt> returns <tt>true</tt> and the Linda is also signaled for read so that <tt>send()</tt>-blocked threads are awakened. | 1290 | If the key was full but the new data count of the key after <tt>set()</tt> is below its limit, <tt>set()</tt> returns <tt>true</tt> and the Linda is also signaled for read so that <tt>send()</tt>-blocked threads are awakened. |
1292 | </p> | 1291 | </p> |
1293 | 1292 | ||
1294 | <p> | 1293 | <p> |
1295 | <tt>set()</tt> can write several values at the specified key, writing <tt>nil</tt> values is now possible, and clearing the contents at the specified key is done by not providing any value.<br/> | 1294 | <tt>set()</tt> can write several values at the specified key, writing <tt>nil</tt> values is now possible, and clearing the contents at the specified key is done by not providing any value.<br /> |
1296 | Also, <tt>get()</tt> can read several values at once. If the key contains no data, <tt>get()</tt> returns no value. This can be used to separate the case when reading stored <tt>nil</tt> values. | 1295 | Also, <tt>get()</tt> can read several values at once. If the key contains no data, <tt>get()</tt> returns no value. This can be used to separate the case when reading stored <tt>nil</tt> values. |
1297 | </p> | 1296 | </p> |
1298 | 1297 | ||
@@ -1305,10 +1304,10 @@ | |||
1305 | </pre></td></tr></table> | 1304 | </pre></td></tr></table> |
1306 | 1305 | ||
1307 | <p> | 1306 | <p> |
1308 | Returns some information about the contents of the Linda.<br/> | 1307 | Returns some information about the contents of the Linda.<br /> |
1309 | If no key is specified, and the Linda is empty, returns nothing.<br/> | 1308 | If no key is specified, and the Linda is empty, returns nothing.<br /> |
1310 | If no key is specified, and the Linda is not empty, returns a table of key/count pairs that counts the number of items in each of the exiting keys of the Linda. This count can be 0 if the key has been used but is empty.<br/> | 1309 | If no key is specified, and the Linda is not empty, returns a table of key/count pairs that counts the number of items in each of the exiting keys of the Linda. This count can be 0 if the key has been used but is empty.<br /> |
1311 | If a single key is specified, returns the number of pending items, or nothing if the key is unknown.<br/> | 1310 | If a single key is specified, returns the number of pending items, or nothing if the key is unknown.<br /> |
1312 | If more than one key is specified, return a table of key/count pairs for the known keys. | 1311 | If more than one key is specified, return a table of key/count pairs for the known keys. |
1313 | </p> | 1312 | </p> |
1314 | 1313 | ||
@@ -1317,7 +1316,7 @@ | |||
1317 | </pre></td></tr></table> | 1316 | </pre></td></tr></table> |
1318 | 1317 | ||
1319 | <p> | 1318 | <p> |
1320 | Returns a table describing the full contents of a Linda, or <tt>nil</tt> if the Linda wasn't used yet.<br/> | 1319 | Returns a table describing the full contents of a Linda, or <tt>nil</tt> if the Linda wasn't used yet.<br /> |
1321 | If Decoda support is enabled with <tt>HAVE_DECODA_SUPPORT()</tt>, <a Linda metatable contain a <tt>__towatch</tt> special function that generates a similar table used for debug display. | 1320 | If Decoda support is enabled with <tt>HAVE_DECODA_SUPPORT()</tt>, <a Linda metatable contain a <tt>__towatch</tt> special function that generates a similar table used for debug display. |
1322 | </p> | 1321 | </p> |
1323 | 1322 | ||
@@ -1327,8 +1326,8 @@ | |||
1327 | 1326 | ||
1328 | <p> | 1327 | <p> |
1329 | Signals the Linda so that lanes waiting for read, write, or both, wake up. | 1328 | Signals the Linda so that lanes waiting for read, write, or both, wake up. |
1330 | All Linda operations (including <tt>get()</tt> and <tt>set()</tt>) will return <tt>lanes.cancel_error</tt> as when the calling lane is <a href="#cancelling">soft-cancelled</a> as long as the Linda is marked as cancelled.<br/> | 1329 | All Linda operations (including <tt>get()</tt> and <tt>set()</tt>) will return <tt>lanes.cancel_error</tt> as when the calling lane is <a href="#cancelling">soft-cancelled</a> as long as the Linda is marked as cancelled.<br /> |
1331 | <tt>"none"</tt> reset the Linda's cancel status, but doesn't signal it.<br/> | 1330 | <tt>"none"</tt> reset the Linda's cancel status, but doesn't signal it.<br /> |
1332 | If not void, the lane's cancel status overrides the Linda's cancel status. | 1331 | If not void, the lane's cancel status overrides the Linda's cancel status. |
1333 | </p> | 1332 | </p> |
1334 | 1333 | ||
@@ -1343,12 +1342,12 @@ | |||
1343 | <h3 id="keepers">Granularity of using Lindas</h3> | 1342 | <h3 id="keepers">Granularity of using Lindas</h3> |
1344 | 1343 | ||
1345 | <p> | 1344 | <p> |
1346 | A Linda is a gateway to read and write data inside some hidden Lua states, called keeper states. Lindas are hashed to a fixed number of keeper states, which are a locking entity.<br/> | 1345 | A Linda is a gateway to read and write data inside some hidden Lua states, called keeper states. Lindas are hashed to a fixed number of keeper states, which are a locking entity.<br /> |
1347 | The data sent through a Linda is stored inside the associated keeper state in a Lua table where each Linda slot is the key to another table containing a FIFO for that slot.<br/> | 1346 | The data sent through a Linda is stored inside the associated keeper state in a Lua table where each Linda slot is the key to another table containing a FIFO for that slot.<br /> |
1348 | Each keeper state is associated with an OS mutex, to prevent concurrent access to the keeper state. The Linda itself uses two signals to be made aware of operations occuring on it.<br/> | 1347 | Each keeper state is associated with an OS mutex, to prevent concurrent access to the keeper state. The Linda itself uses two signals to be made aware of operations occuring on it.<br /> |
1349 | Whenever Lua code reads from or writes to a Linda, the mutex is acquired. If Linda limits don't block the operation, it is fulfilled, then the mutex is released.<br/> | 1348 | Whenever Lua code reads from or writes to a Linda, the mutex is acquired. If Linda limits don't block the operation, it is fulfilled, then the mutex is released.<br /> |
1350 | If the Linda has to block, the mutex is released and the OS thread sleeps, waiting for a Linda operation to be signalled. When an operation occurs on the same Linda, possibly fufilling the condition, or a timeout expires, the thread wakes up.<br/> | 1349 | If the Linda has to block, the mutex is released and the OS thread sleeps, waiting for a Linda operation to be signalled. When an operation occurs on the same Linda, possibly fufilling the condition, or a timeout expires, the thread wakes up.<br /> |
1351 | If the thread is woken but the condition is not yet fulfilled, it goes back to sleep, until the timeout expires.<br/> | 1350 | If the thread is woken but the condition is not yet fulfilled, it goes back to sleep, until the timeout expires.<br /> |
1352 | When a lane is cancelled, the signal it is waiting on (if any) is signalled. In that case, the Linda operation will return <tt>lanes.cancel_error</tt>. | 1351 | When a lane is cancelled, the signal it is waiting on (if any) is signalled. In that case, the Linda operation will return <tt>lanes.cancel_error</tt>. |
1353 | </p> | 1352 | </p> |
1354 | 1353 | ||
@@ -1464,7 +1463,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1464 | 1463 | ||
1465 | <p> | 1464 | <p> |
1466 | A very simple way of sleeping when nothing else is available. Is implemented by attempting to read some data in an unused channel of the internal <a href="#lindas">Linda</a> used for timers (this <a href="#lindas">Linda</a> exists even when timers aren't enabled). | 1465 | A very simple way of sleeping when nothing else is available. Is implemented by attempting to read some data in an unused channel of the internal <a href="#lindas">Linda</a> used for timers (this <a href="#lindas">Linda</a> exists even when timers aren't enabled). |
1467 | Default duration is 0, which should only cause a thread context switch.<br/> | 1466 | Default duration is 0, which should only cause a thread context switch.<br /> |
1468 | Return values should always be <tt>nil, "timeout"</tt> (or <tt>nil, lanes.cancel_error</tt> in case of interruption). | 1467 | Return values should always be <tt>nil, "timeout"</tt> (or <tt>nil, lanes.cancel_error</tt> in case of interruption). |
1469 | </p> | 1468 | </p> |
1470 | 1469 | ||
@@ -1494,9 +1493,9 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1494 | 1493 | ||
1495 | <p> | 1494 | <p> |
1496 | The generated function acquires M tokens from the N available, or releases them if the value is negative. The acquiring call will suspend the lane, if necessary. Use <tt>M=N=1</tt> for a critical section lock (only one lane allowed to enter). | 1495 | The generated function acquires M tokens from the N available, or releases them if the value is negative. The acquiring call will suspend the lane, if necessary. Use <tt>M=N=1</tt> for a critical section lock (only one lane allowed to enter). |
1497 | <br/> | 1496 | <br /> |
1498 | When passsing <tt>"try"</tt> as second argument when acquiring, then <tt>lock_func</tt> operates on the <a href="#lindas">Linda</a> with a timeout of 0 to emulate a TryLock() operation. If locking fails, <tt>lock_func</tt> returns <tt>false</tt>. <tt>"try"</tt> is ignored when releasing (as it it not expected to ever have to wait unless the acquisition/release pairs are not properly matched). | 1497 | When passsing <tt>"try"</tt> as second argument when acquiring, then <tt>lock_func</tt> operates on the <a href="#lindas">Linda</a> with a timeout of 0 to emulate a TryLock() operation. If locking fails, <tt>lock_func</tt> returns <tt>false</tt>. <tt>"try"</tt> is ignored when releasing (as it it not expected to ever have to wait unless the acquisition/release pairs are not properly matched). |
1499 | <br/> | 1498 | <br /> |
1500 | Upon successful lock/unlock, <tt>lock_func</tt> returns <tt>true</tt> (always the case when block-waiting for completion). | 1499 | Upon successful lock/unlock, <tt>lock_func</tt> returns <tt>true</tt> (always the case when block-waiting for completion). |
1501 | </p> | 1500 | </p> |
1502 | 1501 | ||
@@ -1591,15 +1590,15 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1591 | 1590 | ||
1592 | <p> | 1591 | <p> |
1593 | 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. | 1592 | 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. |
1594 | <br/> | 1593 | <br /> |
1595 | 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. | 1594 | 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. |
1596 | <br/> | 1595 | <br /> |
1597 | 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. | 1596 | 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. |
1598 | <br/> | 1597 | <br /> |
1599 | 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). | 1598 | 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). |
1600 | <br/> | 1599 | <br /> |
1601 | 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. | 1600 | 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. |
1602 | <br/> | 1601 | <br /> |
1603 | 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). | 1602 | 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). |
1604 | </p> | 1603 | </p> |
1605 | 1604 | ||
@@ -1659,8 +1658,8 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1659 | <h3 id="clonable_userdata">Clonable full userdata in your own apps</h3> | 1658 | <h3 id="clonable_userdata">Clonable full userdata in your own apps</h3> |
1660 | <p> | 1659 | <p> |
1661 | An alternative way of passing full userdata across lanes uses a new <tt>__lanesclone</tt> metamethod. | 1660 | An alternative way of passing full userdata across lanes uses a new <tt>__lanesclone</tt> metamethod. |
1662 | When a deep userdata is cloned, Lanes calls <tt>__lanesclone</tt> once, in the context of the source lane.<br/> | 1661 | When a deep userdata is cloned, Lanes calls <tt>__lanesclone</tt> once, in the context of the source lane.<br /> |
1663 | The call receives the clone and original as light userdata, plus the actual userdata size, as in <tt>clone:__lanesclone(original,size)</tt>, and should perform the actual cloning.<br/> | 1662 | The call receives the clone and original as light userdata, plus the actual userdata size, as in <tt>clone:__lanesclone(original,size)</tt>, and should perform the actual cloning.<br /> |
1664 | A typical implementation would look like: | 1663 | A typical implementation would look like: |
1665 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1664 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1666 | static int clonable_lanesclone(lua_State* L) | 1665 | static int clonable_lanesclone(lua_State* L) |
@@ -1686,7 +1685,7 @@ static int clonable_lanesclone(lua_State* L) | |||
1686 | </p> | 1685 | </p> |
1687 | 1686 | ||
1688 | <p> | 1687 | <p> |
1689 | <b>NOTE</b>: In the event the source userdata has uservalues, it is not necessary to create them for the clone, Lanes will handle their cloning.<br/> | 1688 | <b>NOTE</b>: In the event the source userdata has uservalues, it is not necessary to create them for the clone, Lanes will handle their cloning.<br /> |
1690 | Of course, more complex objects may require smarter cloning behavior than a simple <tt>memcpy</tt>. Also, the module initialisation code should make each metatable accessible from the module table itself as in: | 1689 | Of course, more complex objects may require smarter cloning behavior than a simple <tt>memcpy</tt>. Also, the module initialisation code should make each metatable accessible from the module table itself as in: |
1691 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1690 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1692 | int luaopen_deep_test(lua_State* L) | 1691 | int luaopen_deep_test(lua_State* L) |
@@ -1768,9 +1767,9 @@ static MyDeepFactory g_MyDeepFactory; | |||
1768 | </p> | 1767 | </p> |
1769 | 1768 | ||
1770 | <p> | 1769 | <p> |
1771 | Deep userdata in transit inside <a href="#keepers">Keeper states</a> (sent in a <a href="#lindas">Linda</a> but not yet consumed) don't call <tt>deleteDeepObjectInternal</tt> and aren't considered by reference counting. The rationale is the following:<br/> | 1770 | Deep userdata in transit inside <a href="#keepers">Keeper states</a> (sent in a <a href="#lindas">Linda</a> but not yet consumed) don't call <tt>deleteDeepObjectInternal</tt> and aren't considered by reference counting. The rationale is the following:<br /> |
1772 | If some non-keeper state holds a deep userdata for some deep object, then even if the keeper collects its own deep userdata, it shouldn't be cleaned up since the refcount is not 0.<br/> | 1771 | If some non-keeper state holds a deep userdata for some deep object, then even if the keeper collects its own deep userdata, it shouldn't be cleaned up since the refcount is not 0.<br /> |
1773 | OTOH, if a keeper state holds the last deep userdata for some deep object, then no lane can do actual work with it. Deep userdata's <tt>factory()</tt> interface is never accessed from a keeper state.<br/> | 1772 | OTOH, if a keeper state holds the last deep userdata for some deep object, then no lane can do actual work with it. Deep userdata's <tt>factory()</tt> interface is never accessed from a keeper state.<br /> |
1774 | Therefore, Lanes can just call <tt>deleteDeepObjectInternal</tt> when the last non-keeper-held deep userdata is collected, as long as it doesn't do the same in a keeper state after that, since any remaining deep userdata in <a href="#keepers">Keeper states</a> now hold stale pointers. | 1773 | Therefore, Lanes can just call <tt>deleteDeepObjectInternal</tt> when the last non-keeper-held deep userdata is collected, as long as it doesn't do the same in a keeper state after that, since any remaining deep userdata in <a href="#keepers">Keeper states</a> now hold stale pointers. |
1775 | </p> | 1774 | </p> |
1776 | 1775 | ||
diff --git a/src/lanes.lua b/src/lanes.lua index 07792b6..d890adf 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -758,7 +758,7 @@ local configure = function(settings_) | |||
758 | -- Configure called so remove metatable from lanes | 758 | -- Configure called so remove metatable from lanes |
759 | lanesMeta.__metatable = nil -- unprotect the metatable | 759 | lanesMeta.__metatable = nil -- unprotect the metatable |
760 | setmetatable(lanes, nil) -- remove it | 760 | setmetatable(lanes, nil) -- remove it |
761 | lanes.configure = nil -- no need to call configure() ever again | 761 | lanes.configure = function() return lanes end -- no need to configure anything again |
762 | 762 | ||
763 | -- now we can configure Lanes core | 763 | -- now we can configure Lanes core |
764 | local settings = core.configure and core.configure(params_checker(settings_)) or core.settings | 764 | local settings = core.configure and core.configure(params_checker(settings_)) or core.settings |
diff --git a/tests/appendud.lua b/tests/appendud.lua index d0efb26..f510c8b 100644 --- a/tests/appendud.lua +++ b/tests/appendud.lua | |||
@@ -7,7 +7,6 @@ | |||
7 | -- Needs Lanes >= 2.0.3 | 7 | -- Needs Lanes >= 2.0.3 |
8 | -- | 8 | -- |
9 | local lanes = require "lanes" | 9 | local lanes = require "lanes" |
10 | lanes.configure() | ||
11 | 10 | ||
12 | local _tab = { | 11 | local _tab = { |
13 | beginupdate = function (this) print('tab.beginupdate') end; | 12 | beginupdate = function (this) print('tab.beginupdate') end; |
diff --git a/tests/atomic.lua b/tests/atomic.lua index 12bdf02..2de8f52 100644 --- a/tests/atomic.lua +++ b/tests/atomic.lua | |||
@@ -5,7 +5,6 @@ | |||
5 | -- | 5 | -- |
6 | 6 | ||
7 | local lanes = require "lanes" | 7 | local lanes = require "lanes" |
8 | lanes.configure() | ||
9 | 8 | ||
10 | local linda= lanes.linda() | 9 | local linda= lanes.linda() |
11 | local key= "$" | 10 | local key= "$" |
diff --git a/tests/basic.lua b/tests/basic.lua index cad3764..bdad44c 100644 --- a/tests/basic.lua +++ b/tests/basic.lua | |||
@@ -7,7 +7,8 @@ | |||
7 | -- - ... | 7 | -- - ... |
8 | -- | 8 | -- |
9 | local config = { with_timers = false, strip_functions = false, internal_allocator = "libc"} | 9 | local config = { with_timers = false, strip_functions = false, internal_allocator = "libc"} |
10 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config) | 10 | -- calling configure more than once should work (additional called are ignored) |
11 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() | ||
11 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) | 12 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) |
12 | local lanes = require_lanes_result_1 | 13 | local lanes = require_lanes_result_1 |
13 | 14 | ||
@@ -434,7 +435,7 @@ local function chunk2(linda) | |||
434 | assert(config.strip_functions and info.short_src=="?" or string.match(info.short_src, "^.*basic.lua$"), "bad info.short_src") | 435 | assert(config.strip_functions and info.short_src=="?" or string.match(info.short_src, "^.*basic.lua$"), "bad info.short_src") |
435 | -- These vary so let's not be picky (they're there..) | 436 | -- These vary so let's not be picky (they're there..) |
436 | -- | 437 | -- |
437 | assert(info.linedefined == 419, "bad linedefined") -- start of 'chunk2' | 438 | assert(info.linedefined == 420, "bad linedefined") -- start of 'chunk2' |
438 | assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' | 439 | assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' |
439 | assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' | 440 | assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' |
440 | local k,func= linda:receive("down") | 441 | local k,func= linda:receive("down") |
diff --git a/tests/cyclic.lua b/tests/cyclic.lua index 553d2a9..fd6d4a0 100644 --- a/tests/cyclic.lua +++ b/tests/cyclic.lua | |||
@@ -5,7 +5,6 @@ | |||
5 | -- | 5 | -- |
6 | 6 | ||
7 | local lanes = require "lanes" | 7 | local lanes = require "lanes" |
8 | lanes.configure() | ||
9 | 8 | ||
10 | local table_concat= assert(table.concat) | 9 | local table_concat= assert(table.concat) |
11 | 10 | ||
diff --git a/tests/deadlock.lua b/tests/deadlock.lua index c38ca13..bbbda8d 100644 --- a/tests/deadlock.lua +++ b/tests/deadlock.lua | |||
@@ -1,8 +1,10 @@ | |||
1 | -- this script tests the fix of a bug that could cause the mutex of a keeper state to remain locked | 1 | -- this script tests the fix of a bug that could cause the mutex of a keeper state to remain locked |
2 | -- see https://github.com/LuaLanes/lanes/commit/0cc1c9c9dcea5955f7dab921d9a2fff78c4e1729 | 2 | -- see https://github.com/LuaLanes/lanes/commit/0cc1c9c9dcea5955f7dab921d9a2fff78c4e1729 |
3 | 3 | ||
4 | local lanes = require('lanes').configure{with_timers=false} | 4 | local lanes = require "lanes" |
5 | local linda = lanes.linda "deadlock_linda" | 5 | |
6 | -- Lua 5.1 compatibility | ||
7 | local table_unpack = table.unpack or unpack | ||
6 | 8 | ||
7 | local SLEEP = function(...) | 9 | local SLEEP = function(...) |
8 | local k, v = lanes.sleep(...) | 10 | local k, v = lanes.sleep(...) |
@@ -14,27 +16,28 @@ print "let's begin" | |||
14 | local do_extra_stuff = true | 16 | local do_extra_stuff = true |
15 | 17 | ||
16 | if do_extra_stuff then | 18 | if do_extra_stuff then |
17 | -- just something to make send() succeed and receive() fail (any C function exposed by some module will do) | 19 | local linda = lanes.linda "deadlock_linda" |
18 | local payload = { lanes.require('socket').connect } | 20 | -- just something to make send() succeed and receive() fail |
19 | 21 | local payload = { io.flush } | |
20 | -- lane generator | 22 | |
21 | local g = lanes.gen('*', function() | 23 | -- lane generator. don't initialize "io" base library so that it is not known in the lane |
22 | set_debug_threadname( "deadlock_lane") | 24 | local g = lanes.gen('base,table', function() |
23 | -- wrapping inside pcall makes the Lanes module unaware that something went wrong | 25 | set_debug_threadname( "deadlock_lane") |
24 | print( "In lane 1:", table.unpack{ pcall( linda.receive, linda, 'tmp')}) | 26 | -- wrapping inside pcall makes the Lanes module unaware that something went wrong |
25 | -- with the bug not fixed, and non-recursive mutexes, we can hang here | 27 | print( "In lane 1:", table_unpack{ pcall( linda.receive, linda, 'tmp')}) |
26 | print( "In lane 2:", table.unpack{ pcall( linda.receive, linda, 'tmp')}) | 28 | -- with the bug not fixed, and non-recursive mutexes, we can hang here |
27 | -- return something out of the lane | 29 | print( "In lane 2:", table_unpack{ pcall( linda.receive, linda, 'tmp')}) |
28 | return 33, 55 | 30 | -- return something out of the lane |
29 | end) | 31 | return 33, 55 |
30 | 32 | end) | |
31 | -- send payload twice. succeeds because sending stores a function identification string in the linda's keeper state | 33 | |
32 | linda:send( 'tmp', payload, payload) | 34 | -- send payload twice. succeeds because sending stores a function identification string in the linda's keeper state |
33 | -- start the lane | 35 | linda:send( 'tmp', payload, payload) |
34 | local h = g() | 36 | -- start the lane |
35 | -- wait for lane completion | 37 | local h = g() |
36 | local err, stack = h:join() | 38 | -- wait for lane completion |
37 | print( 'result of lane execution', err, stack) | 39 | local err, stack = h:join() |
40 | print( 'result of lane execution', err, stack) | ||
38 | end | 41 | end |
39 | 42 | ||
40 | -- With the bug not fixed, the linda keeper's mutex is still acquired, | 43 | -- With the bug not fixed, the linda keeper's mutex is still acquired, |
diff --git a/tests/ehynes.lua b/tests/ehynes.lua index 9436c7d..cdcd5a5 100644 --- a/tests/ehynes.lua +++ b/tests/ehynes.lua | |||
@@ -2,7 +2,6 @@ | |||
2 | -- Test from <ehynes at dharmagaia.com> | 2 | -- Test from <ehynes at dharmagaia.com> |
3 | -- | 3 | -- |
4 | local lanes = require "lanes" | 4 | local lanes = require "lanes" |
5 | lanes.configure() | ||
6 | 5 | ||
7 | local SLEEP = function(...) | 6 | local SLEEP = function(...) |
8 | local k, v = lanes.sleep(...) | 7 | local k, v = lanes.sleep(...) |
diff --git a/tests/fibonacci.lua b/tests/fibonacci.lua index 0ff2f37..51e7137 100644 --- a/tests/fibonacci.lua +++ b/tests/fibonacci.lua | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | -- Need to say it's 'local' so it can be an upvalue | 13 | -- Need to say it's 'local' so it can be an upvalue |
14 | -- | 14 | -- |
15 | local lanes = require "lanes".configure() | 15 | local lanes = require "lanes" |
16 | 16 | ||
17 | local function WR(str) | 17 | local function WR(str) |
18 | io.stderr:write( str.."\n" ) | 18 | io.stderr:write( str.."\n" ) |
diff --git a/tests/hangtest.lua b/tests/hangtest.lua index 6a9f7aa..0e44451 100644 --- a/tests/hangtest.lua +++ b/tests/hangtest.lua | |||
@@ -3,7 +3,6 @@ | |||
3 | -- | 3 | -- |
4 | 4 | ||
5 | local lanes = require "lanes" | 5 | local lanes = require "lanes" |
6 | lanes.configure() | ||
7 | 6 | ||
8 | local function ret(b) | 7 | local function ret(b) |
9 | return b | 8 | return b |
diff --git a/tests/irayo_closure.lua b/tests/irayo_closure.lua index 3278d57..45189ec 100644 --- a/tests/irayo_closure.lua +++ b/tests/irayo_closure.lua | |||
@@ -11,7 +11,6 @@ e.g. { globals = { data = 1, func = function() useclosurehere() end } }" | |||
11 | ]] | 11 | ]] |
12 | 12 | ||
13 | local lanes = require "lanes" | 13 | local lanes = require "lanes" |
14 | lanes.configure() | ||
15 | 14 | ||
16 | local function testrun() | 15 | local function testrun() |
17 | assert( print ) | 16 | assert( print ) |
diff --git a/tests/irayo_recursive.lua b/tests/irayo_recursive.lua index fe722a3..88f4aab 100644 --- a/tests/irayo_recursive.lua +++ b/tests/irayo_recursive.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local lanes = require "lanes".configure() | 1 | local lanes = require "lanes" |
2 | -- | 2 | -- |
3 | -- Bugs filed by irayo Jul-2008 | 3 | -- Bugs filed by irayo Jul-2008 |
4 | -- | 4 | -- |
diff --git a/tests/launchtest.lua b/tests/launchtest.lua index f3a6740..16db242 100644 --- a/tests/launchtest.lua +++ b/tests/launchtest.lua | |||
@@ -46,7 +46,6 @@ for k,v in pairs( argtable(...) ) do | |||
46 | end | 46 | end |
47 | 47 | ||
48 | local lanes = require "lanes" | 48 | local lanes = require "lanes" |
49 | lanes.configure() | ||
50 | 49 | ||
51 | local g= lanes.gen( LIBS, function(i) | 50 | local g= lanes.gen( LIBS, function(i) |
52 | --io.stderr:write( i.."\t" ) | 51 | --io.stderr:write( i.."\t" ) |
diff --git a/tests/objects.lua b/tests/objects.lua index 7668e45..61c280d 100644 --- a/tests/objects.lua +++ b/tests/objects.lua | |||
@@ -5,7 +5,6 @@ | |||
5 | -- | 5 | -- |
6 | 6 | ||
7 | local lanes = require "lanes" | 7 | local lanes = require "lanes" |
8 | lanes.configure() | ||
9 | 8 | ||
10 | local linda= lanes.linda() | 9 | local linda= lanes.linda() |
11 | 10 | ||
diff --git a/tests/parallel_os_calls.lua b/tests/parallel_os_calls.lua index 7e7de26..8030d4c 100644 --- a/tests/parallel_os_calls.lua +++ b/tests/parallel_os_calls.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local lanes = require "lanes".configure() | 1 | local lanes = require "lanes" |
2 | print( os.date()) | 2 | print( os.date()) |
3 | local linda = lanes.linda() | 3 | local linda = lanes.linda() |
4 | local l1 = lanes.gen("os,base", function() print "start sleeping" linda:receive(3, "null") print("finished_sleeping " .. os.date()) return true end)() | 4 | local l1 = lanes.gen("os,base", function() print "start sleeping" linda:receive(3, "null") print("finished_sleeping " .. os.date()) return true end)() |
diff --git a/tests/pingpong.lua b/tests/pingpong.lua index fdc60a6..3498f49 100644 --- a/tests/pingpong.lua +++ b/tests/pingpong.lua | |||
@@ -1,4 +1,4 @@ | |||
1 | local lanes = require 'lanes'.configure() | 1 | local lanes = require "lanes" |
2 | local q = lanes.linda() | 2 | local q = lanes.linda() |
3 | 3 | ||
4 | local pingpong = function(name, qr, qs, start) | 4 | local pingpong = function(name, qr, qs, start) |
diff --git a/tests/recursive.lua b/tests/recursive.lua index 139f4c8..97b9c5b 100644 --- a/tests/recursive.lua +++ b/tests/recursive.lua | |||
@@ -12,14 +12,10 @@ local function func( depth ) | |||
12 | end | 12 | end |
13 | 13 | ||
14 | local lanes = require "lanes" | 14 | local lanes = require "lanes" |
15 | -- lanes.configure() is available only at the first require() | 15 | local lane = lanes.gen("*", func)( depth+1 ) |
16 | if lanes.configure then | ||
17 | lanes = lanes.configure{with_timers = false} | ||
18 | end | ||
19 | local lane= lanes.gen("*", func)( depth+1 ) | ||
20 | return lane[1] | 16 | return lane[1] |
21 | end | 17 | end |
22 | 18 | ||
23 | local v= func(0) | 19 | local v= func(0) |
24 | assert(v=="done!") | 20 | assert(v=="done!") |
25 | io.stderr:write("\n") | 21 | io.stderr:write("TEST OK\n") |