From 17576c3f6762b5ba0359ddec04f5cd8916d3e2f8 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 29 Mar 2024 16:43:29 +0100 Subject: C++ migration: bumped version and updated documentation --- docs/index.html | 89 ++++++++++++++++++++------------------------------------- 1 file changed, 31 insertions(+), 58 deletions(-) (limited to 'docs') diff --git a/docs/index.html b/docs/index.html index b48c527..f8124c7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -70,7 +70,7 @@

- This document was revised on 23-Feb-24, and applies to version 3.16.3. + This document was revised on 29-Mar-24, and applies to version 4.0.0.

@@ -88,7 +88,7 @@ Lanes is included into your software by the regular require "lanes" method. No C side programming is needed; all APIs are Lua side, and most existing extension modules should work seamlessly together with the multiple lanes.

- Starting with version 3.1.6, Lanes should build and run identically with either Lua 5.1 or Lua 5.2. Version 3.10.0 supports Lua 5.3. + Lanes should build and run identically with either Lua 5.1 to Lua 5.4, as well as LuaJIT.

See comparison of Lua Lanes with other Lua multithreading solutions. @@ -152,7 +152,7 @@

Building and Installing

- Lua Lanes is built simply by make on the supported platforms (make-vc for Visual C++). See README for system specific details and limitations. + Lua Lanes is implemented in C++20. It is built simply by make on the supported platforms (make-vc for Visual C++). See README for system specific details and limitations.

@@ -246,7 +246,7 @@

- Starting with version 3.0-beta, requiring the module follows Lua 5.2 rules: the module is not available under the global name "lanes", but has to be accessed through require's return value. + Requiring the module follows Lua 5.2+ rules: the module is not available under the global name "lanes", but has to be accessed through require's return value.

After lanes is required, it is necessary to call lanes.configure(), which is the only function exposed by the module at this point. Calling configure() will perform one-time initializations and make the rest of the API available. @@ -259,7 +259,7 @@ 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.

- IMPORTANT NOTE: Starting with version 3.7.0, only the first occurence of require "lanes" must be followed by a call to .configure(). From this point, a simple require "lanes" will do wherever you need to require lanes again. + IMPORTANT NOTE: Only the first occurence of require "lanes" must be followed by a call to .configure(). From this point, a simple require "lanes" will do wherever you need to require lanes again.

@@ -311,25 +311,11 @@ nil/false/true - (Since v3.6.3) If equal to true, Lanes will collect more information when transfering stuff across Lua states to help identify errors (with a cost). + If equal to true, Lanes will collect more information when transfering stuff across Lua states to help identify errors (with a cost). Default is false. - - - .protect_allocator - - - nil/false/true - - - REPLACED BY allocator="protected" AS OF VERSION v3.13.0. - (Since v3.5.2) If equal to true, Lanes wraps all calls to the state's allocator function inside a mutex. Since v3.6.3, when left unset, Lanes attempts to autodetect this value for LuaJIT (the guess might be wrong if "ffi" isn't loaded though). - Default is true when Lanes detects it is run by LuaJIT, else nil. - - - .allocator @@ -338,7 +324,6 @@ nil/"protected"/function - (Since v3.13.0)
If nil, Lua states are created with lua_newstate() and reuse the allocator from the master state.
If "protected", The default allocator obtained from lua_getallocf() in the master state is wrapped inside a critical section and used in all newly created states.
If a function, this function is called prior to creating the state. It should return a full userdata containing the following structure: @@ -362,7 +347,6 @@ "libc"/"allocator" - (Since v3.16.1)
Controls which allocator is used for Lanes internal allocations (for keeper, linda and lane management). If "libc", Lanes uses realloc and free.
If "allocator", Lanes uses whatever was obtained from the "allocator" setting.
@@ -378,7 +362,7 @@ nil/false/true - (Since v3.7.5) If equal to false or nil, Lanes raises an error when attempting to transfer a non-deep full userdata, else it will be demoted to a light userdata in the destination. + If equal to false or nil, Lanes raises an error when attempting to transfer a non-deep full userdata, else it will be demoted to a light userdata in the destination. Default is false (set to true to get the legacy behaviour). @@ -415,7 +399,7 @@ That way, all changes in the state can be properly taken into account when building the function lookup database. Default is nil.
- (Since version 3.7.6) If on_state_create() is a Lua function, it will be transfered normally before the call. + If on_state_create() is a Lua function, it will be transfered normally before the call.
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. @@ -429,18 +413,18 @@ number >= 0 - (Since v3.3.0) Sets the duration in seconds Lanes will wait for graceful termination of running lanes at application shutdown. Irrelevant for builds using pthreads. Default is 0.25. + Sets the duration in seconds Lanes will wait for graceful termination of running lanes at application shutdown. Irrelevant for builds using pthreads. Default is 0.25.

- (Since v3.5.0) Once Lanes is configured, one should register with Lanes the modules exporting functions that will be transferred either during lane generation or through lindas. + Once Lanes is configured, one should register with Lanes the modules exporting functions that will be transferred either during lane generation or through lindas.
Use lanes.require() for this purpose. This will call the original require(), then add the result to the lookup databases.
- (Since version 3.11) It is also possible to register a given module with lanes.register(). This function will raise an error if the registered module is not a function or table. + It is also possible to register a given module with lanes.register(). This function will raise an error if the registered module is not a function or table.

@@ -701,7 +685,7 @@ @@ -724,8 +708,6 @@
function - (Since version 3.8.2) Callback that gets invoked when the lane is garbage collected. The function receives two arguments (the lane name and a string, either "closed" or "selfdestruct"). + Callback that gets invoked when the lane is garbage collected. The function receives two arguments (the lane name and a string, either "closed" or "selfdestruct").
table - Introduced at version 3.0. -
Specifying it when libs_str doesn't cause the package library to be loaded will generate an error.
If not specified, the created lane will receive the current values of package. Only path, cpath, preload and loaders (Lua 5.1)/searchers (Lua 5.2) are transfered. @@ -736,12 +718,12 @@

Each lane also gets a global function set_debug_threadname() that it can use anytime to do as the name says. Supported debuggers are Microsoft Visual Studio (for the C side) and Decoda (for the Lua side).
- Starting with version 3.8.1, the lane has a new method lane:get_debug_threadname() that gives access to that name from the caller side (returns "<unnamed>" if unset, "<closed>" if the internal Lua state is closed). + The lane also has a method lane:get_debug_threadname() that gives access to that name from the caller side (returns "<unnamed>" if unset, "<closed>" if the internal Lua state is closed).

If a lane body pulls a C function imported by a module required before Lanes itself (thus not through a hooked require), the lane generator creation will raise an error. - The function name it shows is a path where it was found by scanning _G. As a utility, the name guessing functionality is exposed as such: + The function name it shows is a path where it was found by scanning _G and the registry. As a utility, the name guessing functionality is exposed as such: @@ -752,10 +734,6 @@

-

- Starting with version 3.8.3, lanes.nameof() searches the registry as well. -

-

Free running lanes

@@ -892,7 +870,7 @@

- was forcefully killed by lane_h:cancel() (since v3.3.0) + was forcefully killed by lane_h:cancel()
@@ -953,7 +931,7 @@

- Waits until the lane finishes, or timeout seconds have passed. Returns nil, "timeout" on timeout (since v3.13), nil,err,stack_tbl if the lane hit an error, nil, "killed" if forcefully killed (starting with v3.3.0), or the return values of the lane. + Waits until the lane finishes, or timeout seconds have passed. Returns nil, "timeout" on timeout, nil,err,stack_tbl if the lane hit an error, nil, "killed" if forcefully killed, or the return values of the lane. Unlike in reading the results in table fashion, errors are not propagated.

@@ -1038,7 +1016,7 @@ If the lane is still running after the timeout expired and force_kill is true, the OS thread running the lane is forcefully killed. This means no GC, probable OS resource leaks (thread stack, locks, DLL notifications), and should generally be the last resort.

- Cancellation is tested before going to sleep in receive() or send() calls and after executing cancelstep Lua statements. Starting with version 3.0-beta, a pending receive()or send() call is awakened. + Cancellation is tested before going to sleep in receive() or send() calls and after executing cancelstep Lua statements. A pending receive()or send() call is awakened.
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 linda with infinite timeout).
@@ -1143,7 +1121,7 @@

  • receive has a batched mode to consume more than one value from a single key, as in linda:receive( 1.0, linda.batched, "key", 3, 6).
  • individual keys' queue length can be limited, balancing speed differences in a producer/consumer scenario (making :send wait).
  • tostring( linda) returns a string of the form "Linda: <opt_name>"
  • -
  • several lindas may share the same keeper state. Since version 3.9.1, state assignation can be controlled with the linda's group (an integer). All lindas belonging to the same group will share the same keeper state. One keeper state may be shared by several groups.
  • +
  • several lindas may share the same keeper state. State assignation can be controlled with the linda's group (an integer). All lindas belonging to the same group will share the same keeper state. One keeper state may be shared by several groups.
  • @@ -1168,7 +1146,7 @@
    A limit of 0 is allowed to block everything.
    - (Since version 3.7.7) if the key was full but the limit change added some room, limit() returns true and the linda is signalled so that send()-blocked threads are awakened. + If the key was full but the limit change added some room, limit() returns true and the linda is signalled so that send()-blocked threads are awakened.

    @@ -1182,9 +1160,9 @@

    send() returns true if the sending succeeded, and false if the queue limit was met, and the queue did not empty enough during the given timeout.
    - (Since version 3.7.8) send() returns lanes.cancel_error if interrupted by a soft cancel request. + send() returns lanes.cancel_error if interrupted by a soft cancel request.
    - If no data is provided after the key, send() raises an error. Since version 3.9.3, if provided with linda.null before the actual key and there is no data to send, send() sends a single nil. + If no data is provided after the key, send() raises an error. If provided with linda.null before the actual key and there is no data to send, send() sends a single nil.
    Also, if linda.null is sent as data in a linda, it will be read as a nil.

    @@ -1192,9 +1170,7 @@

    Equally, receive() returns a key and the value extracted from it, or nothing for timeout. Note that nils can be sent and received; the key value will tell it apart from a timeout.
    - Version 3.4.0 introduces an API change in the returned values: receive() returns the key followed by the value(s), in that order, and not the other way around. -
    - (Since version 3.7.8) receive() returns lanes.cancel_error if interrupted by a soft cancel request. + receive() returns lanes.cancel_error if interrupted by a soft cancel request.

    @@ -1225,17 +1201,17 @@

    set() signals the linda for write if a value is stored. If nothing special happens, set() returns nothing.
    - Since version 3.7.7, if the key was full but the new data count of the key after set() is below its limit, set() returns true and the linda is also signaled for read so that send()-blocked threads are awakened. + If the key was full but the new data count of the key after set() is below its limit, set() returns true and the linda is also signaled for read so that send()-blocked threads are awakened.

    - Since version 3.8.0, set() can write several values at the specified key, writing nil values is now possible, and clearing the contents at the specified key is done by not providing any value. + set() can write several values at the specified key, writing nil values is now possible, and clearing the contents at the specified key is done by not providing any value.
    Also, get() can read several values at once. If the key contains no data, get() returns no value. This can be used to separate the case when reading stored nil values.

    - Since version 3.8.4, trying to send or receive data through a cancelled linda does nothing and returns lanes.cancel_error. + Trying to send or receive data through a cancelled linda does nothing and returns lanes.cancel_error.

    @@ -1267,7 +1243,7 @@
     

    - (Starting with version 3.8.4) Signals the linda so that lanes waiting for read, write, or both, wake up. + Signals the linda so that lanes waiting for read, write, or both, wake up. All linda operations (including get() and set()) will return lanes.cancel_error as when the calling lane is soft-cancelled as long as the linda is marked as cancelled.
    "none" reset the linda's cancel status, but doesn't signal it. @@ -1404,7 +1380,7 @@ events to a common Linda, but... :).

    - (Since version 3.9.7) 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 linda used for timers (this linda exists even when timers aren't enabled). + 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 linda used for timers (this linda exists even when timers aren't enabled). Default duration is null, which should only cause a thread context switch.

    @@ -1470,9 +1446,6 @@ events to a common Linda, but... :).

    @@ -1615,10 +1588,10 @@ events to a common Linda, but... :).

    Clonable full userdata in your own apps

    - Starting with version 3.13.0, a new way of passing full userdata across lanes uses a new __lanesclone metamethod. + An alternative way of passing full userdata across lanes uses a new __lanesclone metamethod. When a deep userdata is cloned, Lanes calls __lanesclone once, in the context of the source lane.
    The call receives the clone and original as light userdata, plus the actual userdata size, as in clone:__lanesclone(original,size), and should perform the actual cloning.
    - A typical implementation would look like (BEWARE, THIS CHANGED WITH VERSION 3.16.0): + A typical implementation would look like:
     static int clonable_lanesclone( lua_State* L)
     {
    @@ -1696,7 +1669,7 @@ int luaD_new_clonable( lua_State* L)
     		
    	void* idfunc( lua_State* L, DeepOp op_);
    op_ can be one of:
      -
    • eDO_new: requests the creation of a new object, whose pointer is returned. Starting with version 3.13.0, object should embed DeepPrelude structure as header and initialize its magic member with the current DEEP_VERSION.
    • +
    • eDO_new: requests the creation of a new object, whose pointer is returned. Said object must derive from DeepPrelude.
    • eDO_delete: receives this same pointer on the stack as a light userdata, and should cleanup the object.
    • eDO_metatable: should build a metatable for the object. Don't cache the metatable yourself, Lanes takes care of it (eDO_metatable should only be invoked once per state). Just push the metatable on the stack.
    • eDO_module: requests the name of the module that exports the idfunc, to be returned. It is necessary so that Lanes can require it in any lane state that receives a userdata. This is to prevent crashes in situations where the module could be unloaded while the idfunc pointer is still held.
    • -- cgit v1.2.3-55-g6feb