From d93e1fcea482f8348bb42171befea08466f8541f Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 10 Jun 2024 09:57:47 +0200 Subject: Suspend/resume GC around Linda operations --- docs/index.html | 155 ++++++++++++++++++++++++++------------------------------ 1 file changed, 72 insertions(+), 83 deletions(-) (limited to 'docs') diff --git a/docs/index.html b/docs/index.html index b83c159..dd7854a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -97,11 +97,11 @@

Features:

@@ -1401,7 +1390,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys.

- Once a timer expires, the key is set with the current time (in seconds, same offset as os.time() but with millisecond accuracy). The key can be waited upon using the regular Linda :receive() method. + Once a timer expires, the key is set with the current time (in seconds, same offset as os.time() but with millisecond accuracy). The key can be waited upon using the regular Linda :receive() method.

@@ -1440,9 +1429,9 @@ On the other side, you need to use a common Linda for waiting for multiple keys. Design note: - Having the API as lanes.timer() is intentional. Another alternative would be linda_h:timer() but timers are not traditionally seen to be part of Lindas. Also, it would mean any lane getting a Linda handle would be able to modify timers on it. - A third choice could be abstracting the timers out of Linda realm altogether (timer_h= lanes.timer(date|first_secs, period_secs )) but that would mean separate waiting functions for timers, and lindas. - Even if a linda object and key was returned, that key couldn't be waited upon simultaneously with one's general linda events. + Having the API as lanes.timer() is intentional. Another alternative would be linda_h:timer() but timers are not traditionally seen to be part of Lindas. Also, it would mean any lane getting a Linda handle would be able to modify timers on it. + A third choice could be abstracting the timers out of Linda realm altogether (timer_h= lanes.timer(date|first_secs, period_secs )) but that would mean separate waiting functions for timers, and lindas. + Even if a Linda object and key was returned, that key couldn't be waited upon simultaneously with one's general Linda events. The current system gives maximum capabilities with minimum API, and any smoothenings can easily be crafted in Lua at the application level. @@ -1465,8 +1454,8 @@ On the other side, you need to use a common Linda for waiting for multiple keys.

- 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 0, which should only cause a thread context switch.
+ 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 0, which should only cause a thread context switch.
Return values should always be nil, "timeout" (or nil, lanes.cancel_error in case of interruption).

@@ -1475,7 +1464,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys.

- Returns the current value of the clock used by timers and lindas. + Returns the current value of the clock used by timers and Linda objects.

@@ -1497,7 +1486,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys.

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 M=N=1 for a critical section lock (only one lane allowed to enter).
- When passsing "try" as second argument when acquiring, then lock_func operates on the linda with a timeout of 0 to emulate a TryLock() operation. If locking fails, lock_func returns false. "try" is ignored when releasing (as it it not expected to ever have to wait unless the acquisition/release pairs are not properly matched). + When passsing "try" as second argument when acquiring, then lock_func operates on the Linda with a timeout of 0 to emulate a TryLock() operation. If locking fails, lock_func returns false. "try" is ignored when releasing (as it it not expected to ever have to wait unless the acquisition/release pairs are not properly matched).
Upon successful lock/unlock, lock_func returns true (always the case when block-waiting for completion).

@@ -1543,7 +1532,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys.
  • Cyclic tables and/or duplicate references are allowed and reproduced appropriately, but only within the same transmission.
  • @@ -1650,7 +1639,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys.
  • Another more immediate reason of failed transfer is when the destination state doesn't know about the C function that has to be transferred. This occurs if a function is transferred in a lane before it had a chance to scan the module. - If the C function is sent through a linda, it is enough for the destination lane body to have required the module before the function is sent. + If the C function is sent through a Linda, it is enough for the destination lane body to have required the module before the function is sent. But if the lane body provided to the generator has a C function as upvalue, the transfer itself must succeed, therefore the module that imported that C function must be required in the destination lane before the lane body starts executing. This is where the .required options play their role.

    @@ -1754,7 +1743,7 @@ int luaD_new_clonable(lua_State* L)

    Deep userdata in your own apps

    - The mechanism Lanes uses for sharing Linda handles between separate Lua states can be used for custom userdata as well. Here's what to do. + The mechanism Lanes uses for sharing Linda handles between separate Lua states can be used for custom userdata as well. Here's what to do.

      @@ -1792,10 +1781,10 @@ static MyDeepFactory g_MyDeepFactory;

      - Deep userdata in transit inside keeper states (sent in a linda but not yet consumed) don't call deleteDeepObjectInternal and aren't considered by reference counting. The rationale is the following:
      + Deep userdata in transit inside Keeper states (sent in a Linda but not yet consumed) don't call deleteDeepObjectInternal and aren't considered by reference counting. The rationale is the following:
      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.
      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 factory() interface is never accessed from a keeper state.
      - Therefore, Lanes can just call deleteDeepObjectInternal 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 keeper states now hold stale pointers. + Therefore, Lanes can just call deleteDeepObjectInternal 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 Keeper states now hold stale pointers.

      @@ -1810,7 +1799,7 @@ static MyDeepFactory g_MyDeepFactory;

      - The same benefits can be achieved by having a single worker lane spawn all the sublanes, and keep track of them. Communications to and from this lane can be handled via a Linda. + The same benefits can be achieved by having a single worker lane spawn all the sublanes, and keep track of them. Communications to and from this lane can be handled via a Linda.

      @@ -1838,12 +1827,12 @@ static MyDeepFactory g_MyDeepFactory;

      -- cgit v1.2.3-55-g6feb