diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 09:57:47 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 09:57:47 +0200 |
commit | d93e1fcea482f8348bb42171befea08466f8541f (patch) | |
tree | 885952cd1de3f4b7d923f61ba3cdf2b358749483 /docs | |
parent | 9a7c7f5f7ec66576447b4d225066cc388f8ca6b0 (diff) | |
download | lanes-d93e1fcea482f8348bb42171befea08466f8541f.tar.gz lanes-d93e1fcea482f8348bb42171befea08466f8541f.tar.bz2 lanes-d93e1fcea482f8348bb42171befea08466f8541f.zip |
Suspend/resume GC around Linda operations
Diffstat (limited to 'docs')
-rw-r--r-- | docs/index.html | 155 |
1 files changed, 72 insertions, 83 deletions
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 @@ | |||
97 | <h3>Features:</h3> | 97 | <h3>Features:</h3> |
98 | 98 | ||
99 | <ul> | 99 | <ul> |
100 | <li>Lanes have separated data, by default. Shared data is possible with Linda objects.</li> | 100 | <li>Lanes have separated data, by default. Shared data is possible with <a href="#lindas">Linda</a> objects.</li> |
101 | <li>Communications is separate of threads, using Linda objects.</li> | 101 | <li>Communications is separate of threads, using <a href="#lindas">Linda</a> objects.</li> |
102 | <li>Data passing uses fast inter-state copies (no serialization required).</li> | 102 | <li>Data passing uses fast inter-state copies (no serialization required).</li> |
103 | <li>"Deep userdata" concept, for sharing userdata over multiple lanes.</li> | 103 | <li>"Deep userdata" concept, for sharing userdata over multiple lanes.</li> |
104 | <li>Millisecond level timers, integrated with the Linda system.</li> | 104 | <li>Millisecond level timers, integrated with the <a href="#lindas">Linda</a> system.</li> |
105 | <li>Threads can be given priorities.</li> | 105 | <li>Threads can be given priorities.</li> |
106 | <li>Lanes are cancellable, with proper cleanup.</li> | 106 | <li>Lanes are cancellable, with proper cleanup.</li> |
107 | <li>No Lua-side application level locking - ever!</li> | 107 | <li>No Lua-side application level locking - ever!</li> |
@@ -142,8 +142,8 @@ | |||
142 | 142 | ||
143 | </p> | 143 | </p> |
144 | <p> | 144 | <p> |
145 | The underlying threading code can be compiled either towards Win32 API or <a TARGET="_blank" HREF="http://en.wikipedia.org/wiki/POSIX_Threads">Pthreads</a>. Unfortunately, thread prioritization under Pthreads is a JOKE, | 145 | The underlying threading code can be compiled either towards Win32 API or <a TARGET="_blank" HREF="http://en.wikipedia.org/wiki/POSIX_Threads">Pthreads</a>. Unfortunately, thread prioritization under Pthreads |
146 | requiring OS specific tweaks and guessing undocumented behaviour. Other features should be portable to any modern platform. | 146 | requires OS specific tweaks and guessing undocumented behaviour. Other features should be portable to any modern platform. |
147 | </p> | 147 | </p> |
148 | 148 | ||
149 | 149 | ||
@@ -285,9 +285,9 @@ | |||
285 | </td> | 285 | </td> |
286 | <td>integer in [0,100]</td> | 286 | <td>integer in [0,100]</td> |
287 | <td> | 287 | <td> |
288 | Controls the number of "user" keeper states used internally by lindas to transfer data between lanes. (see <a href="#lindas">below</a>). Default is <tt>0</tt>.<br/> | 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/> |
289 | Lanes always creates at least one keeper state for the internal timer linda. If <tt>nb_user_keepers</tt> is <tt>0</tt>, the other lindas you create will share this keeper by necessity.<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/> |
290 | If there is more than one keeper (in total), linda creation must specify the group it belongs to. | 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. |
291 | </td> | 291 | </td> |
292 | </tr> | 292 | </tr> |
293 | 293 | ||
@@ -298,8 +298,8 @@ | |||
298 | <td>integer</td> | 298 | <td>integer</td> |
299 | <td> | 299 | <td> |
300 | If <0, GC runs automatically. This is the default.<br/> | 300 | If <0, GC runs automatically. This is the default.<br/> |
301 | If 0, GC runs after *every* keeper operation.<br/> | 301 | If 0, GC runs after *every* <a href="#keepers">Keeper</a> operation.<br/> |
302 | If >0, Keepers 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 keeper operation (see <a href="#lindas">below</a>). If memory usage remains above threshold after the GC cycle, an error is raised. | 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. |
303 | </td> | 303 | </td> |
304 | </tr> | 304 | </tr> |
305 | 305 | ||
@@ -360,7 +360,7 @@ | |||
360 | <tt>"libc"</tt>/<tt>"allocator"</tt> | 360 | <tt>"libc"</tt>/<tt>"allocator"</tt> |
361 | </td> | 361 | </td> |
362 | <td> | 362 | <td> |
363 | Controls which allocator is used for Lanes internal allocations (for keeper, linda and lane management). | 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). |
364 | If <tt>"libc"</tt>, Lanes uses <tt>realloc</tt> and <tt>free</tt>.<br/> | 364 | 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/> | 365 | 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). | 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). |
@@ -403,7 +403,7 @@ | |||
403 | <td> | 403 | <td> |
404 | 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/> | 404 | 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/> |
405 | 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/> | 405 | 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/> |
406 | Keeper states will call it as well, but only if it is a C function (keeper states are not able to execute any user Lua code).<br/> | 406 | 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/> |
407 | Typical usage is twofold: | 407 | Typical usage is twofold: |
408 | <ul> | 408 | <ul> |
409 | <li>Tweak <tt>package.loaders</tt></li> | 409 | <li>Tweak <tt>package.loaders</tt></li> |
@@ -1072,13 +1072,13 @@ | |||
1072 | <br/> | 1072 | <br/> |
1073 | 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>. | 1073 | 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>. |
1074 | If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>. | 1074 | If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>. |
1075 | If <tt>wake_lane</tt> is <tt>true</tt>, the lane is also signalled so that execution returns from any pending linda operation. Linda operations detecting the cancellation request return <tt>lanes.cancel_error</tt>. | 1075 | 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>. |
1076 | </p> | 1076 | </p> |
1077 | <p> | 1077 | <p> |
1078 | 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/> | 1078 | 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/> |
1079 | </p> | 1079 | </p> |
1080 | <p> | 1080 | <p> |
1081 | If <tt>mode</tt> is <tt>"hard"</tt>, waits for the request to be processed, or a timeout to occur. Linda operations detecting the cancellation request will raise a special cancellation error (meaning they won't return in that case).<br/> | 1081 | 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/> |
1082 | <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified. | 1082 | <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified. |
1083 | </p> | 1083 | </p> |
1084 | <p> | 1084 | <p> |
@@ -1094,7 +1094,7 @@ | |||
1094 | <p> | 1094 | <p> |
1095 | 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. | 1095 | 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. |
1096 | <br/> | 1096 | <br/> |
1097 | 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). | 1097 | 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). |
1098 | <br/> | 1098 | <br/> |
1099 | 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). | 1099 | 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). |
1100 | <br/> | 1100 | <br/> |
@@ -1199,8 +1199,14 @@ | |||
1199 | <li><tt>receive</tt> has a batched mode to consume more than one value from a single key, as in <tt>linda:receive(1.0, linda.batched, "key", 3, 6).</tt></li> | 1199 | <li><tt>receive</tt> has a batched mode to consume more than one value from a single key, as in <tt>linda:receive(1.0, linda.batched, "key", 3, 6).</tt></li> |
1200 | <li>individual keys' queue length can be limited, balancing speed differences in a producer/consumer scenario (making <tt>:send</tt> wait).</li> | 1200 | <li>individual keys' queue length can be limited, balancing speed differences in a producer/consumer scenario (making <tt>:send</tt> wait).</li> |
1201 | <li><tt>tostring(linda)</tt> returns a string of the form <tt>"Linda: <opt_name>"</tt></li> | 1201 | <li><tt>tostring(linda)</tt> returns a string of the form <tt>"Linda: <opt_name>"</tt></li> |
1202 | <li>Several lindas may share the same keeper state. In case there is more than one user keeper state, assignation must be controlled with the linda's group (an integer in <tt>[0,nb_user_keepers]</tt>). | 1202 | <li> |
1203 | Lanes has an internal linda used for timers and <tt>lanes.wait</tt>; this linda uses group 0.</li> | 1203 | Several Linda objects may share the same <a href="#keepers">Keeper state</a>. In case there is more than one user <a href="#keepers">Keeper state</a>, assignation must be controlled with the Linda's group (an integer in <tt>[0,nb_user_keepers]</tt>). |
1204 | Lanes has an internal Linda used for timers and <tt>lanes.wait</tt>; this Linda uses group 0. | ||
1205 | </li> | ||
1206 | <li> | ||
1207 | IMPORTANT: *all* Linda operations are wrapped inside a <tt>lua_gc STOP/RESTART</tt> pair. | ||
1208 | This is to prevent potential collection of a Linda during another Linda's operation, as this can cause a crash if they are bound to the same <a href="#keepers">Keeper state</a>. | ||
1209 | </li> | ||
1204 | </ul> | 1210 | </ul> |
1205 | </p> | 1211 | </p> |
1206 | 1212 | ||
@@ -1218,8 +1224,8 @@ | |||
1218 | 1224 | ||
1219 | <p> | 1225 | <p> |
1220 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br/> | 1226 | Converting the Linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br/> |
1221 | If <tt>opt_name</tt> is omitted, it will evaluate to an hexadecimal number uniquely representing that linda.<br/> | 1227 | If <tt>opt_name</tt> is omitted, it will evaluate to an hexadecimal number uniquely representing that Linda.<br/> |
1222 | 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>. | 1228 | 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>. |
1223 | </p> | 1229 | </p> |
1224 | <p> | 1230 | <p> |
1225 | 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's equivalent to an infinite duration). | 1231 | 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's equivalent to an infinite duration). |
@@ -1229,7 +1235,7 @@ | |||
1229 | The <tt>send()</tt> and <tt>receive()</tt> methods use Linda keys as FIFO stacks (first in, first out).<br/> | 1235 | The <tt>send()</tt> and <tt>receive()</tt> methods use Linda keys as FIFO stacks (first in, first out).<br/> |
1230 | By default, stack 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/> | 1236 | By default, stack 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/> |
1231 | A limit of 0 is allowed to block everything.<br/> | 1237 | A limit of 0 is allowed to block everything.<br/> |
1232 | 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/> | 1238 | 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/> |
1233 | In batched mode, <tt>linda:receive()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. | 1239 | In batched mode, <tt>linda:receive()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. |
1234 | </p> | 1240 | </p> |
1235 | 1241 | ||
@@ -1238,7 +1244,7 @@ | |||
1238 | </p> | 1244 | </p> |
1239 | 1245 | ||
1240 | <p> | 1246 | <p> |
1241 | <a href="#cancelling">Hard cancellation</a> will cause pending linda operations to abort execution of the lane through a cancellation error. This means that you have to install a <a href="#finalizers">finalizer</a> in your lane if you want to run some code in that situation. | 1247 | <a href="#cancelling">Hard cancellation</a> will cause pending Linda operations to abort execution of the lane through a cancellation error. This means that you have to install a <a href="#finalizers">finalizer</a> in your lane if you want to run some code in that situation. |
1242 | </p> | 1248 | </p> |
1243 | 1249 | ||
1244 | <p> | 1250 | <p> |
@@ -1248,7 +1254,7 @@ | |||
1248 | <br/> | 1254 | <br/> |
1249 | If no data is provided after the key, <tt>send()</tt> raises an error. | 1255 | If no data is provided after the key, <tt>send()</tt> raises an error. |
1250 | <br/> | 1256 | <br/> |
1251 | 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>. | 1257 | 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>. |
1252 | </p> | 1258 | </p> |
1253 | 1259 | ||
1254 | <p> | 1260 | <p> |
@@ -1273,29 +1279,24 @@ | |||
1273 | </pre></td></tr></table> | 1279 | </pre></td></tr></table> |
1274 | 1280 | ||
1275 | <p> | 1281 | <p> |
1276 | 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. | 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/> |
1277 | <br/> | 1283 | Writing to a slot never blocks because it ignores the limit. It overwrites existing value and clears any possible queued entries.<br/> |
1278 | Writing to a slot never blocks because it ignores the limit. It overwrites existing value and clears any possible queued entries. | 1284 | Reading doesn't block either because <tt>get()</tt> returns whatever is available (which can be nothing), up to the specified count.<br/> |
1279 | <br/> | ||
1280 | Reading doesn't block either because <tt>get()</tt> returns whatever is available (which can be nothing), up to the specified count. | ||
1281 | <br/> | ||
1282 | 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. |
1283 | </p> | 1286 | </p> |
1284 | 1287 | ||
1285 | <p> | 1288 | <p> |
1286 | <tt>set()</tt> signals the linda for write if a value is stored. If nothing special happens, <tt>set() </tt>returns nothing. | 1289 | <tt>set()</tt> signals the Linda for write if a value is stored. If nothing special happens, <tt>set() </tt>returns nothing.<br/> |
1287 | <br/> | 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. |
1288 | 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. | ||
1289 | </p> | 1291 | </p> |
1290 | 1292 | ||
1291 | <p> | 1293 | <p> |
1292 | <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. | 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/> |
1293 | <br/> | ||
1294 | 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. |
1295 | </p> | 1296 | </p> |
1296 | 1297 | ||
1297 | <p> | 1298 | <p> |
1298 | Trying to send or receive data through a cancelled linda does nothing and returns <tt>lanes.cancel_error</tt>. | 1299 | Trying to send or receive data through a cancelled Linda does nothing and returns <tt>lanes.cancel_error</tt>. |
1299 | </p> | 1300 | </p> |
1300 | 1301 | ||
1301 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1302 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
@@ -1303,14 +1304,10 @@ | |||
1303 | </pre></td></tr></table> | 1304 | </pre></td></tr></table> |
1304 | 1305 | ||
1305 | <p> | 1306 | <p> |
1306 | Returns some information about the contents of the linda. | 1307 | Returns some information about the contents of the Linda.<br/> |
1307 | <br/> | 1308 | 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. | 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/> |
1309 | <br/> | 1310 | If a single key is specified, returns the number of pending items, or nothing if the key is unknown.<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. | ||
1311 | <br/> | ||
1312 | If a single key is specified, returns the number of pending items, or nothing if the key is unknown. | ||
1313 | <br/> | ||
1314 | 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. |
1315 | </p> | 1312 | </p> |
1316 | 1313 | ||
@@ -1319,8 +1316,8 @@ | |||
1319 | </pre></td></tr></table> | 1316 | </pre></td></tr></table> |
1320 | 1317 | ||
1321 | <p> | 1318 | <p> |
1322 | 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/> |
1323 | If Decoda support is enabled with <tt>HAVE_DECODA_SUPPORT()</tt>, 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. |
1324 | </p> | 1321 | </p> |
1325 | 1322 | ||
1326 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1323 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
@@ -1328,30 +1325,22 @@ | |||
1328 | </pre></td></tr></table> | 1325 | </pre></td></tr></table> |
1329 | 1326 | ||
1330 | <p> | 1327 | <p> |
1331 | 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. |
1332 | 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. | 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/> |
1333 | <br/> | 1330 | <tt>"none"</tt> reset the Linda's cancel status, but doesn't signal it.<br/> |
1334 | <tt>"none"</tt> reset the linda's cancel status, but doesn't signal it. | 1331 | If not void, the lane's cancel status overrides the Linda's cancel status. |
1335 | <br/> | ||
1336 | If not void, the lane's cancel status overrides the linda's cancel status. | ||
1337 | </p> | 1332 | </p> |
1338 | 1333 | ||
1339 | <h3>Granularity of using Lindas</h3> | 1334 | <h3 id="keepers">Granularity of using Lindas</h3> |
1340 | 1335 | ||
1341 | <p> | 1336 | <p> |
1342 | 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. | 1337 | 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/> |
1343 | <br/> | 1338 | 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/> |
1344 | 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. | 1339 | 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/> |
1345 | <br/> | 1340 | 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/> |
1346 | 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. | 1341 | 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/> |
1347 | <br/> | 1342 | If the thread is woken but the condition is not yet fulfilled, it goes back to sleep, until the timeout expires.<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. | 1343 | 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>. |
1349 | <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. | ||
1351 | <br/> | ||
1352 | If the thread is woken but the condition is not yet fulfilled, it goes back to sleep, until the timeout expires. | ||
1353 | <br/> | ||
1354 | 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>. | ||
1355 | </p> | 1344 | </p> |
1356 | 1345 | ||
1357 | <p> | 1346 | <p> |
@@ -1372,7 +1361,7 @@ | |||
1372 | 1361 | ||
1373 | <li> | 1362 | <li> |
1374 | Performance. Changing any slot in a Linda causes all pending threads for that Linda to be momentarily awakened (at least in the C level). | 1363 | Performance. Changing any slot in a Linda causes all pending threads for that Linda to be momentarily awakened (at least in the C level). |
1375 | This can degrade performance due to unnecessary OS level context switches. The more keeper states you declared with <a href="#initialization"><tt>lanes.configure()</tt></a> the less this should be a problem. | 1364 | This can degrade performance due to unnecessary OS level context switches. The more Keeper states you declared with <a href="#initialization"><tt>lanes.configure()</tt></a> the less this should be a problem. |
1376 | </li> | 1365 | </li> |
1377 | </ul> | 1366 | </ul> |
1378 | 1367 | ||
@@ -1401,7 +1390,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1401 | </p> | 1390 | </p> |
1402 | 1391 | ||
1403 | <p> | 1392 | <p> |
1404 | Once a timer expires, the <tt>key</tt> is set with the current time (in seconds, same offset as <tt>os.time()</tt> but with millisecond accuracy). The key can be waited upon using the regular Linda <tt>:receive()</tt> method. | 1393 | Once a timer expires, the <tt>key</tt> is set with the current time (in seconds, same offset as <tt>os.time()</tt> but with millisecond accuracy). The key can be waited upon using the regular <a href="#lindas">Linda</a> <tt>:receive()</tt> method. |
1405 | </p> | 1394 | </p> |
1406 | 1395 | ||
1407 | <p> | 1396 | <p> |
@@ -1440,9 +1429,9 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1440 | <td valign=top><i><nobr>Design note:</nobr></i></td> | 1429 | <td valign=top><i><nobr>Design note:</nobr></i></td> |
1441 | <td> | 1430 | <td> |
1442 | <font size="-1"> | 1431 | <font size="-1"> |
1443 | Having the API as <tt>lanes.timer()</tt> is intentional. Another alternative would be <tt>linda_h:timer()</tt> 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. | 1432 | Having the API as <tt>lanes.timer()</tt> is intentional. Another alternative would be <tt>linda_h:timer()</tt> but timers are not traditionally seen to be part of Lindas. Also, it would mean any lane getting a <a href="#lindas">Linda</a> handle would be able to modify timers on it. |
1444 | A third choice could be abstracting the timers out of Linda realm altogether (<tt>timer_h= lanes.timer(date|first_secs, period_secs )</tt>) but that would mean separate waiting functions for timers, and lindas. | 1433 | A third choice could be abstracting the timers out of <a href="#lindas">Linda</a> realm altogether (<tt>timer_h= lanes.timer(date|first_secs, period_secs )</tt>) but that would mean separate waiting functions for timers, and lindas. |
1445 | Even if a linda object and key was returned, that key couldn't be waited upon simultaneously with one's general linda events. | 1434 | Even if a <a href="#lindas">Linda</a> object and key was returned, that key couldn't be waited upon simultaneously with one's general <a href="#lindas">Linda</a> events. |
1446 | The current system gives maximum capabilities with minimum API, and any smoothenings can easily be crafted in Lua at the application level. | 1435 | The current system gives maximum capabilities with minimum API, and any smoothenings can easily be crafted in Lua at the application level. |
1447 | </font> | 1436 | </font> |
1448 | </td> | 1437 | </td> |
@@ -1465,8 +1454,8 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1465 | </pre></td></tr></table> | 1454 | </pre></td></tr></table> |
1466 | 1455 | ||
1467 | <p> | 1456 | <p> |
1468 | 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). | 1457 | 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). |
1469 | Default duration is 0, which should only cause a thread context switch.<br /> | 1458 | Default duration is 0, which should only cause a thread context switch.<br/> |
1470 | Return values should always be <tt>nil, "timeout"</tt> (or <tt>nil, lanes.cancel_error</tt> in case of interruption). | 1459 | Return values should always be <tt>nil, "timeout"</tt> (or <tt>nil, lanes.cancel_error</tt> in case of interruption). |
1471 | </p> | 1460 | </p> |
1472 | 1461 | ||
@@ -1475,7 +1464,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1475 | </pre></td></tr></table> | 1464 | </pre></td></tr></table> |
1476 | 1465 | ||
1477 | <p> | 1466 | <p> |
1478 | Returns the current value of the clock used by timers and lindas. | 1467 | Returns the current value of the clock used by timers and <a href="#lindas">Linda</a> objects. |
1479 | </p> | 1468 | </p> |
1480 | 1469 | ||
1481 | <!-- locks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 1470 | <!-- locks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
@@ -1497,7 +1486,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1497 | <p> | 1486 | <p> |
1498 | 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). | 1487 | 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). |
1499 | <br/> | 1488 | <br/> |
1500 | When passsing <tt>"try"</tt> as second argument when acquiring, then <tt>lock_func</tt> operates on the linda 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). | 1489 | 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). |
1501 | <br/> | 1490 | <br/> |
1502 | Upon successful lock/unlock, <tt>lock_func</tt> returns <tt>true</tt> (always the case when block-waiting for completion). | 1491 | Upon successful lock/unlock, <tt>lock_func</tt> returns <tt>true</tt> (always the case when block-waiting for completion). |
1503 | </p> | 1492 | </p> |
@@ -1543,7 +1532,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1543 | <li> | 1532 | <li> |
1544 | Cyclic tables and/or duplicate references are allowed and reproduced appropriately, but only <u>within the same transmission</u>. | 1533 | Cyclic tables and/or duplicate references are allowed and reproduced appropriately, but only <u>within the same transmission</u>. |
1545 | <ul> | 1534 | <ul> |
1546 | <li>Using the same source table in multiple Linda messages keeps no ties between the tables (this is the same reason why tables can't be used as keys).</li> | 1535 | <li>Using the same source table in multiple <a href="#lindas">Linda</a> messages keeps no ties between the tables (this is the same reason why tables can't be used as keys).</li> |
1547 | </ul> | 1536 | </ul> |
1548 | </li> | 1537 | </li> |
1549 | <li> | 1538 | <li> |
@@ -1650,7 +1639,7 @@ On the other side, you need to use a common Linda for waiting for multiple keys. | |||
1650 | </li> | 1639 | </li> |
1651 | </ul> | 1640 | </ul> |
1652 | 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. | 1641 | 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. |
1653 | 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. | 1642 | If the C function is sent through a <a href="#lindas">Linda</a>, it is enough for the destination lane body to have required the module before the function is sent. |
1654 | 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 <a href = "#.required"><tt>.required</tt></a> options play their role. | 1643 | 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 <a href = "#.required"><tt>.required</tt></a> options play their role. |
1655 | </p> | 1644 | </p> |
1656 | 1645 | ||
@@ -1754,7 +1743,7 @@ int luaD_new_clonable(lua_State* L) | |||
1754 | <h3 id="deep_userdata">Deep userdata in your own apps</h3> | 1743 | <h3 id="deep_userdata">Deep userdata in your own apps</h3> |
1755 | 1744 | ||
1756 | <p> | 1745 | <p> |
1757 | 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. | 1746 | The mechanism Lanes uses for sharing <a href="#lindas">Linda</a> handles between separate Lua states can be used for custom userdata as well. Here's what to do. |
1758 | </p> | 1747 | </p> |
1759 | 1748 | ||
1760 | <ol> | 1749 | <ol> |
@@ -1792,10 +1781,10 @@ static MyDeepFactory g_MyDeepFactory; | |||
1792 | </p> | 1781 | </p> |
1793 | 1782 | ||
1794 | <p> | 1783 | <p> |
1795 | Deep userdata in transit inside keeper states (sent in a linda but not yet consumed) don't call <tt>deleteDeepObjectInternal</tt> and aren't considered by reference counting. The rationale is the following:<br/> | 1784 | 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/> |
1796 | 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/> | 1785 | 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/> |
1797 | 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/> | 1786 | 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/> |
1798 | 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 keeper states now hold stale pointers. | 1787 | 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. |
1799 | </p> | 1788 | </p> |
1800 | 1789 | ||
1801 | <p> | 1790 | <p> |
@@ -1810,7 +1799,7 @@ static MyDeepFactory g_MyDeepFactory; | |||
1810 | </p> | 1799 | </p> |
1811 | 1800 | ||
1812 | <p> | 1801 | <p> |
1813 | 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. | 1802 | 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 <a href="#lindas">Linda</a>. |
1814 | </p> | 1803 | </p> |
1815 | 1804 | ||
1816 | 1805 | ||
@@ -1838,12 +1827,12 @@ static MyDeepFactory g_MyDeepFactory; | |||
1838 | 1827 | ||
1839 | <p> | 1828 | <p> |
1840 | <ul> | 1829 | <ul> |
1841 | <li>Data passing (parameters, upvalues, Linda messages) is generally fast, doing two binary state-to-state copies (from source state to hidden state, hidden state to target state). Remember that not only the function you specify but also its upvalues, their upvalues, etc. etc. will get copied.</li> | 1830 | <li>Data passing (parameters, upvalues, <a href="#lindas">Linda</a> messages) is generally fast, doing two binary state-to-state copies (from source state to hidden state, hidden state to target state). Remember that not only the function you specify but also its upvalues, their upvalues, etc. etc. will get copied.</li> |
1842 | <li>Lane startup is fast (1000's of lanes a second), depending on the number of standard libraries initialized. Initializing all standard libraries is about 3-4 times slower than having no standard libraries at all. If you throw in a lot of lanes per second, make sure you give them minimal necessary set of libraries.</li> | 1831 | <li>Lane startup is fast (1000's of lanes a second), depending on the number of standard libraries initialized. Initializing all standard libraries is about 3-4 times slower than having no standard libraries at all. If you throw in a lot of lanes per second, make sure you give them minimal necessary set of libraries.</li> |
1843 | <li>Waiting Lindas are woken up (and execute some hidden Lua code) each time <u>any</u> key in the Lindas they are waiting for are changed. This may give essential slow-down (not measured, just a gut feeling) if a lot of Linda keys are used. Using separate Linda objects for logically separate issues will help (which is good practice anyhow).</li> | 1832 | <li>Waiting Lindas are woken up (and execute some hidden Lua code) each time <u>any</u> key in the <a href="#lindas">Lindas</a> they are waiting for are changed. This may give essential slow-down (not measured, just a gut feeling) if a lot of <a href="#lindas">Linda</a> keys are used. Using separate <a href="#lindas">Lindas</a> for logically separate issues will help (which is good practice anyhow).</li> |
1844 | <li>Linda objects are light. The memory footprint is two OS-level signalling objects (<tt>HANDLE</tt> or <tt>pthread_cond_t</tt>) for each, plus one C pointer for the proxies per each Lua state using the Linda. Barely nothing.</li> | 1833 | <li><a href="#lindas">Linda</a> objects are light. The memory footprint is two OS-level signalling objects (<tt>HANDLE</tt> or <tt>pthread_cond_t</tt>) for each, plus one C pointer for the proxies per each Lua state using the <a href="#lindas">Linda</a>. Barely nothing.</li> |
1845 | <li>Timers are light. You can probably expect timers up to 0.01 second resolution to be useful, but that is very system specific. All timers are merged into one main timer state (see <tt>timer.lua</tt>); no OS side timers are utilized.</li> | 1834 | <li>Timers are light. You can probably expect timers up to 0.01 second resolution to be useful, but that is very system specific. All timers are merged into one main timer state (see <tt>timer.lua</tt>); no OS side timers are utilized.</li> |
1846 | <li>If you are using a lot of Linda objects, it may be useful to try having more of these keeper states. By default, only one is used (see <a href="#initialization"><tt>lanes.configure()</tt></a>).</li> | 1835 | <li>If you are using a lot of <a href="#lindas">Linda</a> objects, it may be useful to try having more of these <a href="#keepers">Keeper states</a>. By default, only one is used (see <a href="#initialization"><tt>lanes.configure()</tt></a>).</li> |
1847 | </ul> | 1836 | </ul> |
1848 | </p> | 1837 | </p> |
1849 | 1838 | ||