From 307fd830eb168005a3ba3d557343284814757eff Mon Sep 17 00:00:00 2001
From: Benoit Germain
-
- bool,string|(nil,[lanes.cancel_error|"timeout"]) = h:limit(key, <limit>) - (number|string),string = h:limit(key) + bool,string|(nil,[lanes.cancel_error|"timeout"]) = h:limit(slot, <limit>) + (number|string),string = h:limit(slot) |
By default, queue sizes are unlimited but limits can be enforced using the limit() method. This can be useful to balance execution speeds in a producer/consumer scenario.
A limit of 0 is allowed to block everything. "unlimited" removes the limit.
- If the key was full but the limit change added some room, limit() first return value is true and the linda is signalled so that send()-blocked threads are awakened, else the return value is false.
- If no limit is provided, limit() first return value is the current limit for the specified key.
- The second returned value is a string representing the fill status relatively to the key's current limit (one of "over", "under", "exact").
+ If the slot was full but the limit change added some room, limit() first return value is true and the linda is signalled so that send()-blocked threads are awakened, else the return value is false.
+ If no limit is provided, limit() first return value is the current limit for the specified slot.
+ The second returned value is a string representing the fill status relatively to the slot's current limit (one of "over", "under", "exact").
Whether reading or writing, if the linda is cancelled, limit() returns nil, lanes.cancel_error.
- true|lanes.cancel_error = h:send([timeout_secs,] key, ...) + string|(nil,[lanes.cancel_error|"timeout"]) = h:restrict(slot [, "<mode>"]) + string = h:restrict(slot) |
- Timeouts are given in seconds (>= 0, millisecond accuracy) or nil. Timeout can be omitted only if the first key is not a number (then it is equivalent to an infinite duration).
- 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.
+ It is possible to restrict a particular slot in a Linda to either send/receive or set/get operations.
+ Possible modes are "none", "set/get" or "send/receive".
+ If a new mode is specified, restrict() updates the mode and returns the previous one.
+ If no mode is specified, restrict() does nothing and returns the current mode.
+ If the linda is cancelled, restrict() returns nil, lanes.cancel_error.
+ If an unknown mode is specified, restrict() raises an error.
+
+ true|lanes.cancel_error = h:send([timeout_secs,] slot, ...) + |
+ Timeouts are given in seconds (>= 0, millisecond accuracy) or nil. Timeout can be omitted only if the first slot is not a number (then it is equivalent to an infinite duration).
+ Each slot acts as a FIFO queue. There is no limit to the number of slots a linda may contain. Different lindas can have identical slots, which are totally unrelated.
- Multiple values can be sent to a given key at once, atomically (the send will fail unless all the values fit within the queue limit). This can be useful for multiple producer scenarios, if the protocols used are giving data in streams of multiple units. + Multiple values can be sent to a given slot at once, atomically (the send will fail unless all the values fit within the queue limit). This can be useful for multiple producer scenarios, if the protocols used are giving data in streams of multiple units. Atomicity avoids the producers from garbling each others messages, which could happen if the units were sent individually.
- If no data is provided after the key, send() raises an error.
- Also, if linda.null or lanes.null is sent as data in a linda, it will be read as a nil.
+ If linda.null or lanes.null is sent as data in a linda, it will be read as a nil.
+
+ send() raises an error if no data is provided after the slot.
+ send() raises an error if called when a restriction forbids its use on the provided slot.
+ send() raises lanes.cancel_error if interrupted by a hard cancel request.
send() return values can be:
- key, val = h:receive([timeout_secs,] key [, key...]) + slot, val = h:receive([timeout_secs,] slot [, slot...]) - key, val [, val...] = h:receive([timeout,] h.batched, key, n_uint_min[, n_uint_max]) + slot, val [, val...] = h:receive([timeout,] h.batched, slot, n_uint_min[, n_uint_max]) |
+ receive() raises an error if called when a restriction forbids its use on any provided slot.
+ In batched mode, receive() will raise an error if min_count < 1 or max_count < min_count.
+
Unbatched receive() return values can be:
- In batched mode, linda:receive() will raise an error if min_count < 1 or max_count < min_count. -
-Note that any number of lanes can be reading or writing a linda. There can be many producers, and many consumers. It is up to you.
@@ -1339,19 +1359,20 @@- When receiving from multiple slots, the keys are checked in order, which can be used for making priority queues. + When receiving from multiple slots, the slots are checked in order, which can be used for making priority queues.
- (bool,string)|(nil,lanes.cancel_error) = linda_h:set(key [, val [, ...]]) + (bool,string)|(nil,lanes.cancel_error) = linda_h:set(slot [, val [, ...]]) - (number,[val [, ...]])|(nil,lanes.cancel_error) = linda_h:get(key [, count = 1]) + (number,[val [, ...]])|(nil,lanes.cancel_error) = linda_h:get(slot [, count = 1]) |
- get()/set() and send()/receive() can be used together; reading a slot essentially peeks the next outcoming value of a queue.
- get()/set() are for accessing a key without queuing or consuming. They can be used for making shared tables of storage among the lanes.
- Writing to a key never blocks because it ignores the limit. It overwrites existing values and clears any possible queued entries.
+ set() and get() raise an error if used when a restriction forbids their use on the provided slot.
+ Unless a particular slot is constrained with restrict(), get()/set() and send()/receive() can be used together; reading a slot essentially peeks the next outcoming value of a queue.
+ get()/set() are for accessing a slot without queuing or consuming. They can be used for making shared tables of storage among the lanes.
+ set() never blocks because it ignores the limit. It overwrites existing values and clears any possible queued entries.
get() can read several values at once, and does not block. Return values ares: @@ -1361,12 +1382,12 @@
- set() can write several values at the specified key. Writing nil values is possible, and clearing the contents at the specified key is done by not providing any value.
+ set() can write several values at the specified slot. Writing nil values is possible, and clearing the contents at the specified slot is done by not providing any value.
If set() actually stores data, the linda is signalled for write, so that receive()-blocked Lanes are awakened.
- Clearing the contents of a non-existent key does not create it!
- If the key was full but the new data count of the key after set() is below its limit, set() first return value is true and the linda is also signaled for read, so that send()-blocked Lanes are awakened.
- If the key was not already full, nothing additional happens, and set() first return value is false.
- The second return value is a string representing the fill status relatively to the key's current limit (one of "over", "under", "exact").
+ Clearing the contents of a non-existent slot does not create it!
+ If the slot was full but the new data count of the slot after set() is below its limit, set() first return value is true and the linda is also signaled for read, so that send()-blocked Lanes are awakened.
+ If the slot was not already full, nothing additional happens, and set() first return value is false.
+ The second return value is a string representing the fill status relatively to the slot's current limit (one of "over", "under", "exact").
@@ -1374,25 +1395,26 @@
- [val] = linda_h:count([key[,...]]) + [val] = linda_h:count([slot[,...]]) |
Returns some information about the contents of the linda.
- If no key is specified, and the linda is empty, returns nothing.
- 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.
- If a single key is specified, returns the number of pending items, or nothing if the key is unknown.
- If more than one key is specified, return a table of key/count pairs for the known keys.
+ If no slot is specified, and the linda is empty, returns nothing.
+ If no slot is specified, and the linda is not empty, returns a table of slot/count pairs that counts the number of items in each of the exiting slots of the linda. This count can be 0 if the slot has been used but is empty.
+ If a single slot is specified, returns the number of pending items, or nothing if the slot is unknown.
+ If more than one slot is specified, return a table of slot/count pairs for the known slots.
linda_h:dump() -> { - [<key>] = + [<slot>] = { first = <n> count = <n> limit = <n>|'unlimited' + restrict = "none"|"set/get"|"send/receive" fifo = { <array of values> } } ... @@ -1458,7 +1480,7 @@ @@ -1480,7 +1502,7 @@ Timers
@@ -1492,7 +1514,7 @@ - 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 slot is set with the current time (in seconds, same offset as os.time() but with millisecond accuracy). The slot can be waited upon using the regular linda :receive() method. @@ -1517,13 +1539,13 @@ lanes.timer(linda, "min", t, 60) -- reoccur every minute (sharp) while true do - local key, v = linda:receive("sec", "min") - print("Timer "..key..": "..v) + local slot, v = linda:receive("sec", "min") + print("Timer "..slot..": "..v) end |
- NOTE: Timer keys are set, not queued, so missing a beat is possible especially if the timer cycle is extremely small. The key value can be used to know the actual time passed. + NOTE: Timer slots are set, not queued, so missing a beat is possible especially if the timer cycle is extremely small. The slot value can be used to know the actual time passed.
- lock_func|lanes.cancel_error = lanes.genlock(linda_h, key [,N_uint=1]) + lock_func|lanes.cancel_error = lanes.genlock(linda_h, slot [,N_uint=1]) bool|lanes.cancel_error = lock_func(M_uint [, "try"] ) -- acquire .. @@ -1604,13 +1626,13 @@
- Each time called, the generated function will change linda[key] atomically, without other lanes being able to interfere. The new value is returned. You can use either diff 0.0 or get to just read the current value. + Each time called, the generated function will change linda[slot] atomically, without other lanes being able to interfere. The new value is returned. You can use either diff 0.0 or get to just read the current value. @@ -1632,7 +1654,7 @@
|