aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
committerPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
commit89d9c98af1ac352ba4d49d660e61b0853d6e1a86 (patch)
tree15c56d2ce66b4ab147171c0f674cdb4a435ff13f /docs
downloadlanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.gz
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.bz2
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.zip
Import to git
Diffstat (limited to 'docs')
-rw-r--r--docs/Lua multithreading choices.grafflebin0 -> 2290 bytes
-rw-r--r--docs/Lua multithreading choices.svg15
-rw-r--r--docs/comparison.html297
-rw-r--r--docs/index.html951
-rw-r--r--docs/multi.pngbin0 -> 4657 bytes
-rw-r--r--docs/performance.odsbin0 -> 66817 bytes
6 files changed, 1263 insertions, 0 deletions
diff --git a/docs/Lua multithreading choices.graffle b/docs/Lua multithreading choices.graffle
new file mode 100644
index 0000000..2bd4cb4
--- /dev/null
+++ b/docs/Lua multithreading choices.graffle
Binary files differ
diff --git a/docs/Lua multithreading choices.svg b/docs/Lua multithreading choices.svg
new file mode 100644
index 0000000..8a09698
--- /dev/null
+++ b/docs/Lua multithreading choices.svg
@@ -0,0 +1,15 @@
1<?xml version="1.0"?>
2<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 813.60004 566.95" width="813.60004pt" height="566.95pt"><metadata xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:date>2008-07-25 19:33Z</dc:date><!-- Produced by OmniGraffle Professional 4.2.1 --></metadata><defs><filter id="Shadow" filterUnits="userSpaceOnUse"><feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="3.488"/><feOffset in="blur" result="offset" dx="0" dy="4"/><feFlood flood-color="black" flood-opacity=".75" result="flood"/><feComposite in="flood" in2="offset" operator="in"/></filter><font-face font-family="Helvetica" font-size="18" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="555.55554" cap-height="722.22223" ascent="770.01953" descent="-229.98047" font-weight="500"><!--NSCTFontDescriptor &lt;0x7988130&gt; = {
4 NSFontNameAttribute = Helvetica;
5 NSFontSizeAttribute = 18;
6}--><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face><marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black"><g><path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/></g></marker><font-face font-family="Courier" font-size="18" units-per-em="1000" underline-position="-178.22266" underline-thickness="57.617188" slope="0" x-height="444.44446" cap-height="611.11115" ascent="753.90625" descent="-246.09375" font-weight="500"><!--NSCTFontDescriptor &lt;0x79dbbf0&gt; = {
7 NSFontNameAttribute = Courier;
8 NSFontSizeAttribute = 18;
9}--><font-face-src><font-face-name name="Courier"/></font-face-src></font-face><font-face font-family="Helvetica" font-size="16" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="531.25" cap-height="718.75" ascent="770.01953" descent="-229.98047" font-weight="500"><!--NSCTFontDescriptor &lt;0x79dde00&gt; = {
10 NSFontNameAttribute = Helvetica;
11 NSFontSizeAttribute = 16;
12}--><font-face-src><font-face-name name="Helvetica"/></font-face-src></font-face><font-face font-family="Times" font-size="24" units-per-em="1000" underline-position="-75.683594" underline-thickness="49.316406" slope="0" x-height="458.33334" cap-height="666.6667" ascent="750" descent="-250" font-weight="500"><!--NSCTFontDescriptor &lt;0x79df960&gt; = {
13 NSFontNameAttribute = "Times-Roman";
14 NSFontSizeAttribute = 24;
15}--><font-face-src><font-face-name name="Times-Roman"/></font-face-src></font-face></defs><g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1"><title>Canvas 1</title><rect fill="white" width="813.60004" height="566.95"/><g><title>Layer 1</title><g><use xl:href="#id4_Graphic" filter="url(#Shadow)"/><use xl:href="#id2_Graphic" filter="url(#Shadow)"/><use xl:href="#id33_Graphic" filter="url(#Shadow)"/><use xl:href="#id36_Graphic" filter="url(#Shadow)"/></g><g id="id4_Graphic"><path d="M 162.15001 63.999992 L 484.84998 63.999992 C 523.0208 63.999992 554 94.02719 554 131.02499 C 554 168.0228 523.0208 198.04999 484.84998 198.04999 L 162.15001 198.04999 C 123.9792 198.04999 93 168.0228 93 131.02499 C 93 94.02719 123.9792 63.999992 162.15001 63.999992" fill="#ffff51"/><path d="M 162.15001 63.999992 L 484.84998 63.999992 C 523.0208 63.999992 554 94.02719 554 131.02499 C 554 168.0228 523.0208 198.04999 484.84998 198.04999 L 162.15001 198.04999 C 123.9792 198.04999 93 168.0228 93 131.02499 C 93 94.02719 123.9792 63.999992 162.15001 63.999992" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(144.10001 120.024994)" fill="black"><tspan font-family="Helvetica" font-size="18" font-weight="500" x="154.878525" y="18" textLength="49.04297">Lanes</tspan></text></g><line x1="67" y1="508" x2="733.09998" y2="508" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><line x1="67" y1="508" x2="67" y2="68.90001" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(613 516)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="118.819336">distributed</tspan></text><text transform="translate(104.9992 516)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="118.819336">shared data</tspan></text><text transform="translate(323.5 516)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="140.42285">isolated data</tspan></text><text transform="translate(21.501301 355) rotate(-90)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="108.01758">coroutines</tspan></text><text transform="translate(21.501297 187.5) rotate(-90)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="108.01758">OS threads</tspan></text><g id="id2_Graphic"><ellipse cx="164.4995" cy="312.5" rx="71.49962" ry="67.025116" fill="white"/><ellipse cx="164.4995" cy="312.5" rx="71.49962" ry="67.025116" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(112.299896 293.50003)" fill="black"><tspan font-family="Helvetica" font-size="16" font-weight="500" x="38.85194" y="15" textLength="26.695312">Lua</tspan><tspan font-family="Helvetica" font-size="16" font-weight="500" x="15.28944" y="34" textLength="73.820312">coroutines</tspan></text></g><text transform="translate(21.501301 504) rotate(-90)" fill="black"><tspan font-family="Courier" font-size="18" font-weight="500" x="0" y="18" textLength="97.21582">core mods</tspan></text><g id="id33_Graphic"><ellipse cx="164.49921" cy="441.975" rx="71.49961" ry="67.02514" fill="#ff7695"/><ellipse cx="164.49921" cy="441.975" rx="71.49961" ry="67.02514" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(112.2996 432.47504)" fill="black"><tspan font-family="Helvetica" font-size="16" font-weight="500" x="13.504284" y="15" textLength="77.390625">LuaThread</tspan></text></g><text transform="translate(518 26)" fill="black"><tspan font-family="Times" font-size="24" font-weight="500" x="0" y="23" textLength="262.58203">Lua multithreading choices</tspan></text><g id="id36_Graphic"><path d="M 345.15002 245.475 L 667.84998 245.475 C 706.0208 245.475 737 275.5022 737 312.5 C 737 349.4978 706.0208 379.525 667.84998 379.525 L 345.15002 379.525 C 306.97919 379.525 276 349.4978 276 312.5 C 276 275.5022 306.97919 245.475 345.15002 245.475" fill="#69b1ff"/><path d="M 345.15002 245.475 L 667.84998 245.475 C 706.0208 245.475 737 275.5022 737 312.5 C 737 349.4978 706.0208 379.525 667.84998 379.525 L 345.15002 379.525 C 306.97919 379.525 276 349.4978 276 312.5 C 276 275.5022 306.97919 245.475 345.15002 245.475" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/><text transform="translate(327.1 301.5)" fill="black"><tspan font-family="Helvetica" font-size="18" font-weight="500" x="119.8629" y="18" textLength="119.07422">ConcurrentLua</tspan></text></g></g></g></svg>
diff --git a/docs/comparison.html b/docs/comparison.html
new file mode 100644
index 0000000..84ef9ca
--- /dev/null
+++ b/docs/comparison.html
@@ -0,0 +1,297 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2<!--
3 Comparison of Lua Lanes with other approaches
4-->
5
6<html>
7<head>
8 <meta name="description" content="Lua Lanes - Comparison" />
9 <meta name="keywords" content="Lua, Library, Multithreading, Threads, Rocks" />
10
11 <title>Lua Lanes - Comparison</title>
12</head>
13
14<body>
15
16<!-- comparisons +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
17<hr/>
18<h2 id="comparisons">Comparisons to other threading kits</h2>
19
20<p>
21A short comparison of Lanes with other existing Lua multithreading kits.
22</p>
23
24<table><tr><td width=40>
25 <td bgcolor="#ffffe0">
26<pre>
27=============
28 Lua Lanes
29=============
30
31With the introduction of Lindas (Jun-2008), Lua Lanes simplifies its API while
32simultaneously adding more power and speed.
33
34Pros:
35 - regular Lua 5.1 module
36 - completely separate Lua states, one per OS thread
37 - message passing, or shared data using Lindas
38 - no application level locking, ever
39 - scales well, up to 1000's of threads
40 - priorities (-2..+2) for launched threads
41 - threads are cancellable (with complete cleanup)
42 - timeouts on all pending operations
43 - thread contents are given as regular Lua functions; syntax checked early on,
44 syntax highlighting works
45 - standard libraries opened to subthreads can be granually selected
46 - fast stack-to-stack copies, via hidden "keeper states". No serialization needed.
47 - protects calls to 'require', allowing wide compatibility with existing
48 modules (and all, with minor changes)
49
50Cons:
51 - requires OS threads
52 - not utilizing network parallelism (all threads on one CPU)
53
54Sample:
55<<
56 require "lanes"
57
58 local function calculate(a,b,c)
59 if not a then
60 error "sample error; propagated to main lane when reading results"
61 end
62 return a+b+c
63 end
64
65 local h1= lanes.new(calculate)(1,2,3)
66 local h2= lanes.new(calculate)(10,20,30)
67 local h3= lanes.new(calculate)(100,200,300)
68
69 print( h1[1], h2[1], h3[1] ) -- pends for the results, or propagates error
70<<
71
72
73==================
74 Lua coroutines (by Lua authors)
75==================
76
77<A HREF="http://www.lua.org/manual/5.1/manual.html#2.11">http://www.lua.org/manual/5.1/manual.html#2.11</A>
78<A HREF="http://lua-users.org/wiki/CoroutinesTutorial">http://lua-users.org/wiki/CoroutinesTutorial</A>
79
80Lua coroutines is an integral part of Lua 5 itself. It is listed here, since
81it should be the _first_ multitasking mechanism to consider. It can also be
82used together with Lanes, or the other mechanisms listed below.
83
84Coroutines are very usable in provider/consumer situations, allowing you to
85queue Lua functions on an as-needed dataflow basis with each other.
86
87Pros:
88 - works with plain Lua (no extensions)
89 - works on any platform
90 - lightweight (no OS level threading or locking involved)
91
92Cons:
93 - co-operative, meaning your code will need to decide, who gets to run
94 - does not utilize multiple CPUs/cores
95
96Sample:
97
98 ..TBD: sample code doing the "child" "parent" output here (see below)..
99
100
101=============
102 LuaThread (by Diego Nehab)
103=============
104
105<A HREF="http://www.cs.princeton.edu/~diego/professional/luathread/">http://www.cs.princeton.edu/~diego/professional/luathread/</A>
106
107LuaThread provides thread creation, mutexes, condition variables, and inter-
108thread queues to the Lua scripts. It takes a C-kind of approach, where Lua
109globals are shared by the threads running, and need therefore to be guarded
110against multithreading conflicts.
111
112Whether this is exactly what you want, or whether a more loosely implemented
113multithreading (s.a. Lanes) would be better, is up to you. One can argue that
114a loose implementation is easier for the developer, since no application level
115lockings need to be considered.
116
117Pros:
118 - no marshalling overhead, since threads share the same Lua state
119
120Cons:
121 - requires a modified Lua core
122 - application level locking required
123
124Sample:
125&lt;&lt;
126 local function flood(output, word)
127 while 1 do
128 output:lock()
129 io.write(word, ", ")
130 output:unlock()
131 end
132 end
133
134 local output = thread.newmutex()
135 thread.newthread(flood, {output, "child"})
136 flood(output, "parent")
137&lt;&lt;
138
139
140=============
141 Lua Rings (by Roberto Ierusalimschy &amp; Tom&aacute;s Guisasola)
142=============
143
144<A HREF="http://www.keplerproject.org/rings/">http://www.keplerproject.org/rings/</A>
145
146".. library which provides a way to create new Lua states from within Lua.
147It also offers a simple way to communicate between the creator (master) and
148the created (slave) states."
149
150".. master can execute code in any of its slaves but each slave only has
151access to its master (or its own slaves)."
152
153Rings offers separate Lua states, but no multithreading. This makes it simple,
154but it won't use more than one CPU core. Other differences include:
155
156 - opens all Lua standard libraries for subthreads
157 (Lanes opens the needed ones)
158
159 - marshalls numbers, strings, booleans, userdata
160 (Lanes marshalls also non-cyclic tables)
161
162 - "remotedostring" allows executing code in the master state
163 (Lanes does _not_ allow subthreads to trouble/modify master automatically,
164 to allow effective sandboxing. The same can be achieved by sending code
165 between the threads, but master needs to explicitly allow this = receive
166 a function and execute it)
167
168 - offers "Stable, a very simple API to manage a shared table at the master
169 state"
170 (Lanes 2008 offers keeper tables)
171
172Pros:
173 - "offers Stable, a very simple API to manage a shared table at the master
174 state"
175
176Cons:
177 - thread contents defined as strings, not Lua source as such; does not
178 give syntax check at file parsing, does not allow syntax highlight
179
180Sample:
181&lt;&lt;
182 require"rings"
183 S = rings.new ()
184
185 data = { 12, 13, 14, }
186 print (S:dostring ([[
187 aux = {}
188 for i, v in ipairs (arg) do
189 table.insert (aux, 1, v)
190 end
191 return unpack (aux)]], unpack (data))) -- true, 14, 13, 12
192
193 S:close ()
194&lt;&lt;
195
196
197==========================
198 Helper Threads Toolkit (by Javier Guerra G.)
199==========================
200
201<A HREF="http://luaforge.net/projects/helper-threads/">http://luaforge.net/projects/helper-threads/</A>
202
203"Provides a consistent framework to write non-blocking C libraries, with a Lua
204interface for starting tasks and managing the Futures, Queues and Threads."
205
206This seems like a companion of the "occasional threading" model (see below);
207Lua side is kept clear of multithreading, while C side can be "spawn" off to
208do things on the background.
209
210Pros:
211 - provides an "update" mechanism, allowing the (C) thread and controlling
212 Lua to interact during execution of the thread
213 - ...
214
215Cons:
216 - thread is "only for C code and it can't touch or access the Lua state",
217 in other words there is no Lua-side multithreading concept (by design)
218
219
220========================
221 Occasional threading (by Russ Cox)
222========================
223
224<A HREF="http://lua-users.org/lists/lua-l/2006-11/msg00368.html">http://lua-users.org/lists/lua-l/2006-11/msg00368.html</A>
225
226".. able to have certain C calls run in parallel with the [Lua] VM, but
227otherwise keep the VM single-threaded."
228
229That pretty much says it all.
230
231Pros:
232 - simple, yet providing for the "occasional" need to run really multithreaded
233 - can be made into a loadable module (says the message)
234
235Cons:
236 - only for occasional usage, the programming paradigm is still essentially
237 singlethreaded (by definition)
238 - not a real project, just a message on the Lua list (but a good one!)
239
240
241=================
242 ConcurrentLua
243=================
244
245<A TARGET="_blank" HREF="http://concurrentlua.luaforge.net/index.html"
246>http://concurrentlua.luaforge.net/index.html</A>
247
248ConcurrentLua is based on the Lua model for concurrency, namely coroutines, and
249extends this model by providing message-passing primitives.
250
251".. implementation of the share-nothing asynchronous message-passing model"
252
253".. process can check its mailbox for new messages at any time, and if there
254are any, they can be read in the order of arrival."
255
256".. processes in the system are implemented with Lua coroutines"
257
258".. still based on the cooperative multithreading model that Lua uses"
259
260Recent, released on 21 June 2008.
261
262Pros:
263 - From ground up designed for distributed computing (multiple computers,
264 not only CPU cores)
265 - Does not require a pre-emptive operating system
266
267Cons:
268 - Serialization must degrade raw performance in one-computer scenarios
269 (vs. stack-to-stack copying ala Lanes)
270 - Depends on LuaSocket and Copas modules.
271 - Each thread has a single mailbox tied to it (vs. separating threads and
272 connection resources)
273
274</pre>
275</td></tr></table>
276
277
278<!-- footnotes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
279<hr/>
280
281<p>For feedback, questions and suggestions:
282<UL>
283 <li><A HREF="http://luaforge.net/projects/lanes">Lanes @ LuaForge</A></li>
284 <li><A HREF="mailto:akauppi@gmail.com">the author</A></li>
285</UL>
286</p>
287
288<!--
289<font size="-1">
290<p>
2911) ...
292</p>
293</font>
294-->
295
296</body>
297</html>
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..956e691
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,951 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2<!--
3 Documentation for Lua Lanes
4-->
5
6<html>
7<head>
8 <meta name="description" content="Lua Lanes - multithreading in Lua" />
9 <meta name="keywords" content="Lua, Library, Multithreading, Threads, Rocks" />
10
11 <title>Lua Lanes - multithreading in Lua</title>
12</head>
13
14<body>
15<div class="header">
16<hr />
17
18<center>
19<table summary="Lua logo">
20 <tbody>
21 <tr>
22 <td align="center">
23 <a href="http://www.lua.org">
24 <img src="http://akauppi.googlepages.com/multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
25 <img src="http://akauppi.googlepages.com/multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
26 <img src="http://akauppi.googlepages.com/multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
27 <img src="http://akauppi.googlepages.com/multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
28 <img src="http://akauppi.googlepages.com/multi.png" alt="Lua" align="middle" border="0" height="120" width="128" />
29 </a></td>
30 </tr>
31 <tr>
32 <td align="center" valign="top"><h1>Lua Lanes - multithreading in Lua</h1>
33 </td>
34 </tr>
35 </tbody>
36</table>
37
38<p class="bar">
39 <a href="#description">Description</a> &middot;
40 <a href="#systems">Supported systems</a> &middot;
41 <a href="#installing">Building and Installing</a>
42</p><p class="bar">
43 <a href="#creation">Creation</a> &middot;
44 <a href="#status">Status</a> &middot;
45 <a href="#results">Results and errors</a>
46</p><p class="bar">
47 <a href="#cancelling">Cancelling</a> &middot;
48 <a href="#finalizers">Finalizers</a> &middot;
49 <a href="#lindas">Lindas</a> &middot;
50 <a href="#timers">Timers</a> &middot;
51 <a href="#locks">Locks etc.</a>
52</p><p class="bar">
53 <a href="#other">Other issues</a> &middot;
54 <a href="#changes">Change log</a>
55 <!-- ... -->
56
57<p><br/><font size="-1"><i>Copyright &copy; 2007-08 Asko Kauppi. All rights reserved.</i>
58 <br>Lua Lanes is published under the same <A HREF="http://en.wikipedia.org/wiki/MIT_License">MIT license</A> as Lua 5.1.
59 </p><p>This document was revised on 23-Jan-09, and applies to version 2.0.3.
60</font></p>
61
62</center>
63</div>
64
65
66<!-- description +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
67<hr/>
68<h2 id="description">Description</h2>
69
70<p>Lua Lanes is a Lua extension library providing
71 the possibility to run multiple Lua states in parallel. It is intended to
72 be used for optimizing performance on multicore CPU's and to study ways to make Lua programs naturally parallel to begin with.
73</p><p>
74 Lanes is included into your software by the regular
75 <tt>require "lanes"</tt> method. No C side programming is needed; all APIs are Lua side, and most existing extension modules should
76 work seamlessly together with the multiple lanes.
77</p><p>
78 See <A HREF="comparison.html">comparison</A> of Lua Lanes with other Lua multithreading solutions.
79</p><p>
80 <h3>Features:</h3>
81
82 <ul>
83 <li>Lanes have separated data, by default. Shared data is possible with Linda objects.
84 </li>
85 <li>Communications is separate of threads, using Linda objects.
86 </li>
87 <li>Data passing uses fast inter-state copies (no serialization required)</li>
88 </li>
89 <li>"Deep userdata" concept, for sharing userdata over multiple lanes
90 </li>
91 <li>Millisecond level timers, integrated with the Linda system.
92 </li>
93 <li>Threads can be given priorities -2..+2 (default is 0).
94 </li>
95 <li>Lanes are cancellable, with proper cleanup.
96 </li>
97 <li>No application level locking - ever!
98 </li>
99 </ul>
100
101
102<h3>Limitations:</h3>
103
104 <ul><li>coroutines are not passed between states
105 </li>
106 <li>sharing full userdata between states needs special C side
107 preparations (-&gt; <A HREF="#deep_userdata">deep userdata</A>)
108 </li>
109 <li>network level parallelism not included
110 </li>
111 </ul>
112</p>
113
114
115<!-- systems +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
116<hr/>
117<h2 id="systems">Supported systems</h2>
118
119<p>Lua Lanes supports the following operating systems:
120
121 <ul>
122 <li>Mac OS X PowerPC / Intel (10.4 and later)</li>
123 <li>Linux x86</li>
124 <li>Windows 2000/XP and later <font size="-1">(MinGW or Visual C++ 2005/2008)</font></li>
125<!--
126 Other OS'es here once people help test them. (and the tester's name)
127
128 Win64, BSD, Linux x64, Linux embedded, QNX, Solaris, ...
129-->
130 </ul>
131
132 <p>The underlying threading code can be compiled either towards Win32 API
133 or <a TARGET="_blank" HREF="http://en.wikipedia.org/wiki/POSIX_Threads">Pthreads</a>. Unfortunately, thread prioritation under Pthreads is a JOKE,
134 requiring OS specific tweaks and guessing undocumented behaviour. Other
135 features should be portable to any modern platform.
136 </p>
137</p>
138
139
140<!-- installing +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
141<hr/>
142<h2 id="installing">Building and Installing</h2>
143
144<p>Lua Lanes is built simply by <tt>make</tt> on the supported platforms
145(<tt>make-vc</tt> for Visual C++). See <tt>README</tt> for system specific
146details and limitations.
147</p>
148
149<p>To install Lanes, all you need are the <tt>lanes.lua</tt> and <tt>lua51-lanes.so|dll</tt>
150files to be reachable by Lua (see LUA_PATH, LUA_CPATH).
151
152Or use <A HREF="http://www.luarocks.org" TARGET="_blank">Lua Rocks</A> package management.
153</p>
154
155<pre>
156 > luarocks search lanes
157 ... output listing Lua Lanes is there ...
158
159 > luarocks install lanes
160 ... output ...
161</pre>
162
163
164<!-- launching +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
165<hr/>
166<h2 id="creation">Creation</h2>
167
168<p>The following sample shows preparing a function for parallel calling, and
169calling it with varying arguments. Each of the two results is calculated in
170a separate OS thread, parallel to the calling one. Reading the results
171joins the threads, waiting for any results not already there.
172</p>
173
174<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
175<pre>
176 require "lanes"
177
178 f= lanes.gen( function(n) return 2*n end )
179 a= f(1)
180 b= f(2)
181
182 print( a[1], b[1] ) -- 2 4
183</pre>
184</table>
185
186<p>
187<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
188 <code>func= lanes.gen( [libs_str | opt_tbl [, ...],] lane_func )
189 <br/><br/>
190 lane_h= func( ... )</code>
191</table>
192</p>
193</p><p>
194 The function returned by <tt>lanes.gen()</tt> is a "generator" for
195 launching any number of lanes. They will share code, options, initial globals,
196 but the particular arguments may vary. Only calling the generator function
197 actually launches a lane, and provides a handle for controlling it.
198<!--
199</p>
200<p>This prepares <tt>lane_func</tt> to be called in parallel. It does not yet start
201anything, but merely returns a <i>generator function</i> that can be called
202any number of times, with varying parameters. Each call will spawn a new lane.
203-->
204</p><p>
205Lanes automatically copies upvalues over to the new lanes, so you
206need not wrap all the required elements into one 'wrapper' function. If
207<tt>lane_func</tt> uses some local values, or local functions, they will be there
208also in the new lanes.
209</p><p>
210 <code>libs_str</code> defines the standard libraries made available to the
211 new Lua state:
212 <table>
213 <tr><td/><td>(nothing)</td><td>no standard libraries (default)</td></tr>
214 <tr><td width=40><td><tt>"base"</tt> or <tt>""</tt></td>
215 <td>root level names, <tt>print</tt>, <tt>assert</tt>, <tt>unpack</tt> etc.</td></tr>
216 <tr><td/><td><tt>"coroutine"</tt></td><td><tt>coroutine.*</tt> namespace <font size="-1">(part of base in Lua 5.1)</font></td></tr>
217 <tr><td/><td><tt>"debug"</tt></td><td><tt>debug.*</tt> namespace</td></tr>
218 <tr><td/><td><tt>"io"</tt></td><td><tt>io.*</tt> namespace</td></tr>
219 <tr><td/><td><tt>"math"</tt></td><td><tt>math.*</tt> namespace</td></tr>
220 <tr><td/><td><tt>"os"</tt></td><td><tt>os.*</tt> namespace</td></tr>
221 <tr><td/><td><tt>"package"</tt></td><td><tt>package.*</tt> namespace and <tt>require</tt></td></tr>
222 <tr><td/><td><tt>"string"</tt></td><td><tt>string.*</tt> namespace</td></tr>
223 <tr><td/><td><tt>"table"</tt></td><td><tt>table.*</tt> namespace</td></tr>
224 <br/>
225 <tr><td/><td><tt>"*"</tt></td><td>all standard libraries</td></tr>
226 </table>
227
228</p><p>
229 Initializing the standard libs takes a bit of time at each lane invocation.
230 This is the main reason why "no libraries" is the default.
231</p><p>
232
233 <code>opt_tbl</code> is a collection of named options to control the way
234 lanes are run:
235</p><p>
236 <table>
237 <tr valign=top><td/><td>
238 <code>.cancelstep</code> <br/><nobr>N / true</nobr></td>
239 <td>
240 By default, lanes are only cancellable when they enter a pending
241 <tt>:receive()</tt> or <tt>:send()</tt> call.
242 With this option, one can set cancellation check to occur every <tt>N</tt>
243 Lua statements. The value <tt>true</tt> uses a default value (100).
244 </td></tr>
245
246 <tr valign=top><td/><td>
247 <code>.globals</code> <br/>globals_tbl</td>
248 <td>
249 Sets the globals table for the launched threads. This can be used for giving
250 them constants.
251 </p><p>
252 The global values of different lanes are in no manner connected;
253 modifying one will only affect the particular lane.
254 </td></tr>
255
256 <tr valign=top><td width=40><td>
257 <code>.priority</code> <br/><nobr>-2..+2</nobr></td>
258 <td>The priority of lanes generated. -2 is lowest, +2 is highest.
259 <p>
260 Implementation and dependability of priorities varies
261 by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.
262 </td></tr>
263 </table>
264
265</p>
266
267<h3>Free running lanes</h3>
268
269<p>
270The lane handles are allowed to be 'let loose'; in other words you may execute
271a lane simply by:
272
273<pre>
274 lanes.gen( function() ... end ) ()
275</pre>
276
277Normally, this kind of lanes will be in an eternal loop handling messages.
278Since the lane handle is gone,
279there is no way to control such a lane from the outside, nor read its potential
280return values. Then again, such a lane does not even normally return.
281</p>
282
283
284<!-- status +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
285<hr/>
286<h2 id="status">Status</h2>
287
288<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
289 <code>str= lane_h.status</code>
290</table>
291
292<p>The current execution state of a lane can be read via its <tt>status</tt>
293member, providing one of these values: <sup>(<a href="#2">2</a></sup>
294
295 <table>
296 <tr><td width=40><td><tt>"pending"</tt></td><td>not started, yet</td></tr>
297 <tr><td/><td><tt>"running"</tt></td><td>running</td></tr>
298 <tr><td/><td><tt>"waiting"</tt></td><td>waiting at a Linda <tt>:receive()</tt> or <tt>:send()</tt></td></tr>
299 <tr><td/><td><tt>"done"</tt></td><td>finished executing (results are ready)</td></tr>
300 <tr><td/><td><tt>"error"</tt></td><td>met an error (reading results will propagate it)</td></tr>
301 <tr><td/><td><tt>"cancelled"</tt></td><td>received cancellation and finished itself</td></tr>
302 </table>
303</p><p>
304 This is similar to <tt>coroutine.status</tt>, which has: <tt>"running"</tt> /
305 <tt>"suspended"</tt> / <tt>"normal"</tt> / <tt>"dead"</tt>. Not using the
306 exact same names is intentional.
307</p>
308
309
310<!-- results +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
311<hr/>
312<h2 id="results">Results and errors</h2>
313
314<p>A lane can be waited upon by simply reading its results. This can be done
315in two ways.
316</p><p>
317
318<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
319 <code>[val]= lane_h[1]</code>
320</table>
321<p>
322Makes sure lane has finished, and gives its first (maybe only) return value.
323Other return values will be available in other <tt>lane_h</tt> indices.
324</p><p>
325If the lane ended in an error, it is propagated to master state at this place.
326</p>
327
328<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
329 <code>[...]|[nil,err,stack_tbl]= lane_h:join( [timeout_secs] )</code>
330</table>
331<p>
332Waits until the lane finishes, or <tt>timeout</tt> seconds have passed.
333Returns <tt>nil</tt> on timeout, <tt>nil,err,stack_tbl</tt> if the lane hit an error,
334or the return values of the lane. Unlike in reading the results in table
335fashion, errors are not propagated.
336</p><p>
337<tt>stack_tbl</tt> is an array of "&lt;filename&gt;:&lt;line&gt;" strings,
338describing where the error was thrown. Use <tt>table.concat()</tt> to format
339it to your liking (or just ignore it).
340</p><p>
341If you use <tt>:join</tt>, make sure your lane main function returns
342a non-nil value so you can tell timeout and error cases apart from succesful
343return (using the <tt>.status</tt> property may be risky, since it might change
344between a timed out join and the moment you read it).
345</p><p>
346
347<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
348<pre>
349 require "lanes"
350
351 f= lanes.gen( function() error "!!!" end )
352 a= f(1)
353
354 --print( a[1] ) -- propagates error
355
356 v,err= a:join() -- no propagation
357 if v==nil then
358 error( "'a' faced error"..tostring(err) ) -- manual propagation
359 end
360</pre>
361</table>
362
363
364<!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
365<hr/>
366<h2 id="cancelling">Cancelling</h2>
367
368<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
369 <code>bool= lane_h:cancel( [timeout_secs=0.0,] [force_kill_bool=false] )</code>
370</table>
371
372<p>Sends a cancellation request to the lane. If <tt>timeout_secs</tt> is non-zero, waits
373for the request to be processed, or a timeout to occur.
374Returns <tt>true</tt> if the lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status)
375or if the cancellation was fruitful within timeout period.
376</p><p>
377If the lane is still running and <tt>force_kill</tt> is <tt>true</tt>, the
378OS thread running the lane is forcefully killed. This means no GC, and should
379generally be the last resort.
380</p>
381<p>Cancellation is tested before going to sleep in <tt>receive()</tt> or <tt>send()</tt> calls
382and after executing <tt>cancelstep</tt> Lua statements. A currently pending <tt>receive</tt>
383or <tt>send</tt> call is currently not awakened, and may be a reason for a non-detected cancel.
384</p>
385
386
387<!-- finalizers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
388<hr/>
389<h2 id="finalizers">Finalizers</h2>
390
391<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
392 <code>set_finalizer( finalizer_func )</code>
393 <br/><br/>
394 <code>void= finalizer_func( [error] )</code>
395</table>
396
397<p>The <tt>error</tt> call is used for throwing exceptions in Lua. What Lua
398does not offer, however, is scoped <a href="http://en.wikipedia.org/wiki/Finalizer">finalizers</a>
399that would get called when a certain block of instructions gets exited, whether
400through peaceful return or abrupt <tt>error</tt>.
401</p>
402<p>Since 2.0.3, Lanes prepares a function <tt>set_finalizer</tt> for doing this.
403Any functions given to it will be called in the lane Lua state, just prior to
404closing it. They are not called in any particular order.
405</p>
406<p>An error in a finalizer itself overrides the state of the regular chunk
407(in practise, it would be highly preferable <i>not</i> to have errors in finalizers).
408If one finalizer errors, the others may not get called.
409</p>
410
411
412<!-- lindas +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
413<hr/>
414<h2 id="lindas">Lindas</h2>
415
416<p>Communications between lanes is completely detached from the lane handles
417themselves. By itself, a lane can only provide return values once it's finished,
418or throw an error. Needs to communicate during runtime are handled by <A HREF="http://en.wikipedia.org/wiki/Linda_%28coordination_language%29" TARGET="_blank">Linda objects</A>, which are
419<A HREF="#deep_userdata">deep userdata</A> instances. They can be provided to a lane
420as startup parameters, upvalues or in some other Linda's message.
421</p><p>
422Access to a Linda object means a lane can read or write to any of its data
423slots. Multiple lanes can be accessing the same Linda in parallel. No application
424level locking is required; each Linda operation is atomic.
425</p><p>
426
427<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
428<pre>
429 require "lanes"
430
431 local linda= lanes.linda()
432
433 local function loop( max )
434 for i=1,max do
435 print( "sending: "..i )
436 linda:send( "x", i ) -- linda as upvalue
437 end
438 end
439
440 a= lanes.gen("",loop)( 10000 )
441
442 while true do
443 local val= linda:receive( 3.0, "x" ) -- timeout in seconds&nbsp;
444 if val==nil then
445 print( "timed out" )
446 break
447 end
448 print( "received: "..val )
449 end
450</pre>
451</table>
452
453</p>
454<p>Characteristics of the Lanes implementation of Lindas are:
455
456<ul>
457 <li>keys can be of number, string or boolean type
458 </li>
459 <li>values can be any type supported by inter-state copying (same limits
460 as for function parameters and upvalues)
461 </li>
462 <li>consuming method is <tt>:receive</tt> (not in)
463 </li>
464 <li>non-consuming method is <tt>:get</tt> (not rd)
465 </li>
466 <li>two producer-side methods: <tt>:send</tt> and <tt>:set</tt> (not out)
467 </li>
468 <li><tt>send</tt> allows for sending multiple values -atomically- to a
469 given key
470 </li>
471 <li><tt>receive</tt> can wait for multiple keys at once
472 </li>
473 <li>individual keys' queue length can be limited, balancing speed differences
474 in a producer/consumer scenario (making <tt>:send</tt> wait)
475 </li>
476</ul>
477</p>
478
479<p>
480<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
481 <code>h= lanes.linda()</code>
482 <br/><br/>
483 <code>bool= h:send( [timeout_secs,] key, ... )</code>
484 <br/>
485 <code>[val, key]= h:receive( [timeout_secs,] key [, ...] )</code>
486 <br/><br/>
487 <code>= h:limit( key, n_uint )</code>
488</table>
489
490<p>The <tt>send</tt> and <tt>receive</tt> methods use Linda keys as FIFO stacks
491(first in, first out). Timeouts are given in seconds (millisecond accuracy).
492If using numbers as the first Linda key, one must explicitly give <tt>nil</tt>
493as the timeout parameter to avoid ambiguities.
494</p><p>
495By default, stack sizes are unlimited but limits can be
496enforced using the <tt>limit</tt> method. This can be useful to balance execution
497speeds in a producer/consumer scenario.
498</p><p>
499Note that any number of lanes can be reading or writing a Linda. There can be
500many producers, and many consumers. It's up to you.
501</p>
502<p><tt>send</tt> returns <tt>true</tt> if the sending succeeded, and <tt>false</tt>
503if the queue limit was met, and the queue did not empty enough during the given
504timeout.
505</p><p>
506Equally, <tt>receive</tt> returns a value and the key that provided the value,
507or nothing for timeout. Note that <tt>nil</tt>s can be sent and received;
508the <tt>key</tt> value will tell it apart from a timeout.
509</p><p>
510Multiple values can be sent to a given key at once, atomically (the send will
511fail unless all the values fit within the queue limit). This can be useful for
512multiple producer scenarios, if the protocols used are giving data in streams
513of multiple units. Atomicity avoids the producers from garbling each others
514messages, which could happen if the units were sent individually.
515</p><p>
516
517When receiving from multiple slots, the keys are checked in order, which can
518be used for making priority queues.
519</p><p>
520
521<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
522 <code>linda_h:set( key, [val] )</code>
523 <br/>
524 <code>[val]= linda_h:get( key )</code>
525</table>
526
527</p><p>
528The table access methods are for accessing a slot without queuing or consuming.
529They can be used for making shared tables of storage among the lanes.
530</p><p>
531Writing to a slot overwrites existing value, and clears any possible queued
532entries. Table access and <tt>send</tt>/<tt>receive</tt> can be used together;
533reading a slot essentially peeks the next outcoming value of a queue.
534</p>
535
536<!--
537<p>
538<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
539 <code>lightuserdata= linda_h:deep()</code>
540</table>
541
542<p>There is one more method that is not required in applications, but
543discussing it is good for a preview of how deep userdata works.
544</p><p>
545Because proxy objects (<tt>linda_h</tt>) are just pointers to the real, deep
546userdata, they cannot be used to identify a certain Linda from the others.
547The internal timer system needs to do this, and the <tt>:deep()</tt> method
548has been added for its use. It returns a light userdata pointing to the
549<i>actual</i> deep object, and thus can be used for seeing, which proxies actually
550mean the same underlying object. You might or might not need a similar system
551with your own deep userdata.
552</p>
553-->
554
555
556<h3>Granularity of using Lindas</h3>
557
558<p>A single Linda object provides an infinite number of slots, so why would
559you want to use several?
560</p><p>There are some important reasons:
561
562<ul>
563 <li>Access control. If you don't trust certain code completely, or just
564 to modularize your design, use one Linda for one usage and another one
565 for the other. This keeps your code clear and readable. You can pass
566 multiple Linda handles to a lane with practically no added cost.
567 </li>
568
569 <li>Namespace control. Linda keys have a "flat" namespace, so collisions
570 are possible if you try to use the same Linda for too many separate uses.
571 </li>
572
573 <li>Performance. Changing any slot in a Linda causes all pending threads
574 for that Linda to be momentarily awakened (at least in the C level).
575 This can degrade performance due to unnecessary OS level context switches.
576 </li>
577</ul>
578
579On the other side, you need to use a common Linda for waiting for multiple
580keys. You cannot wait for keys from two separate Linda objects at the same
581time.
582</p><p>
583<font size="-1">Actually, you can. Make separate lanes to wait each, and then multiplex those
584events to a common Linda, but... :).</font>
585</p>
586
587
588<!-- timers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
589<hr/>
590<h2 id="timers">Timers</h2>
591
592<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td>
593 <code>= lanes.timer( linda_h, key, date_tbl|first_secs [,period_secs] )</code>
594</table>
595
596<p>
597Timers can be run once, or in a reoccurring fashion (<tt>period_secs > 0</tt>).
598The first occurrence can be given either as a date or as a relative delay in seconds.
599The <tt>date</tt> table is like what <tt>os.date("*t")</tt> returns, in the
600local time zone.
601</p><p>
602Once a timer expires, the <tt>key</tt> is set with the current time
603(in seconds, same offset as <tt>os.time()</tt> but with millisecond accuracy).
604The key can be waited upon using the regular Linda <tt>:receive()</tt>
605method.
606</p><p>
607A timer can be stopped simply by <tt>first_secs=0</tt> and no period.
608</p><p>
609
610<table border=1 bgcolor="#FFFFE0" width=500><tr><td>
611<pre>
612 require "lanes"
613
614 local linda= lanes.linda()
615
616 -- First timer once a second, not synchronized to wall clock
617 --
618 lanes.timer( linda, "sec", 1, 1 )
619
620 -- Timer to a future event (next even minute); wall clock synchronized&nbsp;
621 --
622 local t= os.date( "*t", os.time()+60 ) -- now + 1min
623 t.sec= 0
624
625 lanes.timer( linda, "min", t, 60 ) -- reoccur every minute (sharp)
626
627 while true do
628 local v,key= linda:receive( "sec", "min" )
629 print( "Timer "..key..": "..v )
630 end
631</pre>
632</table>
633
634</p><p>
635NOTE: Timer keys are set, not queued, so missing a beat is possible especially
636if the timer cycle is extremely small. The key value can be used to know the
637actual time passed.
638</p><p>
639<table>
640 <tr><td valign=top><nobr><i>Design note:</i></nobr>&nbsp;</td>
641 <td>
642<font size="-1">
643Having the API as <tt>lanes.timer()</tt> is intentional. Another
644alternative would be <tt>linda_h:timer()</tt> but timers are not traditionally
645seen to be part of Lindas. Also, it would mean any lane getting a Linda handle
646would be able to modify timers on it. A third choice could
647be abstracting the timers out of Linda realm altogether (<tt>timer_h= lanes.timer( date|first_secs, period_secs )</tt>)
648but that would mean separate waiting functions for timers, and lindas. Even if
649a linda object and key was returned, that key couldn't be waited upon simultaneously
650with one's general linda events.
651The current system gives maximum capabilities with minimum API, and any smoothenings
652can easily be crafted in Lua at the application level.
653</font>
654 </td>
655 </tr>
656</table>
657</p>
658
659
660<!-- locks +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
661<hr/>
662<h2 id="locks">Locks etc.</h2>
663
664<p>
665Lanes does not generally require locks or critical sections to be used, at all.
666If necessary, a limited queue can be used to emulate them. <tt>lanes.lua</tt>
667offers some sugar to make it easy:
668</p><p>
669
670<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td><pre>
671 lock_func= lanes.genlock( linda_h, key [,N_uint=1] )
672
673 lock_func( M_uint ) -- acquire
674 ..
675 lock_func( -M_uint ) -- release
676</table>
677</p><p>
678
679The generated function acquires M entries from the N available, or releases
680them if the value is negative. The acquiring call will suspend the lane, if necessary.
681Use <tt>M=N=1</tt> for a critical section lock (only one lane allowed to enter).
682</p><p>
683
684Note: The locks generated are <u>not recursive</u>. That would need another
685kind of generator, which is currently not implemented.
686</p><p>
687
688Similar sugar exists for atomic counters:
689</p><p>
690
691<table border=1 bgcolor="#E0E0FF" cellpadding=10><tr><td><pre>
692 atomic_func= lanes.genatomic( linda_h, key [,initial_num=0.0] )
693
694 new_num= atomic_func( [diff_num=+1.0] )
695</table>
696</p><p>
697
698Each time called, the generated function will change <tt>linda[key]</tt>
699atomically, without other lanes being able to interfere. The new value is
700returned. You can use either <tt>diff 0.0</tt> or <tt>get</tt> to just read the current
701value.
702</p><p>
703
704Note that the generated functions can be passed on to other lanes.
705</p>
706
707
708<!-- others +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
709<hr/>
710<h2 id="other">Other issues</h2>
711
712<h3>Limitations on data passing</h3>
713
714<p>Data passed between lanes (either as starting parameters, return values, upvalues or via Lindas) must conform to the following:
715</p>
716<p><ul>
717 <li>Booleans, numbers, strings, light userdata, Lua functions and tables of such can always be passed.
718 </li>
719 <li>Cyclic tables and/or duplicate references are allowed and reproduced appropriately,
720 but only <u>within the same transmission</u>.
721 <ul>
722 <li>using the same source table in multiple Linda messages keeps no ties between the tables
723 </li>
724 </ul>
725 </li>
726 <li>Objects (tables with a metatable) are copyable between lanes.
727 <ul>
728 <li>metatables are assumed to be immutable; they are internally indexed and only copied once
729 per each type of objects per lane
730 </li>
731 </ul>
732 </li>
733 <li>C functions (<tt>lua_CFunction</tt>) referring to <tt>LUA_ENVIRONINDEX</tt> or <tt>LUA_REGISTRYINDEX</tt> might not
734 work right in the target
735 <ul>
736 <li>rather completely re-initialize a module with <tt>require</tt> in the target lane
737 </li>
738 </ul>
739 </li>
740 <li>Full userdata can be passed only if it's prepared using the <A HREF="#deep_userdata">deep userdata</A>
741 system, which handles its lifespan management
742 <ul>
743 <li>in particular, lane handles cannot be passed between lanes
744 </li>
745 </ul>
746 </li>
747 <li>coroutines cannot be passed
748 </li>
749</ul>
750</p>
751
752
753<h3>Required of module makers</h3>
754
755<p>
756Most Lua extension modules should work unaltered with Lanes.
757If the module simply ties C side features to Lua, everything is fine without
758alterations. The <tt>luaopen_...()</tt> entry point will be called separately for each
759lane, where the module is <tt>require</tt>'d from.
760</p><p>
761If it, however, also does one-time C side initializations, these
762should be covered into a one-time-only construct such as below.
763</p><p>
764
765<table><tr><td width=40>
766 <td bgcolor="#ffffe0">
767<pre>
768 int luaopen_module( lua_State *L )
769 {
770 static char been_here; /* 0 by ANSI C */
771
772 /* Calls to 'require' serialized by Lanes; this is safe.&nbsp;&nbsp;
773 */
774 if (!been_here) {
775 been_here= 1;
776 ... one time initializations ...
777 }
778
779 ... binding to Lua ...
780 }
781</pre>
782</td></tr></table>
783</p>
784
785
786<h3 id="shared_userdata">Deep userdata in your own apps</h3>
787
788<p>
789The mechanism Lanes uses for sharing Linda handles between separate Lua states
790can be used for custom userdata as well. Here's what to do.
791</p>
792<ol>
793 <li>Provide an <i>identity function</i> for your userdata, in C. This function is
794used for creation and deletion of your deep userdata (the shared resource),
795and for making metatables for the state-specific proxies for accessing it.
796Take a look at <tt>linda_id</tt> in <tt>lanes.c</tt>.
797 </li>
798 <li>Create your userdata using <tt>luaG_deep_userdata()</tt>, which is
799 a Lua-callable function. Given an <tt>idfunc</tt>, it sets up the support
800 structures and returns a state-specific proxy userdata for accessing your
801 data. This proxy can also be copied over to other lanes.
802 </li>
803 <li>Accessing the deep userdata from your C code, use <tt>luaG_todeep()</tt>
804 instead of the regular <tt>lua_touserdata()</tt>.
805 </li>
806</ol>
807
808<p>Deep userdata management will take care of tying to <tt>__gc</tt> methods,
809and doing reference counting to see how many proxies are still there for
810accessing the data. Once there are none, the data will be freed through a call
811to the <tt>idfunc</tt> you provided.
812</p>
813<p><b>NOTE</b>: The lifespan of deep userdata may exceed that of the Lua state
814that created it. The allocation of the data storage should not be tied to
815the Lua state used. In other words, use <tt>malloc</tt>/<tt>free</tt> or
816similar memory handling mechanism.
817</p>
818
819
820<h3>Lane handles don't travel</h3>
821
822<p>
823Lane handles are not implemented as deep userdata, and cannot thus be
824copied across lanes. This is intentional; problems would occur at least when
825multiple lanes were to wait upon one to get ready. Also, it is a matter of
826design simplicity.
827</p><p>
828The same benefits can be achieved by having a single worker lane spawn all
829the sublanes, and keep track of them. Communications to and from this lane
830can be handled via a Linda.
831</p>
832
833
834<h3>Beware with print and file output</h3>
835
836<p>
837In multithreaded scenarios, giving multiple parameters to <tt>print()</tt>
838or <tt>file:write()</tt> may cause them to be overlapped in the output,
839something like this:
840
841<pre>
842 A: print( 1, 2, 3, 4 )
843 B: print( 'a', 'b', 'c', 'd' )
844
845 1 a b 2 3 c d 4
846</pre>
847
848Lanes does not protect you from this behaviour. The thing to do is either to
849concentrate your output to a certain lane per stream, or to concatenate output
850into a single string before you call the output function.
851</p>
852
853
854<h3 id="performance">Performance considerations</h3>
855
856<p>
857Lanes is about making multithreading easy, and natural in the Lua state of mind.
858Expect performance not to be an issue, if your program is logically built.
859Here are some things one should consider, if best performance is vital:
860</p><p>
861<ul>
862 <li>Data passing (parameters, upvalues, Linda messages) is generally fast,
863 doing two binary state-to-state copies (from source state to hidden state,
864 hidden state to target state). Remember that not only the function you
865 specify but also its upvalues, their upvalues, etc. etc. will get copied.
866 </li>
867 <li>Lane startup is fast (1000's of lanes a second), depending on the
868 number of standard libraries initialized. Initializing all standard libraries
869 is about 3-4 times slower than having no standard libraries at all. If you
870 throw in a lot of lanes per second, make sure you give them minimal necessary
871 set of libraries.
872 </li>
873 <li>Waiting Lindas are woken up (and execute some hidden Lua code) each
874 time <u>any</u> key in the Lindas they are waiting for are changed. This
875 may give essential slow-down (not measured, just a gut feeling) if a lot
876 of Linda keys are used. Using separate Linda objects for logically separate
877 issues will help (which is good practise anyhow).
878 </li>
879 <li>Linda objects are light. The memory footprint is two OS-level signalling
880 objects (<tt>HANDLE</tt> or <tt>pthread_cond_t</tt>) for each, plus one
881 C pointer for the proxies per each Lua state using the Linda. Barely nothing.
882 </li>
883 <li>Timers are light. You can probably expect timers up to 0.01 second
884 resolution to be useful, but that is very system specific. All timers are
885 merged into one main timer state (see <tt>timer.lua</tt>); no OS side
886 timers are utilized.
887 </li>
888 <li>Lindas are hashed to a fixed number of "keeper states", which are a locking entity.
889 If you are using a lot of Linda objects,
890 it may be useful to try having more of these keeper states. By default,
891 only one is used (see <tt>KEEPER_STATES_N</tt>), but this is an implementation detail.
892 </li>
893</ul>
894</p>
895
896
897<h3 id="cancelling_cancel">Cancelling cancel</h3>
898
899<p>
900Cancellation of lanes uses the Lua error mechanism with a special lightuserdata
901error sentinel.
902If you use <tt>pcall</tt> in code that needs to be cancellable
903from the outside, the special error might not get through to Lanes, thus
904preventing the Lane from being cleanly cancelled. You should throw any
905lightuserdata error further.
906</p><p>
907This system can actually be used by application to detect cancel, do your own
908cancellation duties, and pass on the error so Lanes will get it. If it does
909not get a clean cancellation from a lane in due time,
910it may forcefully kill the lane.
911</p><p>
912The sentinel is exposed as <tt>lanes.cancel_error</tt>, if you wish to use
913its actual value.
914</p>
915
916
917
918<!-- change log +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
919<hr/>
920<h2 id="changes">Change log</h2>
921
922<p>
923Jan-2009 (2.0.3):
924<ul>
925 <li>Added 'finalizer' to lane options. (TBD: not implemented yet!)
926 </li>
927 <li>Added call stack to errors coming from a lane.
928 </li>
929</ul>
930
931Jul-2008 (2.0):
932<ul>
933 <li>Too many changes to list (you'll need to re-read this manual)
934 </li>
935</ul>
936</p>
937
938<!-- footnotes +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
939<hr/>
940
941<p>For feedback, questions and suggestions:
942<UL>
943 <li><A HREF="http://luaforge.net/projects/lanes">Lanes @ LuaForge</A></li>
944 <li><A HREF="mailto:akauppi@gmail.com">the author</A></li>
945</UL>
946</p>
947
948<p><br/></p>
949
950</body>
951</html>
diff --git a/docs/multi.png b/docs/multi.png
new file mode 100644
index 0000000..f527aff
--- /dev/null
+++ b/docs/multi.png
Binary files differ
diff --git a/docs/performance.ods b/docs/performance.ods
new file mode 100644
index 0000000..541cc8e
--- /dev/null
+++ b/docs/performance.ods
Binary files differ