aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUGS111
-rw-r--r--CHANGES74
-rw-r--r--COPYRIGHT2
-rw-r--r--Makefile7
-rw-r--r--TODO17
-rw-r--r--docs/comparison.html28
-rw-r--r--docs/index.html44
-rw-r--r--lanes-2.0-2.rockspec95
-rw-r--r--lanes-2.0.2.tgzbin0 -> 312965 bytes
-rw-r--r--setup-vc.cmd8
-rw-r--r--src/keeper.lua4
-rw-r--r--src/lanes.c732
-rw-r--r--src/lanes.lua33
-rw-r--r--src/threading.c9
-rw-r--r--src/tools.c260
-rw-r--r--src/tools.h2
-rw-r--r--tests/appendud.lua58
-rw-r--r--tests/basic.lua52
-rw-r--r--tests/func_is_string.lua12
-rw-r--r--xcode/xcode.xcodeproj/abisoft.mode11460
-rw-r--r--xcode/xcode.xcodeproj/abisoft.pbxuser411
-rw-r--r--xcode/xcode.xcodeproj/project.pbxproj268
-rw-r--r--xcode/xcode.xcodeproj/soumya.pbxuser124
23 files changed, 3319 insertions, 492 deletions
diff --git a/BUGS b/BUGS
index d25cc0e..9ae6db5 100644
--- a/BUGS
+++ b/BUGS
@@ -1,6 +1,117 @@
1 1
2BUGS: 2BUGS:
3 3
4- Reported by Pierre LeMoine (Dec-2009:
5<<
6Hi!
7I think i've located an error in Lanes. When a finalizer is called, it
8receive two tables. The second one seems to be the table containing
9the finalizers. The attached test reproduces the error, and is tested
10on binaries built by myself and from the LfW project.
11The following line from run_finalizers in lanes.c seems to be wrong to me:
12
13 error_index= (lua_rc!=0) ? tbl_index-1 : 0; // absolute indices
14
15I think it should be -2 there, since the stack at this point should look like
16[-1] finalizer table <- tbl_index
17[-2] stack table
18[-3] error string
19
20Also, in some places, checks for valid returns from lua_toLinda are
21missing, leading to crashes. (for example, linda.get)
22
23Sometimes when i use lanes i get a "recursive use of upvalues"-error,
24i fail to see how upvalues can be recursive? =)
25
26/Pierre
27<<
28
29
30- Reported by Benoit Germain (Dec-2009):
31<<
32Doc says :
33
34The current execution state of a lane can be read via its status member, providing one of these values:
35
36
37"waiting" waiting at a Linda :receive() or :send()
38
39
40
41But code and test say otherwise : lane status remains « running » even when waiting on a Linda operation, which is quite understandable since nowhere in the code status is changed to WAITING. This is a problem for me because my lanes are consumers waiting for commands on a linda. « waiting » status is the only means I have to ensure that a command is not currently being processed. Therefore the fix, to make Lanes behave as the documentation states :
42
43LUAG_FUNC( linda_receive ) {
44 ...
45 // BBB HACK: fetch the lane object to update the status
46 {
47 struct s_lane *s;
48 enum e_status prev_status;
49 STACK_GROW(L,1);
50
51 STACK_CHECK(L)
52 lua_pushlightuserdata( L, CANCEL_TEST_KEY );
53 lua_rawget( L, LUA_REGISTRYINDEX );
54 s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil
55 lua_pop(L,1);
56 STACK_END(L,0)
57 if( s)
58 {
59 prev_status = s->status;
60 s->status = WAITING;
61 }
62 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout ))
63 {
64 if( s) s->status = prev_status;
65 break;
66 }
67 if( s) s->status = prev_status;
68 }
69
70Of course, the same has to be done in linda_send, and lane structure retrieval could be factorized with the cancel_test. Anyway, what I am concerned about now is whether I missed something or not. Can the lane status change while waiting, so that restoring the previous value could cause problems?
71<<
72
73
74- The use of 'static' and "one time" initialization of things is not suitable
75to a situation where a Lua state is run, using Lanes, then terminated. If
76another Lua state later is launched, the initializations will get cramped.
77
78Reported by Boris Ouretskey (25-Jun-09)
79
80
81- a 'require "lanes"' and speedy exit from the process causes a segfault
82 on ArchLinux (reported by kkndrox@gmail.com 1-Jun-2009).
83
84 This issue is not reproducible on Ubuntu (8.04 or 9.04) and has not therefore
85 been fixed. A patch is welcome. The issue is most likely caused by the
86 Linda thread not being properly launched when the process itself already
87 quits.
88
89<<
90With Lanes 2.0.3, the following code *always* gives me a segmentation
91fault:
92
93-- begin
94require("lanes")
95-- end
96
97But this:
98
99-- begin
100require("lanes")
101garbagecollect('collect')
102-- end
103
104always work.
105
106Based on this experimentation, if I require lanes and the program end
107without any garbage collecting, I receive a segmentation fault.
108I'm using Arch Linux (32bits), Lua 5.1.4 and it was compiled with gcc 4.3
109<<
110
111 Also simply waiting a bit ('os.execute("sleep 1")') avoids the crash.
112
113
4- tests/irayo_closure.lua fails (trouble with setting globals right 114- tests/irayo_closure.lua fails (trouble with setting globals right
5 for functions carried over to another Lua state) 115 for functions carried over to another Lua state)
6 116
117- "make appendud" causes a segfault on OS X PowerPC.
diff --git a/CHANGES b/CHANGES
index ae4da3c..c41e36d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,11 +3,51 @@ CHANGES:
3 3
4CHANGE X: 4CHANGE X:
5 5
6CHANGE 21 (bugfixes) BGe 3-Jan-2011:
7 Several fixes by Martin Krpan:
8 - linda_send was waiting on the wrong signal
9 - buildfix when using i586-mingw32msvc-gcc cross compiler
10 - lanes_h:cancel() returns a boolean as it should
11 - timers could get blocked sometimes because they were initialized with negative values
12 - prepare_timeout could generate an illegal setting
13
14CHANGE 20 BGe 3-Dec-2010:
15 Enable to specify a string as lane code instead of a function so that we dont use lua_dump, which
16 isn't supported by LuaJIT.
17
18CHANGE 19 BGe 2-Dec-2010:
19 No longer rely on global function 'tostring' to generate unique identifiers when caching data being transfered through la linda. Should fix a compatilibity issue with LuaJIT2.
20
21CHANGE 18 BGe 6-Oct-2010:
22 Fixed 'memory leak' in some situations where a free running lane is collected before application shutdown
23 A bit of code cleanup
24
25CHANGE 17 BGe 21-Sept-2010:
26 Fixed stupid compilation errors.
27
28CHANGE 16 PLM 24-Aug-2010:
29 Releasing memory at gc / atexit.
30 Finalizers actually get error strings.
31 Fixed missing argument propagation in lane:cancel
32 Added variable threadName sent trough globals-table. Set in s_lane, and in debuggers on windows.
33 Added argument checking for linda-objects, where missing them caused crashes.
34
35CHANGE 15 (minor) BGe 27-Jul-2010:
36 Version bump for a true upgrade release (2.0.4 package was only a renamed 2.0.3)
37
38CHANGE 14 (bug fix) BGe 09-Jul-2010:
39 Fixed lane status to be correctly returned as "waiting" when it should.
40
41CHANGE 13 (fix for multithreaded host apps) AKa 24-Jun-2009:
42 <borisusun-at-gmail> mentioned Lanes expects the host application to be singlethreaded,
43 and there are troubles if Lanes is used from multiple threads, opened by the host
44 (before requiring Lanes). This is true, and fix should now be in place.
45
6CHANGE 12 (bug fix on Windows, 2.0.3) AKa 25-Jan-2009: 46CHANGE 12 (bug fix on Windows, 2.0.3) AKa 25-Jan-2009:
7 Did CHANGE 9 the way it should be done. 47 Did CHANGE 9 the way it should be done.
8 48
9CHANGE 11 (new feature, 2.0.3) AKa 23-Jan-2009: 49CHANGE 11 (new feature, 2.0.3) AKa 23-Jan-2009:
10 Finalizers ('set_finalizer()') for being able to do cleanup of a lane's 50 Finalizers ('set_finalizer()') for being able to do cleanup of a lane's
11 resources, whether it returned succesfully or via an error. 51 resources, whether it returned succesfully or via an error.
12 52
13CHANGE 10 (new feature, 2.0.3) AKa 23-Jan-2009: 53CHANGE 10 (new feature, 2.0.3) AKa 23-Jan-2009:
@@ -18,12 +58,12 @@ CHANGE 10 (new feature, 2.0.3) AKa 23-Jan-2009:
18CHANGE 9 (bug fix on Windows) AKa 10-Dec-2008 (> 2.0.2): 58CHANGE 9 (bug fix on Windows) AKa 10-Dec-2008 (> 2.0.2):
19 Applied patch from Kriss Daniels to avoid issues on 'now_time()' in Win32 59 Applied patch from Kriss Daniels to avoid issues on 'now_time()' in Win32
20 (http://luaforge.net/forum/forum.php?thread_id=22704&forum_id=1781). 60 (http://luaforge.net/forum/forum.php?thread_id=22704&forum_id=1781).
21 61
22CHANGE 8 (bug fix) AKa 26-Oct-2008: 62CHANGE 8 (bug fix) AKa 26-Oct-2008:
23 Avoids occasional segfault at process exit (on multicore CPUs). Does this 63 Avoids occasional segfault at process exit (on multicore CPUs). Does this
24 by keeping track of "free running" threads (s.a. the time thread) and 64 by keeping track of "free running" threads (s.a. the time thread) and
25 cancelling them at process exit. 65 cancelling them at process exit.
26 66
27 Tested (2.0.2) on Linux 64,x86, OS X, WinXP. 67 Tested (2.0.2) on Linux 64,x86, OS X, WinXP.
28 68
29CHANGE 7 (bug fix) AKa 15-Oct-2008: 69CHANGE 7 (bug fix) AKa 15-Oct-2008:
@@ -34,15 +74,15 @@ CHANGE 6 (bug fix) AKa 15-Oct-2008:
34 Added local caches of the following to src/lanes.lua (was otherwise getting 74 Added local caches of the following to src/lanes.lua (was otherwise getting
35 errors at least in 'tests/irayo_recursive.lua'). 75 errors at least in 'tests/irayo_recursive.lua').
36 76
37 local assert= assert 77 local assert= assert
38 local string_gmatch= assert( string.gmatch ) 78 local string_gmatch= assert( string.gmatch )
39 local select= assert( select ) 79 local select= assert( select )
40 local type= assert( type ) 80 local type= assert( type )
41 local pairs= assert( pairs ) 81 local pairs= assert( pairs )
42 local tostring= assert( tostring ) 82 local tostring= assert( tostring )
43 local error= assert( error ) 83 local error= assert( error )
44 local setmetatable= assert( setmetatable ) 84 local setmetatable= assert( setmetatable )
45 local rawget= assert( rawget ) 85 local rawget= assert( rawget )
46 86
47 Thanks to Irayo for detecting and reporting this. 87 Thanks to Irayo for detecting and reporting this.
48 88
@@ -55,17 +95,17 @@ CHANGE 4 (new feature):
55CHANGE 3 (bug fix) AKa 5-Aug-2008: 95CHANGE 3 (bug fix) AKa 5-Aug-2008:
56 The '__gc' method was not tied to thread userdata, at all. Caused memory 96 The '__gc' method was not tied to thread userdata, at all. Caused memory
57 lifespan problems at least on OS X when threads were cancelled (EINVAL). 97 lifespan problems at least on OS X when threads were cancelled (EINVAL).
58 98
59CHANGE 2 (bug fix) AKa 5-Aug-2008: 99CHANGE 2 (bug fix) AKa 5-Aug-2008:
60 Better calculation of timeouts, always making them absolute (even in Win32) 100 Better calculation of timeouts, always making them absolute (even in Win32)
61 to allow for events that wake the lane up but don't read/write the Linda 101 to allow for events that wake the lane up but don't read/write the Linda
62 key that it was observing. 102 key that it was observing.
63 103
64CHANGE 1 (bug fix) AKa 4-Aug-2008: 104CHANGE 1 (bug fix) AKa 4-Aug-2008:
65 Signalling woke up only one waiting thread, not all. This caused i.e. 105 Signalling woke up only one waiting thread, not all. This caused i.e.
66 receive to not wake up if there was another thread waiting on the same 106 receive to not wake up if there was another thread waiting on the same
67 Linda object. 107 Linda object.
68 108
69 PThread fix: using 'pthread_cond_broadcast()' instead of 'pthread_cond_signal()' 109 PThread fix: using 'pthread_cond_broadcast()' instead of 'pthread_cond_signal()'
70 Win32 fix: using manual events and 'PulseEvent()' 110 Win32 fix: using manual events and 'PulseEvent()'
71 111
diff --git a/COPYRIGHT b/COPYRIGHT
index 2930f19..d6b0008 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -6,7 +6,7 @@ For details and rationale, see http://www.lua.org/license.html
6 6
7=============================================================================== 7===============================================================================
8 8
9Copyright (C) 2007-09 Asko Kauppi, <akauppi@gmail.com> 9Copyright (C) 2007-11 Asko Kauppi, <akauppi@gmail.com>
10 10
11Permission is hereby granted, free of charge, to any person obtaining a copy 11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal 12of this software and associated documentation files (the "Software"), to deal
diff --git a/Makefile b/Makefile
index 4c0ff4b..b4a78cc 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,7 @@ test:
82 $(MAKE) objects 82 $(MAKE) objects
83 $(MAKE) fibonacci 83 $(MAKE) fibonacci
84 $(MAKE) recursive 84 $(MAKE) recursive
85 $(MAKE) func_is_string
85 86
86basic: tests/basic.lua $(_TARGET_SO) 87basic: tests/basic.lua $(_TARGET_SO)
87 $(_PREFIX) $(LUA) $< 88 $(_PREFIX) $(LUA) $<
@@ -143,6 +144,12 @@ finalizer: tests/finalizer.lua $(_TARGET_SO)
143error-test: tests/error.lua $(_TARGET_SO) 144error-test: tests/error.lua $(_TARGET_SO)
144 $(_PREFIX) $(LUA) $< 145 $(_PREFIX) $(LUA) $<
145 146
147appendud: tests/appendud.lua $(_TARGET_SO)
148 $(_PREFIX) $(LUA) $<
149
150func_is_string: tests/func_is_string.lua $(_TARGET_SO)
151 $(_PREFIX) $(LUA) $<
152
146#--- 153#---
147perftest-plain: tests/perftest.lua $(_TARGET_SO) 154perftest-plain: tests/perftest.lua $(_TARGET_SO)
148 $(MAKE) _perftest ARGS="$< $(N) -plain" 155 $(MAKE) _perftest ARGS="$< $(N) -plain"
diff --git a/TODO b/TODO
index 7c4c3d8..2846384 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,21 @@
1 1
2TODO: 2TODO:
3 3
4- Use of 'atexit()' is not good. It's possible to be called at "program (process)
5 exit", when the so might already be out. Tying to OS specific so cleanup
6 is way better.
7
4- Testing Lane killing (not cancellation, but actual killing) 8- Testing Lane killing (not cancellation, but actual killing)
9
10- Like luaproc: Lanes to have M:N relationship to kernel threads
11 (= give a maximum number of kernel threads to run, then juggle those to run a Lane,
12 until the lane suspends, blocks, or exits)
13 (default could be twice the kernel threads of the CPU count, or something.)
14
15- Like luaproc:
16"only the basic standard
17library and our own library are automatically loaded into each new Lua process. The re-
18maining standard libraries (io, os, table, string, math, and debug) are pre-registered and
19can be loaded with a standard call to Lua’s require function. "
20
21- Lanes so/dll to have a second interface; C code sending data to a linda of given void*
diff --git a/docs/comparison.html b/docs/comparison.html
index 84ef9ca..bebc68b 100644
--- a/docs/comparison.html
+++ b/docs/comparison.html
@@ -49,6 +49,7 @@ Pros:
49 49
50Cons: 50Cons:
51 - requires OS threads 51 - requires OS threads
52 - currently 1:1 mapping to OS threads (limits scalability and maybe performance)
52 - not utilizing network parallelism (all threads on one CPU) 53 - not utilizing network parallelism (all threads on one CPU)
53 54
54Sample: 55Sample:
@@ -70,6 +71,31 @@ Sample:
70<< 71<<
71 72
72 73
74===========
75 luaproc (by Skyrme, Rodriguez and Ierusalimschy)
76===========
77
78<A HREF="http://www.inf.puc-rio.br/~roberto/docs/ry08-05.pdf">http://www.inf.puc-rio.br/~roberto/docs/ry08-05.pdf</A>
79
80The PDF seems to be an authorative voyage into how Lua could handle multithreading,
81in a multicore "separate universes" manner (not like what coroutines already do).
82
83Pros:
84 - Tackles both multicore and network parallelism
85 - M:N relationship to kernel threads (one kernel thread runs multiple luaprocs)
86 - Simple (so they say)
87 - Lua author (Roberto) included
88 - Can be used also without _any_ OS threading support (works like Rings, then)
89
90Cons:
91 - Data passing for "strings, number, or booleans" only
92 "More complex types must be encoded in some form"
93 (serializing data is slower than the stack-to-stack copies used by i.e. Lanes)
94 (yet, serializing allows for network parallelism)
95 - Message passing is synchronous (only). The sender will wait until the
96 receiver has taken the message.
97
98
73================== 99==================
74 Lua coroutines (by Lua authors) 100 Lua coroutines (by Lua authors)
75================== 101==================
@@ -157,7 +183,7 @@ but it won't use more than one CPU core. Other differences include:
157 (Lanes opens the needed ones) 183 (Lanes opens the needed ones)
158 184
159 - marshalls numbers, strings, booleans, userdata 185 - marshalls numbers, strings, booleans, userdata
160 (Lanes marshalls also non-cyclic tables) 186 (Lanes also marshalls tables, functions, upvalues, ..)
161 187
162 - "remotedostring" allows executing code in the master state 188 - "remotedostring" allows executing code in the master state
163 (Lanes does _not_ allow subthreads to trouble/modify master automatically, 189 (Lanes does _not_ allow subthreads to trouble/modify master automatically,
diff --git a/docs/index.html b/docs/index.html
index 956e691..45b52bc 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -54,9 +54,9 @@
54 <a href="#changes">Change log</a> 54 <a href="#changes">Change log</a>
55 <!-- ... --> 55 <!-- ... -->
56 56
57<p><br/><font size="-1"><i>Copyright &copy; 2007-08 Asko Kauppi. All rights reserved.</i> 57<p><br/><font size="-1"><i>Copyright &copy; 2007-11 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. 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. 59 </p><p>This document was revised on 3-Jan-11, and applies to version 2.0.10.
60</font></p> 60</font></p>
61 61
62</center> 62</center>
@@ -195,6 +195,9 @@ joins the threads, waiting for any results not already there.
195 launching any number of lanes. They will share code, options, initial globals, 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 196 but the particular arguments may vary. Only calling the generator function
197 actually launches a lane, and provides a handle for controlling it. 197 actually launches a lane, and provides a handle for controlling it.
198 Alternatively, <tt>lane_func</tt> may be a string, in which case it will be compiled
199 in the lane. This is to be able to launch lanes whith LuaJIT,
200 which does not support lua_dump, used internally to transfer functions to the lane.
198<!-- 201<!--
199</p> 202</p>
200<p>This prepares <tt>lane_func</tt> to be called in parallel. It does not yet start 203<p>This prepares <tt>lane_func</tt> to be called in parallel. It does not yet start
@@ -237,7 +240,7 @@ also in the new lanes.
237 <tr valign=top><td/><td> 240 <tr valign=top><td/><td>
238 <code>.cancelstep</code> <br/><nobr>N / true</nobr></td> 241 <code>.cancelstep</code> <br/><nobr>N / true</nobr></td>
239 <td> 242 <td>
240 By default, lanes are only cancellable when they enter a pending 243 By default, lanes are only cancellable when they <u>enter</u> a pending
241 <tt>:receive()</tt> or <tt>:send()</tt> call. 244 <tt>:receive()</tt> or <tt>:send()</tt> call.
242 With this option, one can set cancellation check to occur every <tt>N</tt> 245 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). 246 Lua statements. The value <tt>true</tt> uses a default value (100).
@@ -250,7 +253,7 @@ also in the new lanes.
250 them constants. 253 them constants.
251 </p><p> 254 </p><p>
252 The global values of different lanes are in no manner connected; 255 The global values of different lanes are in no manner connected;
253 modifying one will only affect the particular lane. 256 modifying one will only affect the particular lane. Settings the variable 'threadName' in this table makes VS display the sent name instead of the normal thread name while debugging.
254 </td></tr> 257 </td></tr>
255 258
256 <tr valign=top><td width=40><td> 259 <tr valign=top><td width=40><td>
@@ -360,6 +363,12 @@ between a timed out join and the moment you read it).
360</pre> 363</pre>
361</table> 364</table>
362 365
366<p>
367If you want to wait for multiple lanes to finish (any of a set of lanes), use
368a <a href="#lindas">Linda</a> object. Give each lane a specific id, and send
369that id over a Linda once that thread is done (as the last thing you do).
370</p>
371
363 372
364<!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 373<!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
365<hr/> 374<hr/>
@@ -378,7 +387,7 @@ If 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 387OS thread running the lane is forcefully killed. This means no GC, and should
379generally be the last resort. 388generally be the last resort.
380</p> 389</p>
381<p>Cancellation is tested before going to sleep in <tt>receive()</tt> or <tt>send()</tt> calls 390<p>Cancellation is tested <u>before</u> 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> 391and 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. 392or <tt>send</tt> call is currently not awakened, and may be a reason for a non-detected cancel.
384</p> 393</p>
@@ -920,6 +929,30 @@ its actual value.
920<h2 id="changes">Change log</h2> 929<h2 id="changes">Change log</h2>
921 930
922<p> 931<p>
932Jan-2011 (2.0.10):
933<ul>
934 <li>linda_send was waiting on the wrong signal</li>
935 <li>buildfix when using i586-mingw32msvc-gcc cross compiler</li>
936 <li>lanes_h:cancel() returns a boolean as it should</li>
937 <li>timers could get blocked sometimes because they were initialized with negative values</li>
938 <li>prepare_timeout could generate an illegal setting</li>
939</ul>
940
941Dec-2010 (2.0.9):
942<ul>
943 <li>Fixed 'memory leak' in some situations where a free running lane is collected before application shutdown</li>
944 <li>Fix LuaJIT2 incompatibility (no 'tostring' hijack anymore)</li>
945 <li>Added support to generate a lane from a string</li>
946</ul>
947
948Aug-2010 (2.0.6):
949<ul>
950<li>Fixed some memory leaks</li>
951<li>Fixed error in passing parameters to finalizers</li>
952<li>Fixed missing argument propagation in lane:cancel</li>
953<li>Added thread name debugging in VS</li>
954</ul>
955
923Jan-2009 (2.0.3): 956Jan-2009 (2.0.3):
924<ul> 957<ul>
925 <li>Added 'finalizer' to lane options. (TBD: not implemented yet!) 958 <li>Added 'finalizer' to lane options. (TBD: not implemented yet!)
@@ -942,6 +975,7 @@ Jul-2008 (2.0):
942<UL> 975<UL>
943 <li><A HREF="http://luaforge.net/projects/lanes">Lanes @ LuaForge</A></li> 976 <li><A HREF="http://luaforge.net/projects/lanes">Lanes @ LuaForge</A></li>
944 <li><A HREF="mailto:akauppi@gmail.com">the author</A></li> 977 <li><A HREF="mailto:akauppi@gmail.com">the author</A></li>
978 <li><A HREF="http://www.lua.org/lua-l.html">the lua mailing list</A></li>
945</UL> 979</UL>
946</p> 980</p>
947 981
diff --git a/lanes-2.0-2.rockspec b/lanes-2.0-2.rockspec
new file mode 100644
index 0000000..407a622
--- /dev/null
+++ b/lanes-2.0-2.rockspec
@@ -0,0 +1,95 @@
1--
2-- Lanes rockspec
3--
4-- Ref:
5-- <http://luarocks.org/en/Rockspec_format>
6--
7-- History:
8-- AKa 1-Sep-2008: 2.0-2 (NOT sent to list): fixed VC++ not finding DLL issue
9-- AKa 20-Aug-2008: 2.0-1 sent to luarocks-developers
10--
11
12package = "Lanes"
13
14version = "2.0-2"
15
16source= {
17 url= "http://akauppi.googlepages.com/lanes-2.0.tgz",
18 md5= "27a807828de0bda3787dbcd2d4947019"
19}
20
21description = {
22 summary= "Multithreading support for Lua",
23 detailed= [[
24 Lua Lanes is a portable, message passing multithreading library
25 providing the possibility to run multiple Lua states in parallel.
26 ]],
27 license= "MIT/X11",
28 homepage="http://kotisivu.dnainternet.net/askok/lanes/",
29 maintainer="Asko Kauppi <akauppi@gmail.com>"
30}
31
32-- Q: What is the difference of "windows" and "win32"? Seems there is none;
33-- so should we list either one or both?
34--
35supported_platforms= { "win32",
36 "macosx",
37 "linux",
38 "freebsd", -- TBD: not tested
39 "msys", -- TBD: not supported by LuaRocks 1.0 (or is it?)
40}
41
42dependencies= {
43 "lua >= 5.1, < 5.2",
44}
45
46--
47-- Non-Win32: build using the Makefile
48-- Win32: build using 'make-vc.cmd' and "manual" copy of products
49--
50-- TBD: How is MSYS treated? We'd like (really) it to use the Makefile.
51-- It should be a target like "cygwin", not defining "windows".
52-- "windows" should actually guarantee Visual C++ as the compiler.
53--
54-- Q: Does "win32" guarantee we have Visual C++ 2005/2008 command line tools?
55--
56-- Note: Cannot use the simple "module" build type, because we need to precompile
57-- 'src/keeper.lua' -> keeper.lch and bake it into lanes.c.
58--
59build = {
60
61 -- Win32 (Visual C++) uses 'make-vc.cmd' for building
62 --
63 platforms= {
64 windows= {
65 type= "command",
66 build_command= "make-vc.cmd",
67 install= {
68 lua = { "src/lanes.lua" },
69 lib = { "lua51-lanes.dll" }
70 }
71 }
72 },
73
74 -- Other platforms use the Makefile
75 --
76 -- LuaRocks defines CFLAGS, LIBFLAG and LUA_INCDIR for 'make rock',
77 -- defines LIBDIR, LUADIR for 'make install'
78 --
79 -- Ref: <http://www.luarocks.org/en/Paths_and_external_dependencies>
80 --
81 type = "make",
82
83 build_target = "rock",
84 build_variables= {
85 CFLAGS= "$(CFLAGS) -I$(LUA_INCDIR)",
86 LIBFLAG= "$(LIBFLAG)",
87 },
88
89 install_target = "install",
90 install_variables= {
91 LUA_LIBDIR= "$(LIBDIR)",
92 LUA_SHAREDIR= "$(LUADIR)",
93 }
94}
95
diff --git a/lanes-2.0.2.tgz b/lanes-2.0.2.tgz
new file mode 100644
index 0000000..666de3b
--- /dev/null
+++ b/lanes-2.0.2.tgz
Binary files differ
diff --git a/setup-vc.cmd b/setup-vc.cmd
index e93262e..247459c 100644
--- a/setup-vc.cmd
+++ b/setup-vc.cmd
@@ -17,19 +17,19 @@ REM Test for VC++2005 FIRST, because it is the norm with Lua 5.1.4
17REM LuaBinaries and LfW. All prebuilt modules and lua.exe are built 17REM LuaBinaries and LfW. All prebuilt modules and lua.exe are built
18REM with it. 18REM with it.
19REM 19REM
20set VSINSTALLDIR=C:\Program Files\Microsoft Visual Studio 8 20set VSINSTALLDIR=%ProgramFiles%\Microsoft Visual Studio 8
21if not exist "%VSINSTALLDIR%\VC\vcvarsall.bat" goto TRY_VC9 21if not exist "%VSINSTALLDIR%\VC\vcvarsall.bat" goto TRY_VC9
22 22
23REM Win32 headers must be separately downloaded for VC++2005 23REM Win32 headers must be separately downloaded for VC++2005
24REM (VC++2008 SP1 carries an SDK with it) 24REM (VC++2008 SP1 carries an SDK with it)
25REM 25REM
26set _SDK=C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\SetEnv.cmd 26set _SDK=%ProgramFiles%\Microsoft Platform SDK for Windows Server 2003 R2\SetEnv.cmd
27if not exist "%_SDK%" goto ERR_NOSDK 27if not exist "%_SDK%" goto ERR_NOSDK
28call "%_SDK%" 28call "%_SDK%"
29goto FOUND_VC 29goto FOUND_VC
30 30
31:TRY_VC9 31:TRY_VC9
32set VSINSTALLDIR=C:\Program Files\Microsoft Visual Studio 9.0 32set VSINSTALLDIR=%ProgramFiles%\Microsoft Visual Studio 9.0
33if not exist "%VSINSTALLDIR%\VC\vcvarsall.bat" goto ERR_NOVC 33if not exist "%VSINSTALLDIR%\VC\vcvarsall.bat" goto ERR_NOVC
34 34
35echo. 35echo.
@@ -54,7 +54,7 @@ call "%VSINSTALLDIR%\VC\vcvarsall.bat"
54 54
55REM 'timeit.exe' is part of the MS Server Res Kit Tools (needed for "make perftest") 55REM 'timeit.exe' is part of the MS Server Res Kit Tools (needed for "make perftest")
56REM 56REM
57set _RESKIT=C:\Program Files\Windows Resource Kits\Tools\ 57set _RESKIT=%ProgramFiles%\Windows Resource Kits\Tools\
58if not exist "%_RESKIT%\timeit.exe" goto WARN_NOTIMEIT 58if not exist "%_RESKIT%\timeit.exe" goto WARN_NOTIMEIT
59PATH=%PATH%;%_RESKIT% 59PATH=%PATH%;%_RESKIT%
60goto EXIT 60goto EXIT
diff --git a/src/keeper.lua b/src/keeper.lua
index f76173b..9256a4b 100644
--- a/src/keeper.lua
+++ b/src/keeper.lua
@@ -11,7 +11,7 @@
11--[[ 11--[[
12=============================================================================== 12===============================================================================
13 13
14Copyright (C) 2008 Asko Kauppi <akauppi@gmail.com> 14Copyright (C) 2008-10 Asko Kauppi <akauppi@gmail.com>
15 15
16Permission is hereby granted, free of charge, to any person obtaining a copy 16Permission is hereby granted, free of charge, to any person obtaining a copy
17of this software and associated documentation files (the "Software"), to deal 17of this software and associated documentation files (the "Software"), to deal
@@ -135,7 +135,7 @@ function send( ud, key, ... )
135 local m= limits[key] 135 local m= limits[key]
136 136
137 if m and len+n > m then 137 if m and len+n > m then
138 return false -- would exceed the limit; try again later 138 return false -- would exceed the limit; try again later
139 end 139 end
140 140
141 for i=1,n do 141 for i=1,n do
diff --git a/src/lanes.c b/src/lanes.c
index 9b36e4d..ba9e59a 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -4,6 +4,13 @@
4 * Multithreading in Lua. 4 * Multithreading in Lua.
5 * 5 *
6 * History: 6 * History:
7 * 3-Jan-11 (2.0.10): linda_send bugfix, was waiting on the wrong signal
8 * 3-Dec-10 (2.0.9): Added support to generate a lane from a string
9 * 2-Dec-10 (2.0.8): Fix LuaJIT2 incompatibility (no 'tostring' hijack anymore)
10 * ???????? (2.0.7): Fixed 'memory leak' in some situations where a free running
11 * lane is collected before application shutdown
12 * 24-Aug-10 (2.0.6): Mem fixes, argument checking (lua_toLinda result), thread name
13 * 24-Jun-09 (2.0.4): Made friendly to already multithreaded host apps.
7 * 20-Oct-08 (2.0.2): Added closing of free-running threads, but it does 14 * 20-Oct-08 (2.0.2): Added closing of free-running threads, but it does
8 * not seem to eliminate the occasional segfaults at process 15 * not seem to eliminate the occasional segfaults at process
9 * exit. 16 * exit.
@@ -13,10 +20,9 @@
13 * 18-Sep-06 AKa: Started the module. 20 * 18-Sep-06 AKa: Started the module.
14 * 21 *
15 * Platforms (tested internally): 22 * Platforms (tested internally):
16 * OS X (10.5.4 PowerPC/Intel) 23 * OS X (10.5.7 PowerPC/Intel)
17 * Linux x86 (Ubuntu 8.04) 24 * Linux x86 (Ubuntu 8.04)
18 * Win32 (Windows XP Home SP2, Visual C++ 2005/2008 Express) 25 * Win32 (Windows XP Home SP2, Visual C++ 2005/2008 Express)
19 * PocketPC (TBD)
20 * 26 *
21 * Platforms (tested externally): 27 * Platforms (tested externally):
22 * Win32 (MSYS) by Ross Berteig. 28 * Win32 (MSYS) by Ross Berteig.
@@ -54,15 +60,16 @@
54 * 60 *
55 * To-do: 61 * To-do:
56 * 62 *
63 * Make waiting threads cancelable.
57 * ... 64 * ...
58 */ 65 */
59 66
60const char *VERSION= "2.0.3"; 67const char *VERSION= "2.0.10";
61 68
62/* 69/*
63=============================================================================== 70===============================================================================
64 71
65Copyright (C) 2007-08 Asko Kauppi <akauppi@gmail.com> 72Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
66 73
67Permission is hereby granted, free of charge, to any person obtaining a copy 74Permission is hereby granted, free of charge, to any person obtaining a copy
68of this software and associated documentation files (the "Software"), to deal 75of this software and associated documentation files (the "Software"), to deal
@@ -84,10 +91,11 @@ THE SOFTWARE.
84 91
85=============================================================================== 92===============================================================================
86*/ 93*/
94
87#include <string.h> 95#include <string.h>
88#include <stdio.h> 96#include <stdio.h>
89#include <ctype.h>
90#include <stdlib.h> 97#include <stdlib.h>
98#include <ctype.h>
91 99
92#include "lua.h" 100#include "lua.h"
93#include "lauxlib.h" 101#include "lauxlib.h"
@@ -127,7 +135,59 @@ THE SOFTWARE.
127static char keeper_chunk[]= 135static char keeper_chunk[]=
128#include "keeper.lch" 136#include "keeper.lch"
129 137
130struct s_lane; 138// NOTE: values to be changed by either thread, during execution, without
139// locking, are marked "volatile"
140//
141struct s_lane {
142 THREAD_T thread;
143 //
144 // M: sub-thread OS thread
145 // S: not used
146
147 char threadName[64]; //Optional, for debugging and such. owerflowable by a strcpy.
148
149 lua_State *L;
150 //
151 // M: prepares the state, and reads results
152 // S: while S is running, M must keep out of modifying the state
153
154 volatile enum e_status status;
155 //
156 // M: sets to PENDING (before launching)
157 // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED
158
159 volatile bool_t cancel_request;
160 //
161 // M: sets to FALSE, flags TRUE for cancel request
162 // S: reads to see if cancel is requested
163
164#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) )
165 SIGNAL_T done_signal_;
166 //
167 // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN)
168 // S: sets the signal once cancellation is noticed (avoids a kill)
169
170 MUTEX_T done_lock_;
171 //
172 // Lock required by 'done_signal' condition variable, protecting
173 // lane status changes to DONE/ERROR_ST/CANCELLED.
174#endif
175
176 volatile enum {
177 NORMAL, // normal master side state
178 KILLED // issued an OS kill
179 } mstatus;
180 //
181 // M: sets to NORMAL, if issued a kill changes to KILLED
182 // S: not used
183
184 struct s_lane * volatile selfdestruct_next;
185 //
186 // M: sets to non-NULL if facing lane handle '__gc' cycle but the lane
187 // is still running
188 // S: cleans up after itself if non-NULL at lane exit
189};
190
131static bool_t cancel_test( lua_State *L ); 191static bool_t cancel_test( lua_State *L );
132static void cancel_error( lua_State *L ); 192static void cancel_error( lua_State *L );
133 193
@@ -360,10 +420,11 @@ int keeper_call( lua_State* K, const char *func_name,
360 int Ktos= lua_gettop(K); 420 int Ktos= lua_gettop(K);
361 int retvals; 421 int retvals;
362 422
423 STACK_GROW( K, 2 );
424
363 lua_getglobal( K, func_name ); 425 lua_getglobal( K, func_name );
364 ASSERT_L( lua_isfunction(K,-1) ); 426 ASSERT_L( lua_isfunction(K,-1) );
365 427
366 STACK_GROW( K, 1 );
367 lua_pushlightuserdata( K, linda ); 428 lua_pushlightuserdata( K, linda );
368 429
369 luaG_inter_copy( L,K, args ); // L->K 430 luaG_inter_copy( L,K, args ); // L->K
@@ -408,6 +469,8 @@ LUAG_FUNC( linda_send ) {
408 struct s_Keeper *K; 469 struct s_Keeper *K;
409 time_d timeout= -1.0; 470 time_d timeout= -1.0;
410 uint_t key_i= 2; // index of first key, if timeout not there 471 uint_t key_i= 2; // index of first key, if timeout not there
472
473 luaL_argcheck( L, linda, 1, "expected a linda object!");
411 474
412 if (lua_isnumber(L,2)) { 475 if (lua_isnumber(L,2)) {
413 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) ); 476 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) );
@@ -449,10 +512,36 @@ STACK_MID(KL,0)
449 cancel= cancel_test( L ); // testing here causes no delays 512 cancel= cancel_test( L ); // testing here causes no delays
450 if (cancel) break; 513 if (cancel) break;
451 514
515// Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting"
516//
517#if 1
518{
519 struct s_lane *s;
520 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
521 STACK_GROW(L,1);
522
523 STACK_CHECK(L)
524 lua_pushlightuserdata( L, CANCEL_TEST_KEY );
525 lua_rawget( L, LUA_REGISTRYINDEX );
526 s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil
527 lua_pop(L,1);
528 STACK_END(L,0)
529 if (s) {
530 prev_status = s->status;
531 s->status = WAITING;
532 }
533 if (!SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout )) {
534 if (s) { s->status = prev_status; }
535 break;
536 }
537 if (s) s->status = prev_status;
538}
539#else
452 // K lock will be released for the duration of wait and re-acquired 540 // K lock will be released for the duration of wait and re-acquired
453 // 541 //
454 if (!SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout )) 542 if (!SIGNAL_WAIT( &linda->read_happened, &K->lock_, timeout ))
455 break; // timeout 543 break; // timeout
544#endif
456 } 545 }
457 } 546 }
458STACK_END(KL,0) 547STACK_END(KL,0)
@@ -483,6 +572,8 @@ LUAG_FUNC( linda_receive ) {
483 time_d timeout= -1.0; 572 time_d timeout= -1.0;
484 uint_t key_i= 2; 573 uint_t key_i= 2;
485 574
575 luaL_argcheck( L, linda, 1, "expected a linda object!");
576
486 if (lua_isnumber(L,2)) { 577 if (lua_isnumber(L,2)) {
487 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) ); 578 timeout= SIGNAL_TIMEOUT_PREPARE( lua_tonumber(L,2) );
488 key_i++; 579 key_i++;
@@ -509,10 +600,36 @@ LUAG_FUNC( linda_receive ) {
509 cancel= cancel_test( L ); // testing here causes no delays 600 cancel= cancel_test( L ); // testing here causes no delays
510 if (cancel) break; 601 if (cancel) break;
511 602
603// Bugfix by Benoit Germain Dec-2009: change status of lane to "waiting"
604//
605#if 1
606{
607 struct s_lane *s;
608 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings
609 STACK_GROW(L,1);
610
611 STACK_CHECK(L)
612 lua_pushlightuserdata( L, CANCEL_TEST_KEY );
613 lua_rawget( L, LUA_REGISTRYINDEX );
614 s= lua_touserdata( L, -1 ); // lightuserdata (true 's_lane' pointer) / nil
615 lua_pop(L,1);
616 STACK_END(L,0)
617 if (s) {
618 prev_status = s->status;
619 s->status = WAITING;
620 }
621 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout )) {
622 if (s) { s->status = prev_status; }
623 break;
624 }
625 if (s) s->status = prev_status;
626}
627#else
512 // Release the K lock for the duration of wait, and re-acquire 628 // Release the K lock for the duration of wait, and re-acquire
513 // 629 //
514 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout )) 630 if (!SIGNAL_WAIT( &linda->write_happened, &K->lock_, timeout ))
515 break; 631 break;
632#endif
516 } 633 }
517 } 634 }
518 } 635 }
@@ -535,8 +652,11 @@ LUAG_FUNC( linda_receive ) {
535LUAG_FUNC( linda_set ) { 652LUAG_FUNC( linda_set ) {
536 struct s_Linda *linda= lua_toLinda( L, 1 ); 653 struct s_Linda *linda= lua_toLinda( L, 1 );
537 bool_t has_value= !lua_isnil(L,3); 654 bool_t has_value= !lua_isnil(L,3);
655 struct s_Keeper *K;
538 656
539 struct s_Keeper *K= keeper_acquire( linda ); 657 luaL_argcheck( L, linda, 1, "expected a linda object!");
658
659 K= keeper_acquire( linda );
540 { 660 {
541 int pushed= keeper_call( K->L, "set", L, linda, 2 ); 661 int pushed= keeper_call( K->L, "set", L, linda, 2 );
542 ASSERT_L( pushed==0 ); 662 ASSERT_L( pushed==0 );
@@ -561,8 +681,11 @@ LUAG_FUNC( linda_set ) {
561LUAG_FUNC( linda_get ) { 681LUAG_FUNC( linda_get ) {
562 struct s_Linda *linda= lua_toLinda( L, 1 ); 682 struct s_Linda *linda= lua_toLinda( L, 1 );
563 int pushed; 683 int pushed;
684 struct s_Keeper *K;
564 685
565 struct s_Keeper *K= keeper_acquire( linda ); 686 luaL_argcheck( L, linda, 1, "expected a linda object!");
687
688 K= keeper_acquire( linda );
566 { 689 {
567 pushed= keeper_call( K->L, "get", L, linda, 2 ); 690 pushed= keeper_call( K->L, "get", L, linda, 2 );
568 ASSERT_L( pushed==0 || pushed==1 ); 691 ASSERT_L( pushed==0 || pushed==1 );
@@ -580,8 +703,11 @@ LUAG_FUNC( linda_get ) {
580*/ 703*/
581LUAG_FUNC( linda_limit ) { 704LUAG_FUNC( linda_limit ) {
582 struct s_Linda *linda= lua_toLinda( L, 1 ); 705 struct s_Linda *linda= lua_toLinda( L, 1 );
706 struct s_Keeper *K;
707
708 luaL_argcheck( L, linda, 1, "expected a linda object!");
583 709
584 struct s_Keeper *K= keeper_acquire( linda ); 710 K= keeper_acquire( linda );
585 { 711 {
586 int pushed= keeper_call( K->L, "limit", L, linda, 2 ); 712 int pushed= keeper_call( K->L, "limit", L, linda, 2 );
587 ASSERT_L( pushed==0 ); 713 ASSERT_L( pushed==0 );
@@ -604,6 +730,7 @@ LUAG_FUNC( linda_limit ) {
604*/ 730*/
605LUAG_FUNC( linda_deep ) { 731LUAG_FUNC( linda_deep ) {
606 struct s_Linda *linda= lua_toLinda( L, 1 ); 732 struct s_Linda *linda= lua_toLinda( L, 1 );
733 luaL_argcheck( L, linda, 1, "expected a linda object!");
607 lua_pushlightuserdata( L, linda ); // just the address 734 lua_pushlightuserdata( L, linda ); // just the address
608 return 1; 735 return 1;
609} 736}
@@ -761,13 +888,13 @@ static int run_finalizers( lua_State *L, int lua_rc )
761 return 0; // no finalizers 888 return 0; // no finalizers
762 889
763 tbl_index= lua_gettop(L); 890 tbl_index= lua_gettop(L);
764 error_index= (lua_rc!=0) ? tbl_index-1 : 0; // absolute indices 891 error_index= (lua_rc!=0) ? tbl_index-2 : 0; // absolute indices
765 892
766 STACK_GROW(L,4); 893 STACK_GROW(L,4);
767 894
768 // [-1]: { func [, ...] } 895 // [-1]: { func [, ...] }
769 // 896 //
770 for( n= lua_objlen(L,-1); n>0; n-- ) { 897 for( n= (unsigned int)lua_objlen(L,-1); n>0; n-- ) {
771 unsigned args= 0; 898 unsigned args= 0;
772 lua_pushinteger( L,n ); 899 lua_pushinteger( L,n );
773 lua_gettable( L, -2 ); 900 lua_gettable( L, -2 );
@@ -805,57 +932,6 @@ static int run_finalizers( lua_State *L, int lua_rc )
805/*---=== Threads ===--- 932/*---=== Threads ===---
806*/ 933*/
807 934
808// NOTE: values to be changed by either thread, during execution, without
809// locking, are marked "volatile"
810//
811struct s_lane {
812 THREAD_T thread;
813 //
814 // M: sub-thread OS thread
815 // S: not used
816
817 lua_State *L;
818 //
819 // M: prepares the state, and reads results
820 // S: while S is running, M must keep out of modifying the state
821
822 volatile enum e_status status;
823 //
824 // M: sets to PENDING (before launching)
825 // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED
826
827 volatile bool_t cancel_request;
828 //
829 // M: sets to FALSE, flags TRUE for cancel request
830 // S: reads to see if cancel is requested
831
832#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) )
833 SIGNAL_T done_signal_;
834 //
835 // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN)
836 // S: sets the signal once cancellation is noticed (avoids a kill)
837
838 MUTEX_T done_lock_;
839 //
840 // Lock required by 'done_signal' condition variable, protecting
841 // lane status changes to DONE/ERROR_ST/CANCELLED.
842#endif
843
844 volatile enum {
845 NORMAL, // normal master side state
846 KILLED // issued an OS kill
847 } mstatus;
848 //
849 // M: sets to NORMAL, if issued a kill changes to KILLED
850 // S: not used
851
852 struct s_lane * volatile selfdestruct_next;
853 //
854 // M: sets to non-NULL if facing lane handle '__gc' cycle but the lane
855 // is still running
856 // S: cleans up after itself if non-NULL at lane exit
857};
858
859static MUTEX_T selfdestruct_cs; 935static MUTEX_T selfdestruct_cs;
860 // 936 //
861 // Protects modifying the selfdestruct chain 937 // Protects modifying the selfdestruct chain
@@ -985,11 +1061,13 @@ static void selfdestruct_atexit( void ) {
985 // Linux (at least 64-bit): CAUSES A SEGFAULT IF THIS BLOCK IS ENABLED 1061 // Linux (at least 64-bit): CAUSES A SEGFAULT IF THIS BLOCK IS ENABLED
986 // and works without the block (so let's leave those lanes running) 1062 // and works without the block (so let's leave those lanes running)
987 // 1063 //
988#if 1 1064//we want to free memory and such when we exit.
1065#if 0
989 // 2.0.2: at least timer lane is still here 1066 // 2.0.2: at least timer lane is still here
990 // 1067 //
991 //fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n ); 1068 DEBUGEXEC(fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n ));
992#else 1069#else
1070 n=0;
993 MUTEX_LOCK( &selfdestruct_cs ); 1071 MUTEX_LOCK( &selfdestruct_cs );
994 { 1072 {
995 struct s_lane *s= selfdestruct_first; 1073 struct s_lane *s= selfdestruct_first;
@@ -998,6 +1076,8 @@ static void selfdestruct_atexit( void ) {
998 s->selfdestruct_next= NULL; // detach from selfdestruct chain 1076 s->selfdestruct_next= NULL; // detach from selfdestruct chain
999 1077
1000 THREAD_KILL( &s->thread ); 1078 THREAD_KILL( &s->thread );
1079 lua_close(s->L);
1080 free(s);
1001 s= next_s; 1081 s= next_s;
1002 n++; 1082 n++;
1003 } 1083 }
@@ -1005,9 +1085,16 @@ static void selfdestruct_atexit( void ) {
1005 } 1085 }
1006 MUTEX_UNLOCK( &selfdestruct_cs ); 1086 MUTEX_UNLOCK( &selfdestruct_cs );
1007 1087
1008 fprintf( stderr, "Killed %d lane(s) at process end.\n", n ); 1088 DEBUGEXEC(fprintf( stderr, "Killed %d lane(s) at process end.\n", n ));
1009#endif 1089#endif
1010 } 1090 }
1091 {
1092 int i;
1093 for(i=0;i<KEEPER_STATES_N;i++){
1094 lua_close(keeper[i].L);
1095 keeper[i].L = 0;
1096 }
1097 }
1011} 1098}
1012 1099
1013 1100
@@ -1153,6 +1240,38 @@ static int lane_error( lua_State *L ) {
1153} 1240}
1154#endif 1241#endif
1155 1242
1243#if defined PLATFORM_WIN32 && !defined __GNUC__
1244//see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
1245#define MS_VC_EXCEPTION 0x406D1388
1246#pragma pack(push,8)
1247typedef struct tagTHREADNAME_INFO
1248{
1249 DWORD dwType; // Must be 0x1000.
1250 LPCSTR szName; // Pointer to name (in user addr space).
1251 DWORD dwThreadID; // Thread ID (-1=caller thread).
1252 DWORD dwFlags; // Reserved for future use, must be zero.
1253} THREADNAME_INFO;
1254#pragma pack(pop)
1255
1256void SetThreadName( DWORD dwThreadID, char* threadName)
1257{
1258 THREADNAME_INFO info;
1259 Sleep(10);
1260 info.dwType = 0x1000;
1261 info.szName = threadName;
1262 info.dwThreadID = dwThreadID;
1263 info.dwFlags = 0;
1264
1265 __try
1266 {
1267 RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
1268 }
1269 __except(EXCEPTION_EXECUTE_HANDLER)
1270 {
1271 }
1272}
1273#endif
1274
1156 1275
1157//--- 1276//---
1158#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1277#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
@@ -1165,7 +1284,12 @@ static int lane_error( lua_State *L ) {
1165 int rc, rc2; 1284 int rc, rc2;
1166 lua_State *L= s->L; 1285 lua_State *L= s->L;
1167 1286
1168 s->status= RUNNING; // PENDING -> RUNNING 1287
1288#if defined PLATFORM_WIN32 && !defined __GNUC__
1289 SetThreadName(-1, s->threadName);
1290#endif
1291
1292 s->status= RUNNING; // PENDING -> RUNNING
1169 1293
1170 // Tie "set_finalizer()" to the state 1294 // Tie "set_finalizer()" to the state
1171 // 1295 //
@@ -1243,7 +1367,7 @@ static int lane_error( lua_State *L ) {
1243 // We're a free-running thread and no-one's there to clean us up. 1367 // We're a free-running thread and no-one's there to clean us up.
1244 // 1368 //
1245 lua_close( s->L ); 1369 lua_close( s->L );
1246 L= 0; 1370 s->L = L = 0;
1247 1371
1248 #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) 1372 #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) )
1249 SIGNAL_FREE( &s->done_signal_ ); 1373 SIGNAL_FREE( &s->done_signal_ );
@@ -1290,121 +1414,144 @@ static int lane_error( lua_State *L ) {
1290// 1414//
1291LUAG_FUNC( thread_new ) 1415LUAG_FUNC( thread_new )
1292{ 1416{
1293 lua_State *L2; 1417 lua_State *L2;
1294 struct s_lane *s; 1418 struct s_lane *s;
1295 struct s_lane **ud; 1419 struct s_lane **ud;
1296 1420 const char *threadName = 0;
1297 const char *libs= lua_tostring( L, 2 ); 1421
1298 uint_t cs= luaG_optunsigned( L, 3,0); 1422 const char *libs= lua_tostring( L, 2 );
1299 int prio= luaL_optinteger( L, 4,0); 1423 uint_t cs= luaG_optunsigned( L, 3,0);
1300 uint_t glob= luaG_isany(L,5) ? 5:0; 1424 int prio= (int)luaL_optinteger( L, 4,0);
1301 1425 uint_t glob= luaG_isany(L,5) ? 5:0;
1302 #define FIXED_ARGS (5) 1426
1303 uint_t args= lua_gettop(L) - FIXED_ARGS; 1427#define FIXED_ARGS (5)
1304 1428 uint_t args= lua_gettop(L) - FIXED_ARGS;
1305 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) { 1429
1306 luaL_error( L, "Priority out of range: %d..+%d (%d)", 1430 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
1307 THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio ); 1431 {
1308 } 1432 luaL_error( L, "Priority out of range: %d..+%d (%d)",
1309 1433 THREAD_PRIO_MIN, THREAD_PRIO_MAX, prio );
1310 /* --- Create and prepare the sub state --- */ 1434 }
1311 1435
1312 L2 = luaL_newstate(); // uses standard 'realloc()'-based allocator, 1436 /* --- Create and prepare the sub state --- */
1313 // sets the panic callback 1437
1314 1438 L2 = luaL_newstate(); // uses standard 'realloc()'-based allocator,
1315 if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" ); 1439 // sets the panic callback
1316 1440
1317 STACK_GROW( L,2 ); 1441 if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" );
1318 1442
1319 // Setting the globals table (needs to be done before loading stdlibs, 1443 STACK_GROW( L,2 );
1320 // and the lane function) 1444
1321 // 1445 // Setting the globals table (needs to be done before loading stdlibs,
1322 if (glob!=0) { 1446 // and the lane function)
1323STACK_CHECK(L) 1447 //
1324 if (!lua_istable(L,glob)) 1448 if (glob!=0)
1325 luaL_error( L, "Expected table, got %s", luaG_typename(L,glob) ); 1449 {
1326 1450 STACK_CHECK(L)
1327 lua_pushvalue( L, glob ); 1451 if (!lua_istable(L,glob))
1328 luaG_inter_move( L,L2, 1 ); // moves the table to L2 1452 luaL_error( L, "Expected table, got %s", luaG_typename(L,glob) );
1329 1453
1330 // L2 [-1]: table of globals 1454 lua_pushvalue( L, glob );
1331 1455 lua_pushstring( L, "threadName");
1332 // "You can change the global environment of a Lua thread using lua_replace" 1456 lua_gettable( L, -2);
1333 // (refman-5.0.pdf p. 30) 1457 threadName = lua_tostring( L, -1);
1334 // 1458 lua_pop( L, 1);
1335 lua_replace( L2, LUA_GLOBALSINDEX ); 1459 luaG_inter_move( L,L2, 1 ); // moves the table to L2
1336STACK_END(L,0) 1460
1337 } 1461 // L2 [-1]: table of globals
1338 1462
1339 // Selected libraries 1463 // "You can change the global environment of a Lua thread using lua_replace"
1340 // 1464 // (refman-5.0.pdf p. 30)
1341 if (libs) { 1465 //
1342 const char *err= luaG_openlibs( L2, libs ); 1466 lua_replace( L2, LUA_GLOBALSINDEX );
1343 ASSERT_L( !err ); // bad libs should have been noticed by 'lanes.lua' 1467 STACK_END(L,0)
1344 1468 }
1345 serialize_require( L2 ); 1469
1346 } 1470 // Selected libraries
1347 1471 //
1348 // Lane main function 1472 if (libs)
1349 // 1473 {
1350STACK_CHECK(L) 1474 const char *err= luaG_openlibs( L2, libs );
1351 lua_pushvalue( L, 1 ); 1475 ASSERT_L( !err ); // bad libs should have been noticed by 'lanes.lua'
1352 luaG_inter_move( L,L2, 1 ); // L->L2 1476
1353STACK_MID(L,0) 1477 serialize_require( L2 );
1354 1478 }
1355 ASSERT_L( lua_gettop(L2) == 1 ); 1479
1356 ASSERT_L( lua_isfunction(L2,1) ); 1480 // Lane main function
1357 1481 //
1358 // revive arguments 1482 STACK_CHECK(L)
1359 // 1483 if( lua_type(L, 1) == LUA_TFUNCTION)
1360 if (args) luaG_inter_copy( L,L2, args ); // L->L2 1484 {
1361STACK_MID(L,0) 1485 lua_pushvalue( L, 1 );
1362 1486 luaG_inter_move( L,L2, 1 ); // L->L2
1363ASSERT_L( (uint_t)lua_gettop(L2) == 1+args ); 1487 STACK_MID(L,0)
1364ASSERT_L( lua_isfunction(L2,1) ); 1488 }
1365 1489 else if( lua_type(L, 1) == LUA_TSTRING)
1366 // 's' is allocated from heap, not Lua, since its life span may surpass 1490 {
1367 // the handle's (if free running thread) 1491 // compile the string
1368 // 1492 if( luaL_loadstring( L2, lua_tostring( L, 1)) != 0)
1369 ud= lua_newuserdata( L, sizeof(struct s_lane*) ); 1493 {
1370 ASSERT_L(ud); 1494 luaL_error( L, "error when parsing lane function code");
1371 1495 }
1372 s= *ud= malloc( sizeof(struct s_lane) ); 1496 }
1373 ASSERT_L(s); 1497
1374 1498 ASSERT_L( lua_gettop(L2) == 1 );
1375 //memset( s, 0, sizeof(struct s_lane) ); 1499 ASSERT_L( lua_isfunction(L2,1) );
1376 s->L= L2; 1500
1377 s->status= PENDING; 1501 // revive arguments
1378 s->cancel_request= FALSE; 1502 //
1503 if (args) luaG_inter_copy( L,L2, args ); // L->L2
1504 STACK_MID(L,0)
1505
1506 ASSERT_L( (uint_t)lua_gettop(L2) == 1+args );
1507 ASSERT_L( lua_isfunction(L2,1) );
1508
1509 // 's' is allocated from heap, not Lua, since its life span may surpass
1510 // the handle's (if free running thread)
1511 //
1512 ud= lua_newuserdata( L, sizeof(struct s_lane*) );
1513 ASSERT_L(ud);
1514
1515 s= *ud= malloc( sizeof(struct s_lane) );
1516 ASSERT_L(s);
1517
1518 //memset( s, 0, sizeof(struct s_lane) );
1519 s->L= L2;
1520 s->status= PENDING;
1521 s->cancel_request= FALSE;
1522
1523 threadName = threadName ? threadName : "<unnamed thread>";
1524 strcpy(s->threadName, threadName);
1379 1525
1380#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) 1526#if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) )
1381 MUTEX_INIT( &s->done_lock_ ); 1527 MUTEX_INIT( &s->done_lock_ );
1382 SIGNAL_INIT( &s->done_signal_ ); 1528 SIGNAL_INIT( &s->done_signal_ );
1383#endif 1529#endif
1384 s->mstatus= NORMAL; 1530 s->mstatus= NORMAL;
1385 s->selfdestruct_next= NULL; 1531 s->selfdestruct_next= NULL;
1386 1532
1387 // Set metatable for the userdata 1533 // Set metatable for the userdata
1388 // 1534 //
1389 lua_pushvalue( L, lua_upvalueindex(1) ); 1535 lua_pushvalue( L, lua_upvalueindex(1) );
1390 lua_setmetatable( L, -2 ); 1536 lua_setmetatable( L, -2 );
1391STACK_MID(L,1) 1537 STACK_MID(L,1)
1392 1538
1393 // Place 's' to registry, for 'cancel_test()' (even if 'cs'==0 we still 1539 // Place 's' to registry, for 'cancel_test()' (even if 'cs'==0 we still
1394 // do cancel tests at pending send/receive). 1540 // do cancel tests at pending send/receive).
1395 // 1541 //
1396 lua_pushlightuserdata( L2, CANCEL_TEST_KEY ); 1542 lua_pushlightuserdata( L2, CANCEL_TEST_KEY );
1397 lua_pushlightuserdata( L2, s ); 1543 lua_pushlightuserdata( L2, s );
1398 lua_rawset( L2, LUA_REGISTRYINDEX ); 1544 lua_rawset( L2, LUA_REGISTRYINDEX );
1399 1545
1400 if (cs) { 1546 if (cs)
1401 lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs ); 1547 {
1402 } 1548 lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cs );
1403 1549 }
1404 THREAD_CREATE( &s->thread, lane_main, s, prio ); 1550
1405STACK_END(L,1) 1551 THREAD_CREATE( &s->thread, lane_main, s, prio );
1406 1552 STACK_END(L,1)
1407 return 1; 1553
1554 return 1;
1408} 1555}
1409 1556
1410 1557
@@ -1428,45 +1575,56 @@ STACK_END(L,1)
1428// 1575//
1429// Todo: Maybe we should have a clear #define for selecting either behaviour. 1576// Todo: Maybe we should have a clear #define for selecting either behaviour.
1430// 1577//
1431LUAG_FUNC( thread_gc ) { 1578LUAG_FUNC( thread_gc )
1432 struct s_lane *s= lua_toLane(L,1); 1579{
1433 1580 struct s_lane *s= lua_toLane(L,1);
1434 // We can read 's->status' without locks, but not wait for it 1581
1435 // 1582 // We can read 's->status' without locks, but not wait for it
1436 if (s->status < DONE) { 1583 //
1437 // 1584 if (s->status < DONE)
1438 selfdestruct_add(s); 1585 {
1439 assert( s->selfdestruct_next ); 1586 //
1440 return 0; 1587 selfdestruct_add(s);
1441 1588 assert( s->selfdestruct_next );
1442 } else if (s->mstatus==KILLED) { 1589 return 0;
1443 // Make sure a kill has proceeded, before cleaning up the data structure. 1590
1444 // 1591 }
1445 // If not doing 'THREAD_WAIT()' we should close the Lua state here 1592 else if (s->mstatus==KILLED)
1446 // (can it be out of order, since we killed the lane abruptly?) 1593 {
1447 // 1594 // Make sure a kill has proceeded, before cleaning up the data structure.
1595 //
1596 // If not doing 'THREAD_WAIT()' we should close the Lua state here
1597 // (can it be out of order, since we killed the lane abruptly?)
1598 //
1448#if 0 1599#if 0
1449 lua_close( s->L ); 1600 lua_close( s->L );
1601 s->L = 0;
1450#else 1602#else
1451fprintf( stderr, "** Joining with a killed thread (needs testing) **" ); 1603 DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" ));
1452#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) 1604#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)
1453 THREAD_WAIT( &s->thread, -1 ); 1605 THREAD_WAIT( &s->thread, -1 );
1454#else 1606#else
1455 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, -1 ); 1607 THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, -1 );
1456#endif 1608#endif
1457fprintf( stderr, "** Joined ok **" ); 1609 DEBUGEXEC(fprintf( stderr, "** Joined ok **" ));
1458#endif 1610#endif
1459 } 1611 }
1460 1612 else if( s->L)
1461 // Clean up after a (finished) thread 1613 {
1462 // 1614 lua_close( s->L);
1615 s->L = 0;
1616 }
1617
1618 // Clean up after a (finished) thread
1619 //
1463#if (! ((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN))) 1620#if (! ((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)))
1464 SIGNAL_FREE( &s->done_signal_ ); 1621 SIGNAL_FREE( &s->done_signal_ );
1465 MUTEX_FREE( &s->done_lock_ ); 1622 MUTEX_FREE( &s->done_lock_ );
1466 free(s);
1467#endif 1623#endif
1468 1624
1469 return 0; 1625 free(s);
1626
1627 return 0;
1470} 1628}
1471 1629
1472 1630
@@ -1614,10 +1772,11 @@ LUAG_FUNC( thread_join )
1614 break; 1772 break;
1615 1773
1616 default: 1774 default:
1617 fprintf( stderr, "Status: %d\n", s->status ); 1775 DEBUGEXEC(fprintf( stderr, "Status: %d\n", s->status ));
1618 ASSERT_L( FALSE ); ret= 0; 1776 ASSERT_L( FALSE ); ret= 0;
1619 } 1777 }
1620 lua_close(L2); 1778 lua_close(L2);
1779 s->L = L2 = 0;
1621 1780
1622 return ret; 1781 return ret;
1623} 1782}
@@ -1627,48 +1786,6 @@ LUAG_FUNC( thread_join )
1627*/ 1786*/
1628 1787
1629/* 1788/*
1630* Push a timer gateway Linda object; only one deep userdata is
1631* created for this, each lane will get its own proxy.
1632*
1633* Note: this needs to be done on the C side; Lua wouldn't be able
1634* to even see, when we've been initialized for the very first
1635* time (with us, they will be).
1636*/
1637static
1638void push_timer_gateway( lua_State *L ) {
1639
1640 /* No need to lock; 'static' is just fine
1641 */
1642 static DEEP_PRELUDE *p; // = NULL
1643
1644 STACK_CHECK(L)
1645 if (!p) {
1646 // Create the Linda (only on first time)
1647 //
1648 // proxy_ud= deep_userdata( idfunc )
1649 //
1650 lua_pushcfunction( L, luaG_deep_userdata );
1651 lua_pushcfunction( L, LG_linda_id );
1652 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
1653
1654 ASSERT_L( lua_isuserdata(L,-1) );
1655
1656 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer
1657 //
1658 p= * (DEEP_PRELUDE**) lua_touserdata( L, -1 );
1659 ASSERT_L(p && p->refcount==1 && p->deep);
1660
1661 // [-1]: proxy for accessing the Linda
1662
1663 } else {
1664 /* Push a proxy based on the deep userdata we stored.
1665 */
1666 luaG_push_proxy( L, LG_linda_id, p );
1667 }
1668 STACK_END(L,1)
1669}
1670
1671/*
1672* secs= now_secs() 1789* secs= now_secs()
1673* 1790*
1674* Returns the current time, as seconds (millisecond resolution). 1791* Returns the current time, as seconds (millisecond resolution).
@@ -1697,12 +1814,12 @@ LUAG_FUNC( wakeup_conv )
1697 // .isdst (daylight saving on/off) 1814 // .isdst (daylight saving on/off)
1698 1815
1699 STACK_CHECK(L) 1816 STACK_CHECK(L)
1700 lua_getfield( L, 1, "year" ); year= lua_tointeger(L,-1); lua_pop(L,1); 1817 lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1);
1701 lua_getfield( L, 1, "month" ); month= lua_tointeger(L,-1); lua_pop(L,1); 1818 lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1);
1702 lua_getfield( L, 1, "day" ); day= lua_tointeger(L,-1); lua_pop(L,1); 1819 lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1);
1703 lua_getfield( L, 1, "hour" ); hour= lua_tointeger(L,-1); lua_pop(L,1); 1820 lua_getfield( L, 1, "hour" ); hour= (int)lua_tointeger(L,-1); lua_pop(L,1);
1704 lua_getfield( L, 1, "min" ); min= lua_tointeger(L,-1); lua_pop(L,1); 1821 lua_getfield( L, 1, "min" ); min= (int)lua_tointeger(L,-1); lua_pop(L,1);
1705 lua_getfield( L, 1, "sec" ); sec= lua_tointeger(L,-1); lua_pop(L,1); 1822 lua_getfield( L, 1, "sec" ); sec= (int)lua_tointeger(L,-1); lua_pop(L,1);
1706 1823
1707 // If Lua table has '.isdst' we trust that. If it does not, we'll let 1824 // If Lua table has '.isdst' we trust that. If it does not, we'll let
1708 // 'mktime' decide on whether the time is within DST or not (value -1). 1825 // 'mktime' decide on whether the time is within DST or not (value -1).
@@ -1744,19 +1861,11 @@ LUAG_FUNC( wakeup_conv )
1744 lua_pushinteger( L, val ); \ 1861 lua_pushinteger( L, val ); \
1745 lua_setglobal( L, #name ) 1862 lua_setglobal( L, #name )
1746 1863
1747 1864/*
1748int 1865* One-time initializations
1749#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1866*/
1750__declspec(dllexport) 1867static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref ) {
1751#endif
1752 luaopen_lanes( lua_State *L ) {
1753 const char *err; 1868 const char *err;
1754 static volatile char been_here; // =0
1755
1756 // One time initializations:
1757 //
1758 if (!been_here) {
1759 been_here= TRUE;
1760 1869
1761#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1870#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
1762 now_secs(); // initialize 'now_secs()' internal offset 1871 now_secs(); // initialize 'now_secs()' internal offset
@@ -1806,10 +1915,87 @@ __declspec(dllexport)
1806 #endif 1915 #endif
1807#endif 1916#endif
1808 err= init_keepers(); 1917 err= init_keepers();
1809 if (err) 1918 if (err) {
1810 luaL_error( L, "Unable to initialize: %s", err ); 1919 luaL_error( L, "Unable to initialize: %s", err );
1811 } 1920 }
1812 1921
1922 // Initialize 'timer_deep'; a common Linda object shared by all states
1923 //
1924 ASSERT_L( timer_deep_ref && (!(*timer_deep_ref)) );
1925
1926 STACK_CHECK(L)
1927 {
1928 // proxy_ud= deep_userdata( idfunc )
1929 //
1930 lua_pushcfunction( L, luaG_deep_userdata );
1931 lua_pushcfunction( L, LG_linda_id );
1932 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
1933
1934 ASSERT_L( lua_isuserdata(L,-1) );
1935
1936 // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer
1937 //
1938 *timer_deep_ref= * (DEEP_PRELUDE**) lua_touserdata( L, -1 );
1939 ASSERT_L( (*timer_deep_ref) && (*timer_deep_ref)->refcount==1 && (*timer_deep_ref)->deep );
1940
1941 lua_pop(L,1); // we don't need the proxy
1942 }
1943 STACK_END(L,0)
1944}
1945
1946int
1947#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
1948__declspec(dllexport)
1949#endif
1950 luaopen_lanes( lua_State *L ) {
1951
1952 // Initialized by 'init_once_LOCKED()': the deep userdata Linda object
1953 // used for timers (each lane will get a proxy to this)
1954 //
1955 static volatile DEEP_PRELUDE *timer_deep; // = NULL
1956
1957 /*
1958 * Making one-time initializations.
1959 *
1960 * When the host application is single-threaded (and all threading happens via Lanes)
1961 * there is no problem. But if the host is multithreaded, we need to lock around the
1962 * initializations.
1963 */
1964 static volatile int /*bool*/ go_ahead; // = 0
1965#ifdef PLATFORM_WIN32
1966 {
1967 // TBD: Someone please replace this with reliable Win32 API code. Problem is,
1968 // there's no autoinitializing locks (s.a. PTHREAD_MUTEX_INITIALIZER) in
1969 // Windows so 'InterlockedIncrement' or something needs to be used.
1970 // This is 99.9999% safe, though (and always safe if host is single-threaded)
1971 // -- AKa 24-Jun-2009
1972 //
1973 static volatile unsigned my_number; // = 0
1974
1975 if (my_number++ == 0) { // almost atomic
1976 init_once_LOCKED(L, &timer_deep);
1977 go_ahead= 1; // let others pass
1978 } else {
1979 while( !go_ahead ) { Sleep(1); } // changes threads
1980 }
1981 }
1982#else
1983 if (!go_ahead) {
1984 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER;
1985 pthread_mutex_lock(&my_lock);
1986 {
1987 // Recheck now that we're within the lock
1988 //
1989 if (!go_ahead) {
1990 init_once_LOCKED(L, &timer_deep);
1991 go_ahead= 1;
1992 }
1993 }
1994 pthread_mutex_unlock(&my_lock);
1995 }
1996#endif
1997 assert( timer_deep != 0 );
1998
1813 // Linda identity function 1999 // Linda identity function
1814 // 2000 //
1815 REG_FUNC( linda_id ); 2001 REG_FUNC( linda_id );
@@ -1835,7 +2021,7 @@ __declspec(dllexport)
1835 REG_FUNC( now_secs ); 2021 REG_FUNC( now_secs );
1836 REG_FUNC( wakeup_conv ); 2022 REG_FUNC( wakeup_conv );
1837 2023
1838 push_timer_gateway(L); 2024 luaG_push_proxy( L, LG_linda_id, (DEEP_PRELUDE *) timer_deep );
1839 lua_setglobal( L, "timer_gateway" ); 2025 lua_setglobal( L, "timer_gateway" );
1840 2026
1841 REG_INT2( max_prio, THREAD_PRIO_MAX ); 2027 REG_INT2( max_prio, THREAD_PRIO_MAX );
diff --git a/src/lanes.lua b/src/lanes.lua
index c68506d..7ec8c76 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -6,7 +6,8 @@
6-- Author: Asko Kauppi <akauppi@gmail.com> 6-- Author: Asko Kauppi <akauppi@gmail.com>
7-- 7--
8-- History: 8-- History:
9-- Jun-08 AKa: major revise 9-- 3-Dec-10 BGe: Added support to generate a lane from a string
10-- Jun-08 AKa: major revise
10-- 15-May-07 AKa: pthread_join():less version, some speedup & ability to 11-- 15-May-07 AKa: pthread_join():less version, some speedup & ability to
11-- handle more threads (~ 8000-9000, up from ~ 5000) 12-- handle more threads (~ 8000-9000, up from ~ 5000)
12-- 26-Feb-07 AKa: serialization working (C side) 13-- 26-Feb-07 AKa: serialization working (C side)
@@ -15,7 +16,7 @@
15--[[ 16--[[
16=============================================================================== 17===============================================================================
17 18
18Copyright (C) 2007-08 Asko Kauppi <akauppi@gmail.com> 19Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
19 20
20Permission is hereby granted, free of charge, to any person obtaining a copy 21Permission is hereby granted, free of charge, to any person obtaining a copy
21of this software and associated documentation files (the "Software"), to deal 22of this software and associated documentation files (the "Software"), to deal
@@ -89,7 +90,7 @@ ABOUT=
89 author= "Asko Kauppi <akauppi@gmail.com>", 90 author= "Asko Kauppi <akauppi@gmail.com>",
90 description= "Running multiple Lua states in parallel", 91 description= "Running multiple Lua states in parallel",
91 license= "MIT/X11", 92 license= "MIT/X11",
92 copyright= "Copyright (c) 2007-08, Asko Kauppi", 93 copyright= "Copyright (c) 2007-10, Asko Kauppi",
93 version= _version, 94 version= _version,
94} 95}
95 96
@@ -123,6 +124,14 @@ end
123-- 124--
124-- lane_h.state: "pending"/"running"/"waiting"/"done"/"error"/"cancelled" 125-- lane_h.state: "pending"/"running"/"waiting"/"done"/"error"/"cancelled"
125-- 126--
127-- Note: Would be great to be able to have '__ipairs' metamethod, that gets
128-- called by 'ipairs()' function to custom iterate objects. We'd use it
129-- for making sure a lane has ended (results are available); not requiring
130-- the user to precede a loop by explicit 'h[0]' or 'h:join()'.
131--
132-- Or, even better, 'ipairs()' should start valuing '__index' instead
133-- of using raw reads that bypass it.
134--
126local lane_mt= { 135local lane_mt= {
127 __index= function( me, k ) 136 __index= function( me, k )
128 if type(k) == "number" then 137 if type(k) == "number" then
@@ -260,8 +269,9 @@ function gen( ... )
260 end 269 end
261 270
262 local func= select(n,...) 271 local func= select(n,...)
263 if type(func)~="function" then 272 local functype = type(func)
264 error( "Last parameter not function: "..tostring(func) ) 273 if functype ~= "function" and functype ~= "string" then
274 error( "Last parameter not function or string: "..tostring(func))
265 end 275 end
266 276
267 -- Check 'libs' already here, so the error goes in the right place 277 -- Check 'libs' already here, so the error goes in the right place
@@ -302,9 +312,10 @@ lane_proxy= function( ud )
302 local proxy= { 312 local proxy= {
303 _ud= ud, 313 _ud= ud,
304 314
305 -- void= me:cancel() 315 -- true|false= me:cancel()
306 -- 316 --
307 cancel= function(me) thread_cancel(me._ud) end, 317 cancel= function(me, time, force) return thread_cancel(me._ud, time, force) end,
318
308 319
309 -- [...] | [nil,err,stack_tbl]= me:join( [wait_secs=-1] ) 320 -- [...] | [nil,err,stack_tbl]= me:join( [wait_secs=-1] )
310 -- 321 --
@@ -495,14 +506,18 @@ if first_time then
495 -- We let the timer lane be a "free running" thread; no handle to it 506 -- We let the timer lane be a "free running" thread; no handle to it
496 -- remains. 507 -- remains.
497 -- 508 --
498 gen( "io", { priority=max_prio }, function() 509 gen( "io", { priority=max_prio, globals={threadName="LanesTimer"} }, function()
499 510
500 while true do 511 while true do
501 local next_wakeup= check_timers() 512 local next_wakeup= check_timers()
502 513
503 -- Sleep until next timer to wake up, or a set/clear command 514 -- Sleep until next timer to wake up, or a set/clear command
504 -- 515 --
505 local secs= next_wakeup and (next_wakeup - now_secs()) or nil 516 local secs
517 if next_wakeup then
518 secs = next_wakeup - now_secs()
519 if secs < 0 then secs = 0 end
520 end
506 local linda= timer_gateway:receive( secs, TGW_KEY ) 521 local linda= timer_gateway:receive( secs, TGW_KEY )
507 522
508 if linda then 523 if linda then
diff --git a/src/threading.c b/src/threading.c
index 68d1e41..00be243 100644
--- a/src/threading.c
+++ b/src/threading.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * THREADING.C Copyright (c) 2007-08, Asko Kauppi 2 * THREADING.C Copyright (c) 2007-10, Asko Kauppi
3 * 3 *
4 * Lua Lanes OS threading specific code. 4 * Lua Lanes OS threading specific code.
5 * 5 *
@@ -10,7 +10,7 @@
10/* 10/*
11=============================================================================== 11===============================================================================
12 12
13Copyright (C) 2007-08 Asko Kauppi <akauppi@gmail.com> 13Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
14 14
15Permission is hereby granted, free of charge, to any person obtaining a copy 15Permission is hereby granted, free of charge, to any person obtaining a copy
16of this software and associated documentation files (the "Software"), to deal 16of this software and associated documentation files (the "Software"), to deal
@@ -178,6 +178,11 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
178 178
179 ts->tv_sec= floor( abs_secs ); 179 ts->tv_sec= floor( abs_secs );
180 ts->tv_nsec= ((long)((abs_secs - ts->tv_sec) * 1000.0 +0.5)) * 1000000UL; // 1ms = 1000000ns 180 ts->tv_nsec= ((long)((abs_secs - ts->tv_sec) * 1000.0 +0.5)) * 1000000UL; // 1ms = 1000000ns
181 if (ts->tv_nsec == 1000000000UL)
182 {
183 ts->tv_nsec = 0;
184 ts->tv_sec = ts->tv_sec + 1;
185 }
181} 186}
182#endif 187#endif
183 188
diff --git a/src/tools.c b/src/tools.c
index a2ec517..2f3140d 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * TOOLS.C Copyright (c) 2002-08, Asko Kauppi 2 * TOOLS.C Copyright (c) 2002-10, Asko Kauppi
3 * 3 *
4 * Lua tools to support Lanes. 4 * Lua tools to support Lanes.
5*/ 5*/
@@ -7,7 +7,7 @@
7/* 7/*
8=============================================================================== 8===============================================================================
9 9
10Copyright (C) 2002-08 Asko Kauppi <akauppi@gmail.com> 10Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com>
11 11
12Permission is hereby granted, free of charge, to any person obtaining a copy 12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal 13of this software and associated documentation files (the "Software"), to deal
@@ -40,8 +40,6 @@ THE SOFTWARE.
40#include <ctype.h> 40#include <ctype.h>
41#include <stdlib.h> 41#include <stdlib.h>
42 42
43static volatile lua_CFunction hijacked_tostring; // = NULL
44
45MUTEX_T deep_lock; 43MUTEX_T deep_lock;
46MUTEX_T mtid_lock; 44MUTEX_T mtid_lock;
47 45
@@ -600,7 +598,7 @@ uint_t get_mt_id( lua_State *L, int i ) {
600 // [-2]: reg[REG_MTID] 598 // [-2]: reg[REG_MTID]
601 // [-1]: nil/uint 599 // [-1]: nil/uint
602 600
603 id= lua_tointeger(L,-1); // 0 for nil 601 id= (uint_t)lua_tointeger(L,-1); // 0 for nil
604 lua_pop(L,1); 602 lua_pop(L,1);
605 STACK_MID(L,1) 603 STACK_MID(L,1)
606 604
@@ -644,73 +642,60 @@ static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) {
644 * Returns TRUE if the table was cached (no need to fill it!); FALSE if 642 * Returns TRUE if the table was cached (no need to fill it!); FALSE if
645 * it's a virgin. 643 * it's a virgin.
646 */ 644 */
647static 645static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
648bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { 646{
649 bool_t ret; 647 bool_t ret;
650
651 ASSERT_L( hijacked_tostring );
652 ASSERT_L( L2_cache_i != 0 );
653
654 STACK_GROW(L,2);
655 STACK_GROW(L2,3);
656 648
657 // Create an identity string for table at [i]; it should stay unique at 649 ASSERT_L( L2_cache_i != 0 );
658 // least during copying of the data (then we can clear the caches).
659 //
660 STACK_CHECK(L)
661 lua_pushcfunction( L, hijacked_tostring );
662 lua_pushvalue( L, i );
663 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
664 //
665 // [-1]: "table: 0x...."
666 650
667 STACK_END(L,1) 651 STACK_GROW(L2,3);
668 ASSERT_L( lua_type(L,-1) == LUA_TSTRING );
669 652
670 // L2_cache[id_str]= [{...}] 653 // L2_cache[id_str]= [{...}]
671 // 654 //
672 STACK_CHECK(L2) 655 STACK_CHECK(L2)
673 656
674 // We don't need to use the from state ('L') in ID since the life span 657 // We don't need to use the from state ('L') in ID since the life span
675 // is only for the duration of a copy (both states are locked). 658 // is only for the duration of a copy (both states are locked).
676 // 659 //
677 lua_pushstring( L2, lua_tostring(L,-1) ); 660 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the table
678 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
679 661
680//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 662 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
681 663
682 lua_pushvalue( L2, -1 ); 664 lua_pushvalue( L2, -1 );
683 lua_rawget( L2, L2_cache_i ); 665 lua_rawget( L2, L2_cache_i );
684 // 666 //
685 // [-2]: identity string ("table: 0x...") 667 // [-2]: identity table pointer lightuserdata
686 // [-1]: table|nil 668 // [-1]: table|nil
687
688 if (lua_isnil(L2,-1)) {
689 lua_pop(L2,1);
690 lua_newtable(L2);
691 lua_pushvalue(L2,-1);
692 lua_insert(L2,-3);
693 //
694 // [-3]: new table (2nd ref)
695 // [-2]: identity string
696 // [-1]: new table
697 669
698 lua_rawset(L2, L2_cache_i); 670 if (lua_isnil(L2,-1))
699 // 671 {
700 // [-1]: new table (tied to 'L2_cache' table') 672 lua_pop(L2,1);
701 673 lua_newtable(L2);
702 ret= FALSE; // brand new 674 lua_pushvalue(L2,-1);
703 675 lua_insert(L2,-3);
704 } else { 676 //
705 lua_remove(L2,-2); 677 // [-3]: new table (2nd ref)
706 ret= TRUE; // from cache 678 // [-2]: identity table pointer lightuserdata
707 } 679 // [-1]: new table
708 STACK_END(L2,1)
709 //
710 // L2 [-1]: table to use as destination
711 680
712 ASSERT_L( lua_istable(L2,-1) ); 681 lua_rawset(L2, L2_cache_i);
713 return ret; 682 //
683 // [-1]: new table (tied to 'L2_cache' table')
684
685 ret= FALSE; // brand new
686
687 }
688 else
689 {
690 lua_remove(L2,-2);
691 ret= TRUE; // from cache
692 }
693 STACK_END(L2,1)
694 //
695 // L2 [-1]: table to use as destination
696
697 ASSERT_L( lua_istable(L2,-1) );
698 return ret;
714} 699}
715 700
716 701
@@ -722,82 +707,76 @@ bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t
722 */ 707 */
723static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ); 708static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i );
724 709
725static 710static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
726void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { 711{
727 // TBD: Merge this and same code for tables 712 // TBD: Merge this and same code for tables
728 713
729 ASSERT_L( hijacked_tostring ); 714 ASSERT_L( L2_cache_i != 0 );
730 ASSERT_L( L2_cache_i != 0 );
731 715
732 STACK_GROW(L,2); 716 STACK_GROW(L2,3);
733 STACK_GROW(L2,3);
734 717
735 STACK_CHECK(L) 718 // L2_cache[id_str]= function
736 lua_pushcfunction( L, hijacked_tostring ); 719 //
737 lua_pushvalue( L, i ); 720 STACK_CHECK(L2)
738 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
739 //
740 // [-1]: "function: 0x...."
741 721
742 STACK_END(L,1) 722 // We don't need to use the from state ('L') in ID since the life span
743 ASSERT_L( lua_type(L,-1) == LUA_TSTRING ); 723 // is only for the duration of a copy (both states are locked).
744 724 //
745 // L2_cache[id_str]= function 725 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the function
746 //
747 STACK_CHECK(L2)
748 726
749 // We don't need to use the from state ('L') in ID since the life span 727 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
750 // is only for the duration of a copy (both states are locked).
751 //
752 lua_pushstring( L2, lua_tostring(L,-1) );
753 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
754 728
755//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 729 lua_pushvalue( L2, -1 );
730 lua_rawget( L2, L2_cache_i );
731 //
732 // [-2]: identity lightuserdata function pointer
733 // [-1]: function|nil|true (true means: we're working on it; recursive)
756 734
757 lua_pushvalue( L2, -1 ); 735 if (lua_isnil(L2,-1))
758 lua_rawget( L2, L2_cache_i ); 736 {
759 // 737 lua_pop(L2,1);
760 // [-2]: identity string ("function: 0x...")
761 // [-1]: function|nil|true (true means: we're working on it; recursive)
762 738
763 if (lua_isnil(L2,-1)) { 739 // Set to 'true' for the duration of creation; need to find self-references
764 lua_pop(L2,1); 740 // via upvalues
765 741 //
766 // Set to 'true' for the duration of creation; need to find self-references 742 lua_pushvalue( L2, -1);
767 // via upvalues 743 lua_pushboolean(L2,TRUE);
768 // 744 lua_rawset( L2, L2_cache_i);
769 lua_pushboolean(L2,TRUE);
770 lua_setfield( L2, L2_cache_i, lua_tostring(L2,-2) );
771
772 inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func
773 745
774 lua_pushvalue(L2,-1); 746 inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func
775 lua_insert(L2,-3);
776 //
777 // [-3]: function (2nd ref)
778 // [-2]: identity string
779 // [-1]: function
780 747
781 lua_rawset(L2,L2_cache_i); 748 lua_pushvalue(L2,-1);
782 // 749 lua_insert(L2,-3);
783 // [-1]: function (tied to 'L2_cache' table') 750 //
784 751 // [-3]: function (2nd ref)
785 } else if (lua_isboolean(L2,-1)) { 752 // [-2]: identity lightuserdata function pointer
786 // Loop in preparing upvalues; either direct or via a table 753 // [-1]: function
787 //
788 // Note: This excludes the case where a function directly addresses
789 // itself as an upvalue (recursive lane creation).
790 //
791 luaL_error( L, "Recursive use of upvalues; cannot copy the function" );
792
793 } else {
794 lua_remove(L2,-2);
795 }
796 STACK_END(L2,1)
797 //
798 // L2 [-1]: function
799 754
800 ASSERT_L( lua_isfunction(L2,-1) ); 755 lua_rawset(L2,L2_cache_i);
756 //
757 // [-1]: function (tied to 'L2_cache' table')
758
759 }
760 else if (lua_isboolean(L2,-1))
761 {
762 // Loop in preparing upvalues; either direct or via a table
763 //
764 // Note: This excludes the case where a function directly addresses
765 // itself as an upvalue (recursive lane creation).
766 //
767 STACK_GROW(L,1);
768 luaL_error( L, "Recursive use of upvalues; cannot copy the function" );
769
770 }
771 else
772 {
773 lua_remove(L2,-2);
774 }
775 STACK_END(L2,1)
776 //
777 // L2 [-1]: function
778
779 ASSERT_L( lua_isfunction(L2,-1) );
801} 780}
802 781
803 782
@@ -1137,29 +1116,6 @@ void luaG_inter_copy( lua_State* L, lua_State *L2, uint_t n )
1137 uint_t top_L2= lua_gettop(L2); 1116 uint_t top_L2= lua_gettop(L2);
1138 uint_t i; 1117 uint_t i;
1139 1118
1140 /* steal Lua library's 'luaB_tostring()' from the first call. Other calls
1141 * don't have to have access to it.
1142 *
1143 * Note: multiple threads won't come here at once; this function will
1144 * be called before there can be multiple threads (no locking needed).
1145 */
1146 if (!hijacked_tostring) {
1147 STACK_GROW( L,1 );
1148
1149 STACK_CHECK(L)
1150 lua_getglobal( L, "tostring" );
1151 //
1152 // [-1]: function|nil
1153
1154 hijacked_tostring= lua_tocfunction( L, -1 );
1155 lua_pop(L,1);
1156 STACK_END(L,0)
1157
1158 if (!hijacked_tostring) {
1159 luaL_error( L, "Need to see 'tostring()' once" );
1160 }
1161 }
1162
1163 if (n > top_L) 1119 if (n > top_L)
1164 luaL_error( L, "Not enough values: %d < %d", top_L, n ); 1120 luaL_error( L, "Not enough values: %d < %d", top_L, n );
1165 1121
diff --git a/src/tools.h b/src/tools.h
index d155c65..aad26df 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -22,6 +22,7 @@
22 #define STACK_END(L,c) /*nothing*/ 22 #define STACK_END(L,c) /*nothing*/
23 #define STACK_DUMP(L) /*nothing*/ 23 #define STACK_DUMP(L) /*nothing*/
24 #define DEBUG() /*nothing*/ 24 #define DEBUG() /*nothing*/
25 #define DEBUGEXEC(_code) {} /*nothing*/
25#else 26#else
26 #define _ASSERT_L(lua,c) { if (!(c)) luaL_error( lua, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #c ); } 27 #define _ASSERT_L(lua,c) { if (!(c)) luaL_error( lua, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #c ); }
27 // 28 //
@@ -32,6 +33,7 @@
32 33
33 #define STACK_DUMP(L) luaG_dump(L); 34 #define STACK_DUMP(L) luaG_dump(L);
34 #define DEBUG() fprintf( stderr, "<<%s %d>>\n", __FILE__, __LINE__ ); 35 #define DEBUG() fprintf( stderr, "<<%s %d>>\n", __FILE__, __LINE__ );
36 #define DEBUGEXEC(_code) {_code;} /*nothing*/
35#endif 37#endif
36#define ASSERT_L(c) _ASSERT_L(L,c) 38#define ASSERT_L(c) _ASSERT_L(L,c)
37 39
diff --git a/tests/appendud.lua b/tests/appendud.lua
new file mode 100644
index 0000000..afea0e9
--- /dev/null
+++ b/tests/appendud.lua
@@ -0,0 +1,58 @@
1--
2-- APPENDUD.LUA
3--
4-- Lanes version for John Belmonte's challenge on Lua list (about finalizers):
5-- <http://lua-users.org/lists/lua-l/2008-02/msg00243.html>
6--
7-- Needs Lanes >= 2.0.3
8--
9require "lanes"
10
11local _tab = {
12 beginupdate = function (this) print('tab.beginupdate') end;
13 endupdate = function (this) print('tab.endupdate') end;
14}
15local _ud = {
16 lock = function (this) print('ud.lock') end;
17 unlock = function (this) print('ud.unlock') end;
18 1,2,3,4,5;
19}
20
21--
22-- This sample is with the 'finalize/guard' patch applied (new keywords):
23--
24--function appendud(tab, ud)
25-- tab:beginupdate() finalize tab:endupdate() end
26-- ud:lock() finalize ud:unlock() end
27-- for i = 1,#ud do
28-- tab[#tab+1] = ud[i]
29-- end
30--end
31
32
33function appendud(tab, ud)
34io.stderr:write "Starting"
35 tab:beginupdate() set_finalizer( function() tab:endupdate() end )
36 ud:lock() set_finalizer( function() ud:unlock() end )
37 for i = 1,#ud do
38 tab[#tab+1] = ud[i]
39 end
40io.stderr:write "Ending"
41 return tab -- need to return 'tab' since we're running in a separate thread
42 -- ('tab' is passed over lanes by value, not by reference)
43end
44
45local t,err= lanes.gen( appendud )( _tab, _ud ) -- create & launch a thread
46assert(t)
47assert(not err)
48
49-- test
50
51t:join() -- Need to explicitly wait for the thread, since 'ipairs()' does not
52 -- value the '__index' metamethod (wouldn't it be cool if it did..?)
53
54io.stderr:write(t[1])
55
56for k,v in ipairs(t) do
57 print(k,v)
58end
diff --git a/tests/basic.lua b/tests/basic.lua
index ee31ed1..b1e8fd3 100644
--- a/tests/basic.lua
+++ b/tests/basic.lua
@@ -2,7 +2,7 @@
2-- BASIC.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com> 2-- BASIC.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3-- 3--
4-- Selftests for Lua Lanes 4-- Selftests for Lua Lanes
5-- 5--
6-- To do: 6-- To do:
7-- - ... 7-- - ...
8-- 8--
@@ -20,7 +20,7 @@ local function PRINT(...)
20 for i=1,select('#',...) do 20 for i=1,select('#',...) do
21 str= str..tostring(select(i,...)).."\t" 21 str= str..tostring(select(i,...)).."\t"
22 end 22 end
23 if io then 23 if io then
24 io.stderr:write(str.."\n") 24 io.stderr:write(str.."\n")
25 end 25 end
26end 26end
@@ -55,7 +55,7 @@ tables_match= function( a, b )
55end 55end
56 56
57 57
58---=== Tasking (basic) ===--- 58PRINT( "---=== Tasking (basic) ===---")
59 59
60local function task( a, b, c ) 60local function task( a, b, c )
61 --error "111" -- testing error messages 61 --error "111" -- testing error messages
@@ -98,7 +98,7 @@ assert( lane1.status == "done" )
98assert( lane1.status == "done" ) 98assert( lane1.status == "done" )
99 99
100 100
101---=== Tasking (cancelling) ===--- 101PRINT( "---=== Tasking (cancelling) ===---")
102 102
103local task_launch2= lanes_gen( "", { cancelstep=100, globals={hey=true} }, task ) 103local task_launch2= lanes_gen( "", { cancelstep=100, globals={hey=true} }, task )
104 104
@@ -136,7 +136,7 @@ PRINT(" "..st)
136assert( st == "cancelled" ) 136assert( st == "cancelled" )
137 137
138 138
139---=== Communications ===--- 139PRINT( "---=== Communications ===---")
140 140
141local function WR(...) io.stderr:write(...) end 141local function WR(...) io.stderr:write(...) end
142 142
@@ -157,7 +157,7 @@ local chunk= function( linda )
157 send { 'a', 'b', 'c', d=10 }; WR( "{'a','b','c',d=10} sent\n" ) 157 send { 'a', 'b', 'c', d=10 }; WR( "{'a','b','c',d=10} sent\n" )
158 158
159 v=receive(); WR( v.." received\n" ); assert( v==4 ) 159 v=receive(); WR( v.." received\n" ); assert( v==4 )
160 160
161 WR( "Lane ends!\n" ) 161 WR( "Lane ends!\n" )
162end 162end
163 163
@@ -195,7 +195,7 @@ assert( PEEK() == nil )
195SEND(4) 195SEND(4)
196 196
197 197
198---=== Stdlib naming ===--- 198PRINT( "---=== Stdlib naming ===---")
199 199
200local function io_os_f() 200local function io_os_f()
201 assert(io) 201 assert(io)
@@ -215,7 +215,7 @@ assert( f2()[1] )
215assert( f3()[1] ) 215assert( f3()[1] )
216 216
217 217
218---=== Comms criss cross ===--- 218PRINT( "---=== Comms criss cross ===---")
219 219
220-- We make two identical lanes, which are using the same Linda channel. 220-- We make two identical lanes, which are using the same Linda channel.
221-- 221--
@@ -241,7 +241,7 @@ local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twis
241local _= a[1],b[1] -- waits until they are both ready 241local _= a[1],b[1] -- waits until they are both ready
242 242
243 243
244---=== Receive & send of code ===--- 244PRINT( "---=== Receive & send of code ===---")
245 245
246local upvalue="123" 246local upvalue="123"
247 247
@@ -251,21 +251,21 @@ local function chunk2( linda )
251 -- function name & line number should be there even as separate thread 251 -- function name & line number should be there even as separate thread
252 -- 252 --
253 local info= debug.getinfo(1) -- 1 = us 253 local info= debug.getinfo(1) -- 1 = us
254 -- 254 --
255 for k,v in pairs(info) do PRINT(k,v) end 255 for k,v in pairs(info) do PRINT(k,v) end
256 256
257 assert( info.nups == 2 ) -- one upvalue + PRINT 257 assert( info.nups == 2 ) -- one upvalue + PRINT
258 assert( info.what == "Lua" ) 258 assert( info.what == "Lua" )
259 259
260 --assert( info.name == "chunk2" ) -- name does not seem to come through 260 --assert( info.name == "chunk2" ) -- name does not seem to come through
261 assert( string.match( info.source, "^@tests[/\\]basic.lua$" ) ) 261 assert( string.match( info.source, "^@basic.lua$" ) )
262 assert( string.match( info.short_src, "^tests[/\\]basic.lua$" ) ) 262 assert( string.match( info.short_src, "^basic.lua$" ) )
263 263
264 -- These vary so let's not be picky (they're there..) 264 -- These vary so let's not be picky (they're there..)
265 -- 265 --
266 assert( info.linedefined > 200 ) -- start of 'chunk2' 266 assert( info.linedefined > 200 ) -- start of 'chunk2'
267 assert( info.currentline > info.linedefined ) -- line of 'debug.getinfo' 267 assert( info.currentline > info.linedefined ) -- line of 'debug.getinfo'
268 assert( info.lastlinedefined > info.currentline ) -- end of 'chunk2' 268 assert( info.lastlinedefined > info.currentline ) -- end of 'chunk2'
269 269
270 local func,k= linda:receive( "down" ) 270 local func,k= linda:receive( "down" )
271 assert( type(func)=="function" ) 271 assert( type(func)=="function" )
@@ -275,7 +275,7 @@ local function chunk2( linda )
275 275
276 local str= linda:receive( "down" ) 276 local str= linda:receive( "down" )
277 assert( str=="ok" ) 277 assert( str=="ok" )
278 278
279 linda:send( "up", function() return ":)" end, "ok2" ) 279 linda:send( "up", function() return ":)" end, "ok2" )
280end 280end
281 281
@@ -304,7 +304,7 @@ local ok2= linda:receive( "up" )
304assert( ok2 == "ok2" ) 304assert( ok2 == "ok2" )
305 305
306 306
307---=== :join test ===--- 307PRINT( "---=== :join test ===---")
308 308
309-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil 309-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil
310-- (unless [1..n] has been read earlier, in which case it would seemingly 310-- (unless [1..n] has been read earlier, in which case it would seemingly
diff --git a/tests/func_is_string.lua b/tests/func_is_string.lua
new file mode 100644
index 0000000..98ea62b
--- /dev/null
+++ b/tests/func_is_string.lua
@@ -0,0 +1,12 @@
1require "lanes"
2
3local options = {globals = { b = 666 }}
4
5-- local gen1 = lanes.gen("*", "dofile('fibonacci.lua')")
6local gen2 = lanes.gen(options, "return b")
7
8-- fibLane = gen1()
9retLane1, retLane2 = gen2(), gen2()
10-- fibLane:join()
11
12print( retLane1[1], retLane2[1])
diff --git a/xcode/xcode.xcodeproj/abisoft.mode1 b/xcode/xcode.xcodeproj/abisoft.mode1
new file mode 100644
index 0000000..569158d
--- /dev/null
+++ b/xcode/xcode.xcodeproj/abisoft.mode1
@@ -0,0 +1,1460 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3<plist version="1.0">
4<dict>
5 <key>ActivePerspectiveName</key>
6 <string>Project</string>
7 <key>AllowedModules</key>
8 <array>
9 <dict>
10 <key>BundleLoadPath</key>
11 <string></string>
12 <key>MaxInstances</key>
13 <string>n</string>
14 <key>Module</key>
15 <string>PBXSmartGroupTreeModule</string>
16 <key>Name</key>
17 <string>Groups and Files Outline View</string>
18 </dict>
19 <dict>
20 <key>BundleLoadPath</key>
21 <string></string>
22 <key>MaxInstances</key>
23 <string>n</string>
24 <key>Module</key>
25 <string>PBXNavigatorGroup</string>
26 <key>Name</key>
27 <string>Editor</string>
28 </dict>
29 <dict>
30 <key>BundleLoadPath</key>
31 <string></string>
32 <key>MaxInstances</key>
33 <string>n</string>
34 <key>Module</key>
35 <string>XCTaskListModule</string>
36 <key>Name</key>
37 <string>Task List</string>
38 </dict>
39 <dict>
40 <key>BundleLoadPath</key>
41 <string></string>
42 <key>MaxInstances</key>
43 <string>n</string>
44 <key>Module</key>
45 <string>XCDetailModule</string>
46 <key>Name</key>
47 <string>File and Smart Group Detail Viewer</string>
48 </dict>
49 <dict>
50 <key>BundleLoadPath</key>
51 <string></string>
52 <key>MaxInstances</key>
53 <string>1</string>
54 <key>Module</key>
55 <string>PBXBuildResultsModule</string>
56 <key>Name</key>
57 <string>Detailed Build Results Viewer</string>
58 </dict>
59 <dict>
60 <key>BundleLoadPath</key>
61 <string></string>
62 <key>MaxInstances</key>
63 <string>1</string>
64 <key>Module</key>
65 <string>PBXProjectFindModule</string>
66 <key>Name</key>
67 <string>Project Batch Find Tool</string>
68 </dict>
69 <dict>
70 <key>BundleLoadPath</key>
71 <string></string>
72 <key>MaxInstances</key>
73 <string>n</string>
74 <key>Module</key>
75 <string>PBXRunSessionModule</string>
76 <key>Name</key>
77 <string>Run Log</string>
78 </dict>
79 <dict>
80 <key>BundleLoadPath</key>
81 <string></string>
82 <key>MaxInstances</key>
83 <string>n</string>
84 <key>Module</key>
85 <string>PBXBookmarksModule</string>
86 <key>Name</key>
87 <string>Bookmarks Tool</string>
88 </dict>
89 <dict>
90 <key>BundleLoadPath</key>
91 <string></string>
92 <key>MaxInstances</key>
93 <string>n</string>
94 <key>Module</key>
95 <string>PBXClassBrowserModule</string>
96 <key>Name</key>
97 <string>Class Browser</string>
98 </dict>
99 <dict>
100 <key>BundleLoadPath</key>
101 <string></string>
102 <key>MaxInstances</key>
103 <string>n</string>
104 <key>Module</key>
105 <string>PBXCVSModule</string>
106 <key>Name</key>
107 <string>Source Code Control Tool</string>
108 </dict>
109 <dict>
110 <key>BundleLoadPath</key>
111 <string></string>
112 <key>MaxInstances</key>
113 <string>n</string>
114 <key>Module</key>
115 <string>PBXDebugBreakpointsModule</string>
116 <key>Name</key>
117 <string>Debug Breakpoints Tool</string>
118 </dict>
119 <dict>
120 <key>BundleLoadPath</key>
121 <string></string>
122 <key>MaxInstances</key>
123 <string>n</string>
124 <key>Module</key>
125 <string>XCDockableInspector</string>
126 <key>Name</key>
127 <string>Inspector</string>
128 </dict>
129 <dict>
130 <key>BundleLoadPath</key>
131 <string></string>
132 <key>MaxInstances</key>
133 <string>n</string>
134 <key>Module</key>
135 <string>PBXOpenQuicklyModule</string>
136 <key>Name</key>
137 <string>Open Quickly Tool</string>
138 </dict>
139 <dict>
140 <key>BundleLoadPath</key>
141 <string></string>
142 <key>MaxInstances</key>
143 <string>1</string>
144 <key>Module</key>
145 <string>PBXDebugSessionModule</string>
146 <key>Name</key>
147 <string>Debugger</string>
148 </dict>
149 <dict>
150 <key>BundleLoadPath</key>
151 <string></string>
152 <key>MaxInstances</key>
153 <string>1</string>
154 <key>Module</key>
155 <string>PBXDebugCLIModule</string>
156 <key>Name</key>
157 <string>Debug Console</string>
158 </dict>
159 </array>
160 <key>Description</key>
161 <string>DefaultDescriptionKey</string>
162 <key>DockingSystemVisible</key>
163 <false/>
164 <key>Extension</key>
165 <string>mode1</string>
166 <key>FavBarConfig</key>
167 <dict>
168 <key>PBXProjectModuleGUID</key>
169 <string>27602E5F0C2F36D60086E627</string>
170 <key>XCBarModuleItemNames</key>
171 <dict/>
172 <key>XCBarModuleItems</key>
173 <array/>
174 </dict>
175 <key>FirstTimeWindowDisplayed</key>
176 <false/>
177 <key>Identifier</key>
178 <string>com.apple.perspectives.project.mode1</string>
179 <key>MajorVersion</key>
180 <integer>31</integer>
181 <key>MinorVersion</key>
182 <integer>1</integer>
183 <key>Name</key>
184 <string>Default</string>
185 <key>Notifications</key>
186 <array>
187 <dict>
188 <key>XCObserverAutoDisconnectKey</key>
189 <true/>
190 <key>XCObserverDefintionKey</key>
191 <dict/>
192 <key>XCObserverFactoryKey</key>
193 <string>XCPerspectivesSpecificationIdentifier</string>
194 <key>XCObserverGUIDKey</key>
195 <string>XCObserverProjectIdentifier</string>
196 <key>XCObserverNotificationKey</key>
197 <string>PBXStatusBuildStateMessageNotification</string>
198 <key>XCObserverTargetKey</key>
199 <string>XCMainBuildResultsModuleGUID</string>
200 <key>XCObserverTriggerKey</key>
201 <string>awakenModuleWithObserver:</string>
202 <key>XCObserverValidationKey</key>
203 <dict/>
204 </dict>
205 </array>
206 <key>OpenEditors</key>
207 <array>
208 <dict>
209 <key>Content</key>
210 <dict>
211 <key>PBXProjectModuleGUID</key>
212 <string>2784DBE60CD6544900B13CF3</string>
213 <key>PBXProjectModuleLabel</key>
214 <string>gluax_static.c</string>
215 <key>PBXSplitModuleInNavigatorKey</key>
216 <dict>
217 <key>Split0</key>
218 <dict>
219 <key>PBXProjectModuleGUID</key>
220 <string>2784DBE70CD6544900B13CF3</string>
221 <key>PBXProjectModuleLabel</key>
222 <string>gluax_static.c</string>
223 <key>_historyCapacity</key>
224 <integer>0</integer>
225 <key>bookmark</key>
226 <string>2736316D0CD721CA00A12F3E</string>
227 <key>history</key>
228 <array>
229 <string>27F8E2020CD71E630081A54F</string>
230 </array>
231 </dict>
232 <key>SplitCount</key>
233 <string>1</string>
234 </dict>
235 <key>StatusBarVisibility</key>
236 <true/>
237 </dict>
238 <key>Geometry</key>
239 <dict>
240 <key>Frame</key>
241 <string>{{0, 20}, {1057, 709}}</string>
242 <key>PBXModuleWindowStatusBarHidden2</key>
243 <false/>
244 <key>RubberWindowFrame</key>
245 <string>349 236 1057 750 0 0 1680 1028 </string>
246 </dict>
247 </dict>
248 <dict>
249 <key>Content</key>
250 <dict>
251 <key>PBXProjectModuleGUID</key>
252 <string>27F6DA310C4416540054E42A</string>
253 <key>PBXProjectModuleLabel</key>
254 <string>gluax.c</string>
255 <key>PBXSplitModuleInNavigatorKey</key>
256 <dict>
257 <key>Split0</key>
258 <dict>
259 <key>PBXProjectModuleGUID</key>
260 <string>27F6DA320C4416540054E42A</string>
261 <key>PBXProjectModuleLabel</key>
262 <string>gluax.c</string>
263 <key>_historyCapacity</key>
264 <integer>0</integer>
265 <key>bookmark</key>
266 <string>2736316E0CD721CA00A12F3E</string>
267 <key>history</key>
268 <array>
269 <string>27F8E2030CD71E630081A54F</string>
270 </array>
271 </dict>
272 <key>SplitCount</key>
273 <string>1</string>
274 </dict>
275 <key>StatusBarVisibility</key>
276 <true/>
277 </dict>
278 <key>Geometry</key>
279 <dict>
280 <key>Frame</key>
281 <string>{{0, 20}, {1057, 709}}</string>
282 <key>PBXModuleWindowStatusBarHidden2</key>
283 <false/>
284 <key>RubberWindowFrame</key>
285 <string>540 110 1057 750 0 0 1680 1028 </string>
286 </dict>
287 </dict>
288 </array>
289 <key>PerspectiveWidths</key>
290 <array>
291 <integer>-1</integer>
292 <integer>-1</integer>
293 </array>
294 <key>Perspectives</key>
295 <array>
296 <dict>
297 <key>ChosenToolbarItems</key>
298 <array>
299 <string>active-target-popup</string>
300 <string>active-buildstyle-popup</string>
301 <string>action</string>
302 <string>NSToolbarFlexibleSpaceItem</string>
303 <string>buildOrClean</string>
304 <string>build-and-runOrDebug</string>
305 <string>com.apple.ide.PBXToolbarStopButton</string>
306 <string>get-info</string>
307 <string>toggle-editor</string>
308 <string>NSToolbarFlexibleSpaceItem</string>
309 <string>com.apple.pbx.toolbar.searchfield</string>
310 </array>
311 <key>ControllerClassBaseName</key>
312 <string></string>
313 <key>IconName</key>
314 <string>WindowOfProjectWithEditor</string>
315 <key>Identifier</key>
316 <string>perspective.project</string>
317 <key>IsVertical</key>
318 <false/>
319 <key>Layout</key>
320 <array>
321 <dict>
322 <key>BecomeActive</key>
323 <true/>
324 <key>ContentConfiguration</key>
325 <dict>
326 <key>PBXBottomSmartGroupGIDs</key>
327 <array>
328 <string>1C37FBAC04509CD000000102</string>
329 <string>1C37FAAC04509CD000000102</string>
330 <string>1C08E77C0454961000C914BD</string>
331 <string>1C37FABC05509CD000000102</string>
332 <string>1C37FABC05539CD112110102</string>
333 <string>E2644B35053B69B200211256</string>
334 <string>1C37FABC04509CD000100104</string>
335 <string>1CC0EA4004350EF90044410B</string>
336 <string>1CC0EA4004350EF90041110B</string>
337 </array>
338 <key>PBXProjectModuleGUID</key>
339 <string>1CE0B1FE06471DED0097A5F4</string>
340 <key>PBXProjectModuleLabel</key>
341 <string>Files</string>
342 <key>PBXProjectStructureProvided</key>
343 <string>yes</string>
344 <key>PBXSmartGroupTreeModuleColumnData</key>
345 <dict>
346 <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
347 <array>
348 <real>186</real>
349 </array>
350 <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
351 <array>
352 <string>MainColumn</string>
353 </array>
354 </dict>
355 <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
356 <dict>
357 <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
358 <array>
359 <string>08FB7794FE84155DC02AAC07</string>
360 <string>1AB674ADFE9D54B511CA2CBB</string>
361 <string>1C37FBAC04509CD000000102</string>
362 <string>1C37FAAC04509CD000000102</string>
363 <string>1C37FABC05509CD000000102</string>
364 </array>
365 <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
366 <array>
367 <array>
368 <integer>12</integer>
369 </array>
370 </array>
371 <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
372 <string>{{0, 0}, {186, 503}}</string>
373 </dict>
374 <key>PBXTopSmartGroupGIDs</key>
375 <array/>
376 <key>XCIncludePerspectivesSwitch</key>
377 <true/>
378 <key>XCSharingToken</key>
379 <string>com.apple.Xcode.GFSharingToken</string>
380 </dict>
381 <key>GeometryConfiguration</key>
382 <dict>
383 <key>Frame</key>
384 <string>{{0, 0}, {203, 521}}</string>
385 <key>GroupTreeTableConfiguration</key>
386 <array>
387 <string>MainColumn</string>
388 <real>186</real>
389 </array>
390 <key>RubberWindowFrame</key>
391 <string>243 337 880 562 0 0 1680 1028 </string>
392 </dict>
393 <key>Module</key>
394 <string>PBXSmartGroupTreeModule</string>
395 <key>Proportion</key>
396 <string>203pt</string>
397 </dict>
398 <dict>
399 <key>Dock</key>
400 <array>
401 <dict>
402 <key>ContentConfiguration</key>
403 <dict>
404 <key>PBXProjectModuleGUID</key>
405 <string>1CE0B20306471E060097A5F4</string>
406 <key>PBXProjectModuleLabel</key>
407 <string>MyNewFile14.java</string>
408 <key>PBXSplitModuleInNavigatorKey</key>
409 <dict>
410 <key>Split0</key>
411 <dict>
412 <key>PBXProjectModuleGUID</key>
413 <string>1CE0B20406471E060097A5F4</string>
414 <key>PBXProjectModuleLabel</key>
415 <string>MyNewFile14.java</string>
416 </dict>
417 <key>SplitCount</key>
418 <string>1</string>
419 </dict>
420 <key>StatusBarVisibility</key>
421 <true/>
422 </dict>
423 <key>GeometryConfiguration</key>
424 <dict>
425 <key>Frame</key>
426 <string>{{0, 0}, {672, 0}}</string>
427 <key>RubberWindowFrame</key>
428 <string>243 337 880 562 0 0 1680 1028 </string>
429 </dict>
430 <key>Module</key>
431 <string>PBXNavigatorGroup</string>
432 <key>Proportion</key>
433 <string>0pt</string>
434 </dict>
435 <dict>
436 <key>ContentConfiguration</key>
437 <dict>
438 <key>PBXProjectModuleGUID</key>
439 <string>1CE0B20506471E060097A5F4</string>
440 <key>PBXProjectModuleLabel</key>
441 <string>Detail</string>
442 </dict>
443 <key>GeometryConfiguration</key>
444 <dict>
445 <key>Frame</key>
446 <string>{{0, 5}, {672, 516}}</string>
447 <key>RubberWindowFrame</key>
448 <string>243 337 880 562 0 0 1680 1028 </string>
449 </dict>
450 <key>Module</key>
451 <string>XCDetailModule</string>
452 <key>Proportion</key>
453 <string>516pt</string>
454 </dict>
455 </array>
456 <key>Proportion</key>
457 <string>672pt</string>
458 </dict>
459 </array>
460 <key>Name</key>
461 <string>Project</string>
462 <key>ServiceClasses</key>
463 <array>
464 <string>XCModuleDock</string>
465 <string>PBXSmartGroupTreeModule</string>
466 <string>XCModuleDock</string>
467 <string>PBXNavigatorGroup</string>
468 <string>XCDetailModule</string>
469 </array>
470 <key>TableOfContents</key>
471 <array>
472 <string>2736315A0CD71F3400A12F3E</string>
473 <string>1CE0B1FE06471DED0097A5F4</string>
474 <string>2736315B0CD71F3400A12F3E</string>
475 <string>1CE0B20306471E060097A5F4</string>
476 <string>1CE0B20506471E060097A5F4</string>
477 </array>
478 <key>ToolbarConfiguration</key>
479 <string>xcode.toolbar.config.default</string>
480 </dict>
481 <dict>
482 <key>ControllerClassBaseName</key>
483 <string></string>
484 <key>IconName</key>
485 <string>WindowOfProject</string>
486 <key>Identifier</key>
487 <string>perspective.morph</string>
488 <key>IsVertical</key>
489 <integer>0</integer>
490 <key>Layout</key>
491 <array>
492 <dict>
493 <key>BecomeActive</key>
494 <integer>1</integer>
495 <key>ContentConfiguration</key>
496 <dict>
497 <key>PBXBottomSmartGroupGIDs</key>
498 <array>
499 <string>1C37FBAC04509CD000000102</string>
500 <string>1C37FAAC04509CD000000102</string>
501 <string>1C08E77C0454961000C914BD</string>
502 <string>1C37FABC05509CD000000102</string>
503 <string>1C37FABC05539CD112110102</string>
504 <string>E2644B35053B69B200211256</string>
505 <string>1C37FABC04509CD000100104</string>
506 <string>1CC0EA4004350EF90044410B</string>
507 <string>1CC0EA4004350EF90041110B</string>
508 </array>
509 <key>PBXProjectModuleGUID</key>
510 <string>11E0B1FE06471DED0097A5F4</string>
511 <key>PBXProjectModuleLabel</key>
512 <string>Files</string>
513 <key>PBXProjectStructureProvided</key>
514 <string>yes</string>
515 <key>PBXSmartGroupTreeModuleColumnData</key>
516 <dict>
517 <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
518 <array>
519 <real>186</real>
520 </array>
521 <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
522 <array>
523 <string>MainColumn</string>
524 </array>
525 </dict>
526 <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
527 <dict>
528 <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
529 <array>
530 <string>29B97314FDCFA39411CA2CEA</string>
531 <string>1C37FABC05509CD000000102</string>
532 </array>
533 <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
534 <array>
535 <array>
536 <integer>0</integer>
537 </array>
538 </array>
539 <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
540 <string>{{0, 0}, {186, 337}}</string>
541 </dict>
542 <key>PBXTopSmartGroupGIDs</key>
543 <array/>
544 <key>XCIncludePerspectivesSwitch</key>
545 <integer>1</integer>
546 <key>XCSharingToken</key>
547 <string>com.apple.Xcode.GFSharingToken</string>
548 </dict>
549 <key>GeometryConfiguration</key>
550 <dict>
551 <key>Frame</key>
552 <string>{{0, 0}, {203, 355}}</string>
553 <key>GroupTreeTableConfiguration</key>
554 <array>
555 <string>MainColumn</string>
556 <real>186</real>
557 </array>
558 <key>RubberWindowFrame</key>
559 <string>373 269 690 397 0 0 1440 878 </string>
560 </dict>
561 <key>Module</key>
562 <string>PBXSmartGroupTreeModule</string>
563 <key>Proportion</key>
564 <string>100%</string>
565 </dict>
566 </array>
567 <key>Name</key>
568 <string>Morph</string>
569 <key>PreferredWidth</key>
570 <integer>300</integer>
571 <key>ServiceClasses</key>
572 <array>
573 <string>XCModuleDock</string>
574 <string>PBXSmartGroupTreeModule</string>
575 </array>
576 <key>TableOfContents</key>
577 <array>
578 <string>11E0B1FE06471DED0097A5F4</string>
579 </array>
580 <key>ToolbarConfiguration</key>
581 <string>xcode.toolbar.config.default.short</string>
582 </dict>
583 </array>
584 <key>PerspectivesBarVisible</key>
585 <false/>
586 <key>ShelfIsVisible</key>
587 <false/>
588 <key>SourceDescription</key>
589 <string>file at '/System/Library/PrivateFrameworks/DevToolsInterface.framework/Versions/A/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string>
590 <key>StatusbarIsVisible</key>
591 <true/>
592 <key>TimeStamp</key>
593 <real>215425482.989885</real>
594 <key>ToolbarDisplayMode</key>
595 <integer>1</integer>
596 <key>ToolbarIsVisible</key>
597 <true/>
598 <key>ToolbarSizeMode</key>
599 <integer>1</integer>
600 <key>Type</key>
601 <string>Perspectives</string>
602 <key>UpdateMessage</key>
603 <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string>
604 <key>WindowJustification</key>
605 <integer>5</integer>
606 <key>WindowOrderList</key>
607 <array>
608 <string>2736315E0CD71F3400A12F3E</string>
609 <string>2736315F0CD71F3400A12F3E</string>
610 <string>274A5F0A0C2F4351000A66CF</string>
611 <string>273631580CD71F2400A12F3E</string>
612 <string>27F6DA310C4416540054E42A</string>
613 <string>2784DBE60CD6544900B13CF3</string>
614 <string>/Users/abisoft/Slug/public/2007/Lua Modules/Lanes/xcode/xcode.xcodeproj</string>
615 <string>27602E740C2F3B100086E627</string>
616 <string>1CD10A99069EF8BA00B06720</string>
617 </array>
618 <key>WindowString</key>
619 <string>243 337 880 562 0 0 1680 1028 </string>
620 <key>WindowTools</key>
621 <array>
622 <dict>
623 <key>FirstTimeWindowDisplayed</key>
624 <false/>
625 <key>Identifier</key>
626 <string>windowTool.build</string>
627 <key>IsVertical</key>
628 <true/>
629 <key>Layout</key>
630 <array>
631 <dict>
632 <key>Dock</key>
633 <array>
634 <dict>
635 <key>ContentConfiguration</key>
636 <dict>
637 <key>PBXProjectModuleGUID</key>
638 <string>1CD0528F0623707200166675</string>
639 <key>PBXProjectModuleLabel</key>
640 <string></string>
641 <key>StatusBarVisibility</key>
642 <true/>
643 </dict>
644 <key>GeometryConfiguration</key>
645 <dict>
646 <key>Frame</key>
647 <string>{{0, 0}, {983, 267}}</string>
648 <key>RubberWindowFrame</key>
649 <string>541 112 983 821 0 0 1680 1028 </string>
650 </dict>
651 <key>Module</key>
652 <string>PBXNavigatorGroup</string>
653 <key>Proportion</key>
654 <string>267pt</string>
655 </dict>
656 <dict>
657 <key>BecomeActive</key>
658 <true/>
659 <key>ContentConfiguration</key>
660 <dict>
661 <key>PBXBuildLogShowsTranscriptDefaultKey</key>
662 <string>{{0, 5}, {983, 503}}</string>
663 <key>PBXProjectModuleGUID</key>
664 <string>XCMainBuildResultsModuleGUID</string>
665 <key>PBXProjectModuleLabel</key>
666 <string>Build</string>
667 <key>XCBuildResultsTrigger_Collapse</key>
668 <integer>1021</integer>
669 <key>XCBuildResultsTrigger_Open</key>
670 <integer>1010</integer>
671 </dict>
672 <key>GeometryConfiguration</key>
673 <dict>
674 <key>Frame</key>
675 <string>{{0, 272}, {983, 508}}</string>
676 <key>RubberWindowFrame</key>
677 <string>541 112 983 821 0 0 1680 1028 </string>
678 </dict>
679 <key>Module</key>
680 <string>PBXBuildResultsModule</string>
681 <key>Proportion</key>
682 <string>508pt</string>
683 </dict>
684 </array>
685 <key>Proportion</key>
686 <string>780pt</string>
687 </dict>
688 </array>
689 <key>Name</key>
690 <string>Build Results</string>
691 <key>ServiceClasses</key>
692 <array>
693 <string>PBXBuildResultsModule</string>
694 </array>
695 <key>StatusbarIsVisible</key>
696 <true/>
697 <key>TableOfContents</key>
698 <array>
699 <string>27602E740C2F3B100086E627</string>
700 <string>273631510CD71F2400A12F3E</string>
701 <string>1CD0528F0623707200166675</string>
702 <string>XCMainBuildResultsModuleGUID</string>
703 </array>
704 <key>ToolbarConfiguration</key>
705 <string>xcode.toolbar.config.build</string>
706 <key>WindowString</key>
707 <string>541 112 983 821 0 0 1680 1028 </string>
708 <key>WindowToolGUID</key>
709 <string>27602E740C2F3B100086E627</string>
710 <key>WindowToolIsVisible</key>
711 <true/>
712 </dict>
713 <dict>
714 <key>FirstTimeWindowDisplayed</key>
715 <false/>
716 <key>Identifier</key>
717 <string>windowTool.debugger</string>
718 <key>IsVertical</key>
719 <true/>
720 <key>Layout</key>
721 <array>
722 <dict>
723 <key>Dock</key>
724 <array>
725 <dict>
726 <key>ContentConfiguration</key>
727 <dict>
728 <key>Debugger</key>
729 <dict>
730 <key>HorizontalSplitView</key>
731 <dict>
732 <key>_collapsingFrameDimension</key>
733 <real>0.0</real>
734 <key>_indexOfCollapsedView</key>
735 <integer>0</integer>
736 <key>_percentageOfCollapsedView</key>
737 <real>0.0</real>
738 <key>isCollapsed</key>
739 <string>yes</string>
740 <key>sizes</key>
741 <array>
742 <string>{{0, 0}, {437, 275}}</string>
743 <string>{{437, 0}, {584, 275}}</string>
744 </array>
745 </dict>
746 <key>VerticalSplitView</key>
747 <dict>
748 <key>_collapsingFrameDimension</key>
749 <real>0.0</real>
750 <key>_indexOfCollapsedView</key>
751 <integer>0</integer>
752 <key>_percentageOfCollapsedView</key>
753 <real>0.0</real>
754 <key>isCollapsed</key>
755 <string>yes</string>
756 <key>sizes</key>
757 <array>
758 <string>{{0, 0}, {1021, 275}}</string>
759 <string>{{0, 275}, {1021, 605}}</string>
760 </array>
761 </dict>
762 </dict>
763 <key>LauncherConfigVersion</key>
764 <string>8</string>
765 <key>PBXProjectModuleGUID</key>
766 <string>1C162984064C10D400B95A72</string>
767 <key>PBXProjectModuleLabel</key>
768 <string>Debug - GLUTExamples (Underwater)</string>
769 </dict>
770 <key>GeometryConfiguration</key>
771 <dict>
772 <key>DebugConsoleDrawerSize</key>
773 <string>{100, 120}</string>
774 <key>DebugConsoleVisible</key>
775 <string>None</string>
776 <key>DebugConsoleWindowFrame</key>
777 <string>{{200, 200}, {500, 300}}</string>
778 <key>DebugSTDIOWindowFrame</key>
779 <string>{{200, 200}, {500, 300}}</string>
780 <key>Frame</key>
781 <string>{{0, 0}, {1021, 880}}</string>
782 <key>RubberWindowFrame</key>
783 <string>504 97 1021 921 0 0 1680 1028 </string>
784 </dict>
785 <key>Module</key>
786 <string>PBXDebugSessionModule</string>
787 <key>Proportion</key>
788 <string>880pt</string>
789 </dict>
790 </array>
791 <key>Proportion</key>
792 <string>880pt</string>
793 </dict>
794 </array>
795 <key>Name</key>
796 <string>Debugger</string>
797 <key>ServiceClasses</key>
798 <array>
799 <string>PBXDebugSessionModule</string>
800 </array>
801 <key>StatusbarIsVisible</key>
802 <true/>
803 <key>TableOfContents</key>
804 <array>
805 <string>1CD10A99069EF8BA00B06720</string>
806 <string>273631520CD71F2400A12F3E</string>
807 <string>1C162984064C10D400B95A72</string>
808 <string>273631530CD71F2400A12F3E</string>
809 <string>273631540CD71F2400A12F3E</string>
810 <string>273631550CD71F2400A12F3E</string>
811 <string>273631560CD71F2400A12F3E</string>
812 <string>273631570CD71F2400A12F3E</string>
813 <string>273631580CD71F2400A12F3E</string>
814 </array>
815 <key>ToolbarConfiguration</key>
816 <string>xcode.toolbar.config.debug</string>
817 <key>WindowString</key>
818 <string>504 97 1021 921 0 0 1680 1028 </string>
819 <key>WindowToolGUID</key>
820 <string>1CD10A99069EF8BA00B06720</string>
821 <key>WindowToolIsVisible</key>
822 <true/>
823 </dict>
824 <dict>
825 <key>Identifier</key>
826 <string>windowTool.find</string>
827 <key>Layout</key>
828 <array>
829 <dict>
830 <key>Dock</key>
831 <array>
832 <dict>
833 <key>Dock</key>
834 <array>
835 <dict>
836 <key>ContentConfiguration</key>
837 <dict>
838 <key>PBXProjectModuleGUID</key>
839 <string>1CDD528C0622207200134675</string>
840 <key>PBXProjectModuleLabel</key>
841 <string>&lt;No Editor&gt;</string>
842 <key>PBXSplitModuleInNavigatorKey</key>
843 <dict>
844 <key>Split0</key>
845 <dict>
846 <key>PBXProjectModuleGUID</key>
847 <string>1CD0528D0623707200166675</string>
848 </dict>
849 <key>SplitCount</key>
850 <string>1</string>
851 </dict>
852 <key>StatusBarVisibility</key>
853 <integer>1</integer>
854 </dict>
855 <key>GeometryConfiguration</key>
856 <dict>
857 <key>Frame</key>
858 <string>{{0, 0}, {781, 167}}</string>
859 <key>RubberWindowFrame</key>
860 <string>62 385 781 470 0 0 1440 878 </string>
861 </dict>
862 <key>Module</key>
863 <string>PBXNavigatorGroup</string>
864 <key>Proportion</key>
865 <string>781pt</string>
866 </dict>
867 </array>
868 <key>Proportion</key>
869 <string>50%</string>
870 </dict>
871 <dict>
872 <key>BecomeActive</key>
873 <integer>1</integer>
874 <key>ContentConfiguration</key>
875 <dict>
876 <key>PBXProjectModuleGUID</key>
877 <string>1CD0528E0623707200166675</string>
878 <key>PBXProjectModuleLabel</key>
879 <string>Project Find</string>
880 </dict>
881 <key>GeometryConfiguration</key>
882 <dict>
883 <key>Frame</key>
884 <string>{{8, 0}, {773, 254}}</string>
885 <key>RubberWindowFrame</key>
886 <string>62 385 781 470 0 0 1440 878 </string>
887 </dict>
888 <key>Module</key>
889 <string>PBXProjectFindModule</string>
890 <key>Proportion</key>
891 <string>50%</string>
892 </dict>
893 </array>
894 <key>Proportion</key>
895 <string>428pt</string>
896 </dict>
897 </array>
898 <key>Name</key>
899 <string>Project Find</string>
900 <key>ServiceClasses</key>
901 <array>
902 <string>PBXProjectFindModule</string>
903 </array>
904 <key>StatusbarIsVisible</key>
905 <integer>1</integer>
906 <key>TableOfContents</key>
907 <array>
908 <string>1C530D57069F1CE1000CFCEE</string>
909 <string>1C530D58069F1CE1000CFCEE</string>
910 <string>1C530D59069F1CE1000CFCEE</string>
911 <string>1CDD528C0622207200134675</string>
912 <string>1C530D5A069F1CE1000CFCEE</string>
913 <string>1CE0B1FE06471DED0097A5F4</string>
914 <string>1CD0528E0623707200166675</string>
915 </array>
916 <key>WindowString</key>
917 <string>62 385 781 470 0 0 1440 878 </string>
918 <key>WindowToolGUID</key>
919 <string>1C530D57069F1CE1000CFCEE</string>
920 <key>WindowToolIsVisible</key>
921 <integer>0</integer>
922 </dict>
923 <dict>
924 <key>Identifier</key>
925 <string>MENUSEPARATOR</string>
926 </dict>
927 <dict>
928 <key>FirstTimeWindowDisplayed</key>
929 <false/>
930 <key>Identifier</key>
931 <string>windowTool.debuggerConsole</string>
932 <key>IsVertical</key>
933 <true/>
934 <key>Layout</key>
935 <array>
936 <dict>
937 <key>Dock</key>
938 <array>
939 <dict>
940 <key>BecomeActive</key>
941 <true/>
942 <key>ContentConfiguration</key>
943 <dict>
944 <key>PBXProjectModuleGUID</key>
945 <string>1C78EAAC065D492600B07095</string>
946 <key>PBXProjectModuleLabel</key>
947 <string>Debugger Console</string>
948 </dict>
949 <key>GeometryConfiguration</key>
950 <dict>
951 <key>Frame</key>
952 <string>{{0, 0}, {873, 523}}</string>
953 <key>RubberWindowFrame</key>
954 <string>114 193 873 564 0 0 1680 1028 </string>
955 </dict>
956 <key>Module</key>
957 <string>PBXDebugCLIModule</string>
958 <key>Proportion</key>
959 <string>523pt</string>
960 </dict>
961 </array>
962 <key>Proportion</key>
963 <string>523pt</string>
964 </dict>
965 </array>
966 <key>Name</key>
967 <string>Debugger Console</string>
968 <key>ServiceClasses</key>
969 <array>
970 <string>PBXDebugCLIModule</string>
971 </array>
972 <key>StatusbarIsVisible</key>
973 <true/>
974 <key>TableOfContents</key>
975 <array>
976 <string>274A5F0A0C2F4351000A66CF</string>
977 <string>273631590CD71F2400A12F3E</string>
978 <string>1C78EAAC065D492600B07095</string>
979 </array>
980 <key>WindowString</key>
981 <string>114 193 873 564 0 0 1680 1028 </string>
982 <key>WindowToolGUID</key>
983 <string>274A5F0A0C2F4351000A66CF</string>
984 <key>WindowToolIsVisible</key>
985 <false/>
986 </dict>
987 <dict>
988 <key>Identifier</key>
989 <string>windowTool.run</string>
990 <key>Layout</key>
991 <array>
992 <dict>
993 <key>Dock</key>
994 <array>
995 <dict>
996 <key>ContentConfiguration</key>
997 <dict>
998 <key>LauncherConfigVersion</key>
999 <string>3</string>
1000 <key>PBXProjectModuleGUID</key>
1001 <string>1CD0528B0623707200166675</string>
1002 <key>PBXProjectModuleLabel</key>
1003 <string>Run</string>
1004 <key>Runner</key>
1005 <dict>
1006 <key>HorizontalSplitView</key>
1007 <dict>
1008 <key>_collapsingFrameDimension</key>
1009 <real>0.0</real>
1010 <key>_indexOfCollapsedView</key>
1011 <integer>0</integer>
1012 <key>_percentageOfCollapsedView</key>
1013 <real>0.0</real>
1014 <key>isCollapsed</key>
1015 <string>yes</string>
1016 <key>sizes</key>
1017 <array>
1018 <string>{{0, 0}, {493, 167}}</string>
1019 <string>{{0, 176}, {493, 267}}</string>
1020 </array>
1021 </dict>
1022 <key>VerticalSplitView</key>
1023 <dict>
1024 <key>_collapsingFrameDimension</key>
1025 <real>0.0</real>
1026 <key>_indexOfCollapsedView</key>
1027 <integer>0</integer>
1028 <key>_percentageOfCollapsedView</key>
1029 <real>0.0</real>
1030 <key>isCollapsed</key>
1031 <string>yes</string>
1032 <key>sizes</key>
1033 <array>
1034 <string>{{0, 0}, {405, 443}}</string>
1035 <string>{{414, 0}, {514, 443}}</string>
1036 </array>
1037 </dict>
1038 </dict>
1039 </dict>
1040 <key>GeometryConfiguration</key>
1041 <dict>
1042 <key>Frame</key>
1043 <string>{{0, 0}, {460, 159}}</string>
1044 <key>RubberWindowFrame</key>
1045 <string>316 696 459 200 0 0 1280 1002 </string>
1046 </dict>
1047 <key>Module</key>
1048 <string>PBXRunSessionModule</string>
1049 <key>Proportion</key>
1050 <string>159pt</string>
1051 </dict>
1052 </array>
1053 <key>Proportion</key>
1054 <string>159pt</string>
1055 </dict>
1056 </array>
1057 <key>Name</key>
1058 <string>Run Log</string>
1059 <key>ServiceClasses</key>
1060 <array>
1061 <string>PBXRunSessionModule</string>
1062 </array>
1063 <key>StatusbarIsVisible</key>
1064 <integer>1</integer>
1065 <key>TableOfContents</key>
1066 <array>
1067 <string>1C0AD2B3069F1EA900FABCE6</string>
1068 <string>1C0AD2B4069F1EA900FABCE6</string>
1069 <string>1CD0528B0623707200166675</string>
1070 <string>1C0AD2B5069F1EA900FABCE6</string>
1071 </array>
1072 <key>ToolbarConfiguration</key>
1073 <string>xcode.toolbar.config.run</string>
1074 <key>WindowString</key>
1075 <string>316 696 459 200 0 0 1280 1002 </string>
1076 <key>WindowToolGUID</key>
1077 <string>1C0AD2B3069F1EA900FABCE6</string>
1078 <key>WindowToolIsVisible</key>
1079 <integer>0</integer>
1080 </dict>
1081 <dict>
1082 <key>Identifier</key>
1083 <string>windowTool.scm</string>
1084 <key>Layout</key>
1085 <array>
1086 <dict>
1087 <key>Dock</key>
1088 <array>
1089 <dict>
1090 <key>ContentConfiguration</key>
1091 <dict>
1092 <key>PBXProjectModuleGUID</key>
1093 <string>1C78EAB2065D492600B07095</string>
1094 <key>PBXProjectModuleLabel</key>
1095 <string>&lt;No Editor&gt;</string>
1096 <key>PBXSplitModuleInNavigatorKey</key>
1097 <dict>
1098 <key>Split0</key>
1099 <dict>
1100 <key>PBXProjectModuleGUID</key>
1101 <string>1C78EAB3065D492600B07095</string>
1102 </dict>
1103 <key>SplitCount</key>
1104 <string>1</string>
1105 </dict>
1106 <key>StatusBarVisibility</key>
1107 <integer>1</integer>
1108 </dict>
1109 <key>GeometryConfiguration</key>
1110 <dict>
1111 <key>Frame</key>
1112 <string>{{0, 0}, {452, 0}}</string>
1113 <key>RubberWindowFrame</key>
1114 <string>743 379 452 308 0 0 1280 1002 </string>
1115 </dict>
1116 <key>Module</key>
1117 <string>PBXNavigatorGroup</string>
1118 <key>Proportion</key>
1119 <string>0pt</string>
1120 </dict>
1121 <dict>
1122 <key>BecomeActive</key>
1123 <integer>1</integer>
1124 <key>ContentConfiguration</key>
1125 <dict>
1126 <key>PBXProjectModuleGUID</key>
1127 <string>1CD052920623707200166675</string>
1128 <key>PBXProjectModuleLabel</key>
1129 <string>SCM</string>
1130 </dict>
1131 <key>GeometryConfiguration</key>
1132 <dict>
1133 <key>ConsoleFrame</key>
1134 <string>{{0, 259}, {452, 0}}</string>
1135 <key>Frame</key>
1136 <string>{{0, 7}, {452, 259}}</string>
1137 <key>RubberWindowFrame</key>
1138 <string>743 379 452 308 0 0 1280 1002 </string>
1139 <key>TableConfiguration</key>
1140 <array>
1141 <string>Status</string>
1142 <real>30</real>
1143 <string>FileName</string>
1144 <real>199</real>
1145 <string>Path</string>
1146 <real>197.09500122070312</real>
1147 </array>
1148 <key>TableFrame</key>
1149 <string>{{0, 0}, {452, 250}}</string>
1150 </dict>
1151 <key>Module</key>
1152 <string>PBXCVSModule</string>
1153 <key>Proportion</key>
1154 <string>262pt</string>
1155 </dict>
1156 </array>
1157 <key>Proportion</key>
1158 <string>266pt</string>
1159 </dict>
1160 </array>
1161 <key>Name</key>
1162 <string>SCM</string>
1163 <key>ServiceClasses</key>
1164 <array>
1165 <string>PBXCVSModule</string>
1166 </array>
1167 <key>StatusbarIsVisible</key>
1168 <integer>1</integer>
1169 <key>TableOfContents</key>
1170 <array>
1171 <string>1C78EAB4065D492600B07095</string>
1172 <string>1C78EAB5065D492600B07095</string>
1173 <string>1C78EAB2065D492600B07095</string>
1174 <string>1CD052920623707200166675</string>
1175 </array>
1176 <key>ToolbarConfiguration</key>
1177 <string>xcode.toolbar.config.scm</string>
1178 <key>WindowString</key>
1179 <string>743 379 452 308 0 0 1280 1002 </string>
1180 </dict>
1181 <dict>
1182 <key>FirstTimeWindowDisplayed</key>
1183 <false/>
1184 <key>Identifier</key>
1185 <string>windowTool.breakpoints</string>
1186 <key>IsVertical</key>
1187 <false/>
1188 <key>Layout</key>
1189 <array>
1190 <dict>
1191 <key>Dock</key>
1192 <array>
1193 <dict>
1194 <key>BecomeActive</key>
1195 <true/>
1196 <key>ContentConfiguration</key>
1197 <dict>
1198 <key>PBXBottomSmartGroupGIDs</key>
1199 <array>
1200 <string>1C77FABC04509CD000000102</string>
1201 </array>
1202 <key>PBXProjectModuleGUID</key>
1203 <string>1CE0B1FE06471DED0097A5F4</string>
1204 <key>PBXProjectModuleLabel</key>
1205 <string>Files</string>
1206 <key>PBXProjectStructureProvided</key>
1207 <string>no</string>
1208 <key>PBXSmartGroupTreeModuleColumnData</key>
1209 <dict>
1210 <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
1211 <array>
1212 <real>168</real>
1213 </array>
1214 <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
1215 <array>
1216 <string>MainColumn</string>
1217 </array>
1218 </dict>
1219 <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
1220 <dict>
1221 <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
1222 <array>
1223 <string>1C77FABC04509CD000000102</string>
1224 <string>1C3E0DCA080725EA00A55177</string>
1225 </array>
1226 <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
1227 <array>
1228 <array>
1229 <integer>1</integer>
1230 <integer>0</integer>
1231 </array>
1232 </array>
1233 <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
1234 <string>{{0, 0}, {168, 365}}</string>
1235 </dict>
1236 <key>PBXTopSmartGroupGIDs</key>
1237 <array/>
1238 <key>XCIncludePerspectivesSwitch</key>
1239 <false/>
1240 </dict>
1241 <key>GeometryConfiguration</key>
1242 <dict>
1243 <key>Frame</key>
1244 <string>{{0, 0}, {185, 383}}</string>
1245 <key>GroupTreeTableConfiguration</key>
1246 <array>
1247 <string>MainColumn</string>
1248 <real>168</real>
1249 </array>
1250 <key>RubberWindowFrame</key>
1251 <string>713 435 871 424 0 0 1680 1028 </string>
1252 </dict>
1253 <key>Module</key>
1254 <string>PBXSmartGroupTreeModule</string>
1255 <key>Proportion</key>
1256 <string>185pt</string>
1257 </dict>
1258 <dict>
1259 <key>ContentConfiguration</key>
1260 <dict>
1261 <key>PBXProjectModuleGUID</key>
1262 <string>1CA1AED706398EBD00589147</string>
1263 <key>PBXProjectModuleLabel</key>
1264 <string>Detail</string>
1265 </dict>
1266 <key>GeometryConfiguration</key>
1267 <dict>
1268 <key>Frame</key>
1269 <string>{{190, 0}, {681, 383}}</string>
1270 <key>RubberWindowFrame</key>
1271 <string>713 435 871 424 0 0 1680 1028 </string>
1272 </dict>
1273 <key>Module</key>
1274 <string>XCDetailModule</string>
1275 <key>Proportion</key>
1276 <string>681pt</string>
1277 </dict>
1278 </array>
1279 <key>Proportion</key>
1280 <string>383pt</string>
1281 </dict>
1282 </array>
1283 <key>MajorVersion</key>
1284 <integer>2</integer>
1285 <key>MinorVersion</key>
1286 <integer>0</integer>
1287 <key>Name</key>
1288 <string>Breakpoints</string>
1289 <key>ServiceClasses</key>
1290 <array>
1291 <string>PBXSmartGroupTreeModule</string>
1292 <string>XCDetailModule</string>
1293 </array>
1294 <key>StatusbarIsVisible</key>
1295 <true/>
1296 <key>TableOfContents</key>
1297 <array>
1298 <string>271333C40C4602BB005FEE0E</string>
1299 <string>271333C50C4602BB005FEE0E</string>
1300 <string>1CE0B1FE06471DED0097A5F4</string>
1301 <string>1CA1AED706398EBD00589147</string>
1302 </array>
1303 <key>ToolbarConfiguration</key>
1304 <string>xcode.toolbar.config.breakpoints</string>
1305 <key>WindowString</key>
1306 <string>713 435 871 424 0 0 1680 1028 </string>
1307 <key>WindowToolGUID</key>
1308 <string>271333C40C4602BB005FEE0E</string>
1309 <key>WindowToolIsVisible</key>
1310 <false/>
1311 </dict>
1312 <dict>
1313 <key>Identifier</key>
1314 <string>windowTool.debugAnimator</string>
1315 <key>Layout</key>
1316 <array>
1317 <dict>
1318 <key>Dock</key>
1319 <array>
1320 <dict>
1321 <key>Module</key>
1322 <string>PBXNavigatorGroup</string>
1323 <key>Proportion</key>
1324 <string>100%</string>
1325 </dict>
1326 </array>
1327 <key>Proportion</key>
1328 <string>100%</string>
1329 </dict>
1330 </array>
1331 <key>Name</key>
1332 <string>Debug Visualizer</string>
1333 <key>ServiceClasses</key>
1334 <array>
1335 <string>PBXNavigatorGroup</string>
1336 </array>
1337 <key>StatusbarIsVisible</key>
1338 <integer>1</integer>
1339 <key>ToolbarConfiguration</key>
1340 <string>xcode.toolbar.config.debugAnimator</string>
1341 <key>WindowString</key>
1342 <string>100 100 700 500 0 0 1280 1002 </string>
1343 </dict>
1344 <dict>
1345 <key>Identifier</key>
1346 <string>windowTool.bookmarks</string>
1347 <key>Layout</key>
1348 <array>
1349 <dict>
1350 <key>Dock</key>
1351 <array>
1352 <dict>
1353 <key>Module</key>
1354 <string>PBXBookmarksModule</string>
1355 <key>Proportion</key>
1356 <string>100%</string>
1357 </dict>
1358 </array>
1359 <key>Proportion</key>
1360 <string>100%</string>
1361 </dict>
1362 </array>
1363 <key>Name</key>
1364 <string>Bookmarks</string>
1365 <key>ServiceClasses</key>
1366 <array>
1367 <string>PBXBookmarksModule</string>
1368 </array>
1369 <key>StatusbarIsVisible</key>
1370 <integer>0</integer>
1371 <key>WindowString</key>
1372 <string>538 42 401 187 0 0 1280 1002 </string>
1373 </dict>
1374 <dict>
1375 <key>Identifier</key>
1376 <string>windowTool.classBrowser</string>
1377 <key>Layout</key>
1378 <array>
1379 <dict>
1380 <key>Dock</key>
1381 <array>
1382 <dict>
1383 <key>BecomeActive</key>
1384 <integer>1</integer>
1385 <key>ContentConfiguration</key>
1386 <dict>
1387 <key>OptionsSetName</key>
1388 <string>Hierarchy, all classes</string>
1389 <key>PBXProjectModuleGUID</key>
1390 <string>1CA6456E063B45B4001379D8</string>
1391 <key>PBXProjectModuleLabel</key>
1392 <string>Class Browser - NSObject</string>
1393 </dict>
1394 <key>GeometryConfiguration</key>
1395 <dict>
1396 <key>ClassesFrame</key>
1397 <string>{{0, 0}, {374, 96}}</string>
1398 <key>ClassesTreeTableConfiguration</key>
1399 <array>
1400 <string>PBXClassNameColumnIdentifier</string>
1401 <real>208</real>
1402 <string>PBXClassBookColumnIdentifier</string>
1403 <real>22</real>
1404 </array>
1405 <key>Frame</key>
1406 <string>{{0, 0}, {630, 331}}</string>
1407 <key>MembersFrame</key>
1408 <string>{{0, 105}, {374, 395}}</string>
1409 <key>MembersTreeTableConfiguration</key>
1410 <array>
1411 <string>PBXMemberTypeIconColumnIdentifier</string>
1412 <real>22</real>
1413 <string>PBXMemberNameColumnIdentifier</string>
1414 <real>216</real>
1415 <string>PBXMemberTypeColumnIdentifier</string>
1416 <real>97</real>
1417 <string>PBXMemberBookColumnIdentifier</string>
1418 <real>22</real>
1419 </array>
1420 <key>PBXModuleWindowStatusBarHidden2</key>
1421 <integer>1</integer>
1422 <key>RubberWindowFrame</key>
1423 <string>385 179 630 352 0 0 1440 878 </string>
1424 </dict>
1425 <key>Module</key>
1426 <string>PBXClassBrowserModule</string>
1427 <key>Proportion</key>
1428 <string>332pt</string>
1429 </dict>
1430 </array>
1431 <key>Proportion</key>
1432 <string>332pt</string>
1433 </dict>
1434 </array>
1435 <key>Name</key>
1436 <string>Class Browser</string>
1437 <key>ServiceClasses</key>
1438 <array>
1439 <string>PBXClassBrowserModule</string>
1440 </array>
1441 <key>StatusbarIsVisible</key>
1442 <integer>0</integer>
1443 <key>TableOfContents</key>
1444 <array>
1445 <string>1C0AD2AF069F1E9B00FABCE6</string>
1446 <string>1C0AD2B0069F1E9B00FABCE6</string>
1447 <string>1CA6456E063B45B4001379D8</string>
1448 </array>
1449 <key>ToolbarConfiguration</key>
1450 <string>xcode.toolbar.config.classbrowser</string>
1451 <key>WindowString</key>
1452 <string>385 179 630 352 0 0 1440 878 </string>
1453 <key>WindowToolGUID</key>
1454 <string>1C0AD2AF069F1E9B00FABCE6</string>
1455 <key>WindowToolIsVisible</key>
1456 <integer>0</integer>
1457 </dict>
1458 </array>
1459</dict>
1460</plist>
diff --git a/xcode/xcode.xcodeproj/abisoft.pbxuser b/xcode/xcode.xcodeproj/abisoft.pbxuser
new file mode 100644
index 0000000..3da9848
--- /dev/null
+++ b/xcode/xcode.xcodeproj/abisoft.pbxuser
@@ -0,0 +1,411 @@
1// !$*UTF8*$!
2{
3 08FB7793FE84155DC02AAC07 /* Project object */ = {
4 activeArchitecture = ppc;
5 activeBuildConfigurationName = Debug;
6 activeExecutable = 274A5EFC0C2F41FB000A66CF /* Lua 5.1 */;
7 activeTarget = D2AAC0620554660B00DB518D /* xcode */;
8 addToTargets = (
9 D2AAC0620554660B00DB518D /* xcode */,
10 );
11 breakpoints = (
12 27280DE10C495CCB000FD317 /* gluax_static.c:667 */,
13 27280DE60C495D0C000FD317 /* gluax_static.c:663 */,
14 27E802B50C4978C700B1E216 /* sdl_module.cpp:630 */,
15 277CF6980C4A631C0044B79E /* gluax.c:2476 */,
16 2784DBE20CD64B1000B13CF3 /* gluax_static.c:164 */,
17 273631630CD71FBC00A12F3E /* lanes.c:1429 */,
18 27BD9DD60E403B490056C472 /* lanes.c:1168 */,
19 27BD9DEB0E403C250056C472 /* lanes.c:1246 */,
20 );
21 codeSenseManager = 27602E610C2F36D60086E627 /* Code sense */;
22 executables = (
23 274A5EFC0C2F41FB000A66CF /* Lua 5.1 */,
24 );
25 perUserDictionary = {
26 "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA1AED706398EBD00589147" = {
27 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
28 PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID;
29 PBXFileTableDataSourceColumnWidthsKey = (
30 20,
31 20,
32 253,
33 20,
34 152,
35 151,
36 20,
37 );
38 PBXFileTableDataSourceColumnsKey = (
39 PBXBreakpointsDataSource_ActionID,
40 PBXBreakpointsDataSource_TypeID,
41 PBXBreakpointsDataSource_BreakpointID,
42 PBXBreakpointsDataSource_UseID,
43 PBXBreakpointsDataSource_LocationID,
44 PBXBreakpointsDataSource_ConditionID,
45 PBXBreakpointsDataSource_ContinueID,
46 );
47 };
48 PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
49 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
50 PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
51 PBXFileTableDataSourceColumnWidthsKey = (
52 22,
53 300,
54 304,
55 );
56 PBXFileTableDataSourceColumnsKey = (
57 PBXExecutablesDataSource_ActiveFlagID,
58 PBXExecutablesDataSource_NameID,
59 PBXExecutablesDataSource_CommentsID,
60 );
61 };
62 PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
63 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
64 PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
65 PBXFileTableDataSourceColumnWidthsKey = (
66 20,
67 416,
68 20,
69 48,
70 43,
71 43,
72 20,
73 );
74 PBXFileTableDataSourceColumnsKey = (
75 PBXFileDataSource_FiletypeID,
76 PBXFileDataSource_Filename_ColumnID,
77 PBXFileDataSource_Built_ColumnID,
78 PBXFileDataSource_ObjectSize_ColumnID,
79 PBXFileDataSource_Errors_ColumnID,
80 PBXFileDataSource_Warnings_ColumnID,
81 PBXFileDataSource_Target_ColumnID,
82 );
83 };
84 PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = {
85 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
86 PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
87 PBXFileTableDataSourceColumnWidthsKey = (
88 20,
89 200,
90 230,
91 20,
92 48,
93 43,
94 43,
95 );
96 PBXFileTableDataSourceColumnsKey = (
97 PBXFileDataSource_FiletypeID,
98 PBXFileDataSource_Filename_ColumnID,
99 PBXTargetDataSource_PrimaryAttribute,
100 PBXFileDataSource_Built_ColumnID,
101 PBXFileDataSource_ObjectSize_ColumnID,
102 PBXFileDataSource_Errors_ColumnID,
103 PBXFileDataSource_Warnings_ColumnID,
104 );
105 };
106 PBXPerProjectTemplateStateSaveDate = 239090487;
107 PBXWorkspaceStateSaveDate = 239090487;
108 };
109 perUserProjectItems = {
110 27BD9DD90E403B640056C472 /* PBXTextBookmark */ = 27BD9DD90E403B640056C472 /* PBXTextBookmark */;
111 27BD9DDA0E403B640056C472 /* PBXTextBookmark */ = 27BD9DDA0E403B640056C472 /* PBXTextBookmark */;
112 27BD9DDB0E403B640056C472 /* PBXTextBookmark */ = 27BD9DDB0E403B640056C472 /* PBXTextBookmark */;
113 27BD9DEE0E403C960056C472 /* PBXTextBookmark */ = 27BD9DEE0E403C960056C472 /* PBXTextBookmark */;
114 };
115 sourceControlManager = 27602E600C2F36D60086E627 /* Source Control */;
116 userBuildSettings = {
117 };
118 };
119 27280DE10C495CCB000FD317 /* gluax_static.c:667 */ = {
120 isa = PBXFileBreakpoint;
121 actions = (
122 );
123 breakpointStyle = 0;
124 continueAfterActions = 0;
125 countType = 0;
126 delayBeforeContinue = 0;
127 fileReference = 27602E620C2F37390086E627 /* gluax_static.c */;
128 hitCount = 0;
129 ignoreCount = 0;
130 lineNumber = 667;
131 modificationTime = 239090794.843809;
132 state = 1;
133 };
134 27280DE60C495D0C000FD317 /* gluax_static.c:663 */ = {
135 isa = PBXFileBreakpoint;
136 actions = (
137 );
138 breakpointStyle = 0;
139 continueAfterActions = 0;
140 countType = 0;
141 delayBeforeContinue = 0;
142 fileReference = 27602E620C2F37390086E627 /* gluax_static.c */;
143 hitCount = 0;
144 ignoreCount = 0;
145 lineNumber = 663;
146 modificationTime = 239090794.844094;
147 state = 1;
148 };
149 273631630CD71FBC00A12F3E /* lanes.c:1429 */ = {
150 isa = PBXFileBreakpoint;
151 actions = (
152 );
153 breakpointStyle = 0;
154 continueAfterActions = 0;
155 countType = 0;
156 delayBeforeContinue = 0;
157 fileReference = 279F2E690C4A463C0020A321 /* lanes.c */;
158 functionName = "GLUA_FUNC()";
159 hitCount = 0;
160 ignoreCount = 0;
161 lineNumber = 1429;
162 modificationTime = 239090794.843223;
163 state = 1;
164 };
165 274A5EFC0C2F41FB000A66CF /* Lua 5.1 */ = {
166 isa = PBXExecutable;
167 activeArgIndices = (
168 NO,
169 YES,
170 );
171 argumentStrings = (
172 "-lstrict ../fibonacci.lua",
173 tests/basic.lua,
174 );
175 autoAttachOnCrash = 1;
176 breakpointsEnabled = 1;
177 configStateDict = {
178 "PBXLSLaunchAction-0" = {
179 PBXLSLaunchAction = 0;
180 PBXLSLaunchStartAction = 1;
181 PBXLSLaunchStdioStyle = 2;
182 PBXLSLaunchStyle = 0;
183 class = PBXLSRunLaunchConfig;
184 commandLineArgs = (
185 );
186 displayName = "Executable Runner";
187 environment = {
188 };
189 identifier = com.apple.Xcode.launch.runConfig;
190 remoteHostInfo = "";
191 startActionInfo = "";
192 };
193 };
194 customDataFormattersEnabled = 1;
195 debuggerPlugin = GDBDebugging;
196 disassemblyDisplayState = 0;
197 dylibVariantSuffix = "";
198 enableDebugStr = 1;
199 environmentEntries = (
200 {
201 active = YES;
202 name = LUA_PATH;
203 value = "src/?.lua;/sw/share/lua/5.1/?.lua";
204 },
205 {
206 active = YES;
207 name = LUA_CPATH;
208 value = "xcode/build/Debug/lib?.bundle";
209 },
210 );
211 executableSystemSymbolLevel = 0;
212 executableUserSymbolLevel = 0;
213 launchableReference = 274A5EFD0C2F41FB000A66CF /* lua */;
214 libgmallocEnabled = 0;
215 name = "Lua 5.1";
216 savedGlobals = {
217 };
218 sourceDirectories = (
219 );
220 startupPath = /Users/abisoft/Slug/public/2008/Lanes/;
221 variableFormatDictionary = {
222 };
223 };
224 274A5EFD0C2F41FB000A66CF /* lua */ = {
225 isa = PBXFileReference;
226 explicitFileType = "compiled.mach-o.executable";
227 name = lua;
228 path = /sw/bin/lua;
229 sourceTree = "<absolute>";
230 };
231 27602E600C2F36D60086E627 /* Source Control */ = {
232 isa = PBXSourceControlManager;
233 fallbackIsa = XCSourceControlManager;
234 isSCMEnabled = 0;
235 scmConfiguration = {
236 };
237 scmType = "";
238 };
239 27602E610C2F36D60086E627 /* Code sense */ = {
240 isa = PBXCodeSenseManager;
241 indexTemplatePath = "";
242 };
243 27602E620C2F37390086E627 /* gluax_static.c */ = {
244 isa = PBXFileReference;
245 fileEncoding = 30;
246 lastKnownFileType = sourcecode.c.c;
247 name = gluax_static.c;
248 path = /Users/abisoft/Slug/public/2008/gluax/gluax_static.c;
249 sourceTree = "<absolute>";
250 };
251 27602E640C2F37390086E627 /* gluax.c */ = {
252 isa = PBXFileReference;
253 fileEncoding = 30;
254 lastKnownFileType = sourcecode.c.c;
255 name = gluax.c;
256 path = /Users/abisoft/Slug/public/2008/gluax/gluax.c;
257 sourceTree = "<absolute>";
258 };
259 27602E660C2F37390086E627 /* sdl_module.cpp */ = {
260 isa = PBXFileReference;
261 fileEncoding = 30;
262 lastKnownFileType = sourcecode.cpp.cpp;
263 name = sdl_module.cpp;
264 path = /Users/abisoft/Slug/public/2007/Lanes/sdl_module.cpp;
265 sourceTree = "<absolute>";
266 };
267 277CF6980C4A631C0044B79E /* gluax.c:2476 */ = {
268 isa = PBXFileBreakpoint;
269 actions = (
270 );
271 breakpointStyle = 0;
272 continueAfterActions = 0;
273 countType = 0;
274 delayBeforeContinue = 0;
275 fileReference = 27602E640C2F37390086E627 /* gluax.c */;
276 hitCount = 0;
277 ignoreCount = 0;
278 lineNumber = 2476;
279 modificationTime = 239090794.84353;
280 state = 1;
281 };
282 2784DBE20CD64B1000B13CF3 /* gluax_static.c:164 */ = {
283 isa = PBXFileBreakpoint;
284 actions = (
285 );
286 breakpointStyle = 0;
287 continueAfterActions = 0;
288 countType = 0;
289 delayBeforeContinue = 0;
290 fileReference = 27602E620C2F37390086E627 /* gluax_static.c */;
291 functionName = "Loc_PushMetatableRef_()";
292 hitCount = 0;
293 ignoreCount = 0;
294 lineNumber = 164;
295 modificationTime = 239090794.842868;
296 state = 1;
297 };
298 279F2E690C4A463C0020A321 /* lanes.c */ = {
299 isa = PBXFileReference;
300 fileEncoding = 30;
301 lastKnownFileType = sourcecode.c.c;
302 name = lanes.c;
303 path = /Users/abisoft/Slug/public/2008/Lanes/lanes.c;
304 sourceTree = "<absolute>";
305 };
306 27ACDA660E4031F6004F5C28 /* lanes.c */ = {
307 uiCtxt = {
308 sepNavIntBoundsRect = "{{0, 0}, {822, 17500}}";
309 sepNavSelRange = "{31197, 0}";
310 sepNavVisRange = "{30733, 1064}";
311 sepNavWindowFrame = "{{86, 51}, {1052, 971}}";
312 };
313 };
314 27ACDA680E4031F6004F5C28 /* tools.c */ = {
315 uiCtxt = {
316 sepNavIntBoundsRect = "{{0, 0}, {594, 13790}}";
317 sepNavSelRange = "{0, 0}";
318 sepNavVisRange = "{0, 1259}";
319 };
320 };
321 27BD9DD60E403B490056C472 /* lanes.c:1168 */ = {
322 isa = PBXFileBreakpoint;
323 actions = (
324 );
325 breakpointStyle = 0;
326 continueAfterActions = 0;
327 countType = 0;
328 delayBeforeContinue = 0;
329 fileReference = 27ACDA660E4031F6004F5C28 /* lanes.c */;
330 functionName = "luaopen_lanes()";
331 hitCount = 1;
332 ignoreCount = 0;
333 lineNumber = 1168;
334 location = "liblua51-lanes.bundle";
335 modificationTime = 239090520.812976;
336 state = 1;
337 };
338 27BD9DD90E403B640056C472 /* PBXTextBookmark */ = {
339 isa = PBXTextBookmark;
340 fRef = 27ACDA680E4031F6004F5C28 /* tools.c */;
341 name = "tools.c: 1";
342 rLen = 0;
343 rLoc = 0;
344 rType = 0;
345 vrLen = 1259;
346 vrLoc = 0;
347 };
348 27BD9DDA0E403B640056C472 /* PBXTextBookmark */ = {
349 isa = PBXTextBookmark;
350 fRef = 27ACDA660E4031F6004F5C28 /* lanes.c */;
351 rLen = 0;
352 rLoc = 1167;
353 rType = 1;
354 };
355 27BD9DDB0E403B640056C472 /* PBXTextBookmark */ = {
356 isa = PBXTextBookmark;
357 fRef = 27ACDA680E4031F6004F5C28 /* tools.c */;
358 name = "tools.c: 1";
359 rLen = 0;
360 rLoc = 0;
361 rType = 0;
362 vrLen = 1259;
363 vrLoc = 0;
364 };
365 27BD9DEB0E403C250056C472 /* lanes.c:1246 */ = {
366 isa = PBXFileBreakpoint;
367 actions = (
368 );
369 breakpointStyle = 0;
370 continueAfterActions = 0;
371 countType = 0;
372 delayBeforeContinue = 0;
373 fileReference = 27ACDA660E4031F6004F5C28 /* lanes.c */;
374 functionName = "luaopen_lanes()";
375 hitCount = 0;
376 ignoreCount = 0;
377 lineNumber = 1246;
378 location = "liblua51-lanes.bundle";
379 modificationTime = 239090725.673196;
380 state = 1;
381 };
382 27BD9DEE0E403C960056C472 /* PBXTextBookmark */ = {
383 isa = PBXTextBookmark;
384 fRef = 27ACDA660E4031F6004F5C28 /* lanes.c */;
385 name = "lanes.c: 1168";
386 rLen = 0;
387 rLoc = 31197;
388 rType = 0;
389 vrLen = 1064;
390 vrLoc = 30733;
391 };
392 27E802B50C4978C700B1E216 /* sdl_module.cpp:630 */ = {
393 isa = PBXFileBreakpoint;
394 actions = (
395 );
396 breakpointStyle = 0;
397 continueAfterActions = 0;
398 countType = 0;
399 delayBeforeContinue = 0;
400 fileReference = 27602E660C2F37390086E627 /* sdl_module.cpp */;
401 functionName = "GLUA_FUNC()";
402 hitCount = 0;
403 ignoreCount = 0;
404 lineNumber = 630;
405 modificationTime = 239090794.842249;
406 state = 1;
407 };
408 D2AAC0620554660B00DB518D /* xcode */ = {
409 activeExec = 0;
410 };
411}
diff --git a/xcode/xcode.xcodeproj/project.pbxproj b/xcode/xcode.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..d3b3442
--- /dev/null
+++ b/xcode/xcode.xcodeproj/project.pbxproj
@@ -0,0 +1,268 @@
1// !$*UTF8*$!
2{
3 archiveVersion = 1;
4 classes = {
5 };
6 objectVersion = 42;
7 objects = {
8
9/* Begin PBXBuildFile section */
10 27602E840C2F3CA40086E627 /* liblua.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 27602E830C2F3CA40086E627 /* liblua.dylib */; };
11 27ACDA690E4031F6004F5C28 /* lanes.c in Sources */ = {isa = PBXBuildFile; fileRef = 27ACDA660E4031F6004F5C28 /* lanes.c */; };
12 27ACDA6A0E4031F6004F5C28 /* threading.c in Sources */ = {isa = PBXBuildFile; fileRef = 27ACDA670E4031F6004F5C28 /* threading.c */; };
13 27ACDA6B0E4031F6004F5C28 /* tools.c in Sources */ = {isa = PBXBuildFile; fileRef = 27ACDA680E4031F6004F5C28 /* tools.c */; };
14/* End PBXBuildFile section */
15
16/* Begin PBXFileReference section */
17 27602E830C2F3CA40086E627 /* liblua.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = liblua.dylib; path = /sw/lib/liblua.dylib; sourceTree = "<absolute>"; };
18 279F2E7B0C4A477B0020A321 /* liblua51-lanes.bundle */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = "liblua51-lanes.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
19 27ACDA660E4031F6004F5C28 /* lanes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lanes.c; path = ../src/lanes.c; sourceTree = SOURCE_ROOT; };
20 27ACDA670E4031F6004F5C28 /* threading.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = threading.c; path = ../src/threading.c; sourceTree = SOURCE_ROOT; };
21 27ACDA680E4031F6004F5C28 /* tools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tools.c; path = ../src/tools.c; sourceTree = SOURCE_ROOT; };
22/* End PBXFileReference section */
23
24/* Begin PBXFrameworksBuildPhase section */
25 D289988505E68E00004EDB86 /* Frameworks */ = {
26 isa = PBXFrameworksBuildPhase;
27 buildActionMask = 2147483647;
28 files = (
29 27602E840C2F3CA40086E627 /* liblua.dylib in Frameworks */,
30 );
31 runOnlyForDeploymentPostprocessing = 0;
32 };
33/* End PBXFrameworksBuildPhase section */
34
35/* Begin PBXGroup section */
36 08FB7794FE84155DC02AAC07 /* xcode */ = {
37 isa = PBXGroup;
38 children = (
39 27602E830C2F3CA40086E627 /* liblua.dylib */,
40 08FB7795FE84155DC02AAC07 /* Source */,
41 1AB674ADFE9D54B511CA2CBB /* Products */,
42 );
43 comments = "\nTo use this XCode project, set \"active build configuration\" to Debug.\n\nYou may need to add \"custom executable\" to the \"Executables\" tree of the project, with:\n- path /sw/bin/lua\n- custom directory /Users/xxx/.../SDL/\n- arguments \"test.lua\"\n- environment LUA_CPATH xcode/build/Debug/lib?.bundle\n- \n\n---\nAK 25.6.2007 (open):\n\nHow to NOT have the \"lib\" prefix for bundles? Tried everything, still XCode places it there. :((\n\n /usr/bin/g++-4.0 -o /Users/abisoft/Slug/public/2007/SDL/xcode/build/Debug/liblua51-sdl.bundle ...\n\nHave to change the LUA_CPATH instead, so we can debug with this.\n\n---\nAK 25.6.2007 (solved):\nAfter changing dylib->bundle there were some issues, same as:\nhttp://osdir.com/ml/lang.realbasic.plugins/2007-01/msg00033.html\n\n\"Perform single-object prelink\" needs to be ticked.\n";
44 name = xcode;
45 sourceTree = "<group>";
46 };
47 08FB7795FE84155DC02AAC07 /* Source */ = {
48 isa = PBXGroup;
49 children = (
50 27ACDA660E4031F6004F5C28 /* lanes.c */,
51 27ACDA670E4031F6004F5C28 /* threading.c */,
52 27ACDA680E4031F6004F5C28 /* tools.c */,
53 );
54 name = Source;
55 sourceTree = "<group>";
56 };
57 1AB674ADFE9D54B511CA2CBB /* Products */ = {
58 isa = PBXGroup;
59 children = (
60 279F2E7B0C4A477B0020A321 /* liblua51-lanes.bundle */,
61 );
62 name = Products;
63 sourceTree = "<group>";
64 };
65/* End PBXGroup section */
66
67/* Begin PBXHeadersBuildPhase section */
68 D2AAC0600554660B00DB518D /* Headers */ = {
69 isa = PBXHeadersBuildPhase;
70 buildActionMask = 2147483647;
71 files = (
72 );
73 runOnlyForDeploymentPostprocessing = 0;
74 };
75/* End PBXHeadersBuildPhase section */
76
77/* Begin PBXNativeTarget section */
78 D2AAC0620554660B00DB518D /* xcode */ = {
79 isa = PBXNativeTarget;
80 buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "xcode" */;
81 buildPhases = (
82 D2AAC0600554660B00DB518D /* Headers */,
83 D2AAC0610554660B00DB518D /* Sources */,
84 D289988505E68E00004EDB86 /* Frameworks */,
85 );
86 buildRules = (
87 );
88 dependencies = (
89 );
90 name = xcode;
91 productName = xcode;
92 productReference = 279F2E7B0C4A477B0020A321 /* liblua51-lanes.bundle */;
93 productType = "com.apple.product-type.library.dynamic";
94 };
95/* End PBXNativeTarget section */
96
97/* Begin PBXProject section */
98 08FB7793FE84155DC02AAC07 /* Project object */ = {
99 isa = PBXProject;
100 buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "xcode" */;
101 compatibilityVersion = "Xcode 2.4";
102 hasScannedForEncodings = 1;
103 mainGroup = 08FB7794FE84155DC02AAC07 /* xcode */;
104 projectDirPath = "";
105 projectRoot = "";
106 targets = (
107 D2AAC0620554660B00DB518D /* xcode */,
108 );
109 };
110/* End PBXProject section */
111
112/* Begin PBXSourcesBuildPhase section */
113 D2AAC0610554660B00DB518D /* Sources */ = {
114 isa = PBXSourcesBuildPhase;
115 buildActionMask = 2147483647;
116 files = (
117 27ACDA690E4031F6004F5C28 /* lanes.c in Sources */,
118 27ACDA6A0E4031F6004F5C28 /* threading.c in Sources */,
119 27ACDA6B0E4031F6004F5C28 /* tools.c in Sources */,
120 );
121 runOnlyForDeploymentPostprocessing = 0;
122 };
123/* End PBXSourcesBuildPhase section */
124
125/* Begin XCBuildConfiguration section */
126 1DEB914B08733D8E0010E9CD /* Debug */ = {
127 isa = XCBuildConfiguration;
128 buildSettings = {
129 COPY_PHASE_STRIP = NO;
130 EXECUTABLE_PREFIX = lib;
131 GCC_DYNAMIC_NO_PIC = NO;
132 GCC_ENABLE_FIX_AND_CONTINUE = YES;
133 GCC_MODEL_TUNING = G5;
134 GCC_OPTIMIZATION_LEVEL = 0;
135 INSTALL_PATH = /usr/local/lib;
136 LIBRARY_SEARCH_PATHS = (
137 "$(inherited)",
138 /sw/lib,
139 );
140 PRODUCT_NAME = "lua51-lanes";
141 ZERO_LINK = NO;
142 };
143 name = Debug;
144 };
145 1DEB914C08733D8E0010E9CD /* Release */ = {
146 isa = XCBuildConfiguration;
147 buildSettings = {
148 ARCHS = (
149 ppc,
150 i386,
151 );
152 COPY_PHASE_STRIP = NO;
153 EXECUTABLE_PREFIX = lib;
154 GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
155 GCC_MODEL_TUNING = G5;
156 INSTALL_PATH = /usr/local/lib;
157 LIBRARY_SEARCH_PATHS = (
158 "$(inherited)",
159 /sw/lib,
160 );
161 PRODUCT_NAME = "lua51-lanes";
162 ZERO_LINK = NO;
163 };
164 name = Release;
165 };
166 1DEB914F08733D8E0010E9CD /* Debug */ = {
167 isa = XCBuildConfiguration;
168 buildSettings = {
169 BUNDLE_LOADER = /sw/bin/lua;
170 DYLIB_COMPATIBILITY_VERSION = "";
171 DYLIB_CURRENT_VERSION = "";
172 EXECUTABLE_EXTENSION = bundle;
173 EXECUTABLE_PREFIX = "";
174 GCC_ENABLE_CPP_EXCEPTIONS = NO;
175 GCC_ENABLE_CPP_RTTI = NO;
176 GCC_PREPROCESSOR_DEFINITIONS = (
177 GLUA_LUA51,
178 "_GNU_SOURCE=1",
179 _THREAD_SAFE,
180 );
181 GCC_WARN_ABOUT_RETURN_TYPE = YES;
182 GCC_WARN_PEDANTIC = NO;
183 GCC_WARN_UNUSED_VARIABLE = YES;
184 GENERATE_MASTER_OBJECT_FILE = YES;
185 HEADER_SEARCH_PATHS = (
186 ../../gluax,
187 /sw/include,
188 );
189 LIBRARY_SEARCH_PATHS = /sw/lib;
190 MACH_O_TYPE = mh_bundle;
191 OTHER_LDFLAGS = (
192 "-framework",
193 Cocoa,
194 );
195 PREBINDING = NO;
196 PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
197 PRELINK_LIBS = "";
198 PRODUCT_NAME = "lua51-lanes";
199 SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
200 SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
201 SHARED_PRECOMPS_DIR = "";
202 };
203 name = Debug;
204 };
205 1DEB915008733D8E0010E9CD /* Release */ = {
206 isa = XCBuildConfiguration;
207 buildSettings = {
208 BUNDLE_LOADER = /sw/bin/lua;
209 DYLIB_COMPATIBILITY_VERSION = "";
210 DYLIB_CURRENT_VERSION = "";
211 EXECUTABLE_EXTENSION = bundle;
212 EXECUTABLE_PREFIX = "";
213 GCC_ENABLE_CPP_EXCEPTIONS = NO;
214 GCC_ENABLE_CPP_RTTI = NO;
215 GCC_PREPROCESSOR_DEFINITIONS = (
216 GLUA_LUA51,
217 "_GNU_SOURCE=1",
218 _THREAD_SAFE,
219 );
220 GCC_WARN_ABOUT_RETURN_TYPE = YES;
221 GCC_WARN_PEDANTIC = NO;
222 GCC_WARN_UNUSED_VARIABLE = YES;
223 GENERATE_MASTER_OBJECT_FILE = YES;
224 HEADER_SEARCH_PATHS = (
225 ../../gluax,
226 /sw/include,
227 );
228 LIBRARY_SEARCH_PATHS = /sw/lib;
229 MACH_O_TYPE = mh_bundle;
230 OTHER_LDFLAGS = (
231 "-framework",
232 Cocoa,
233 );
234 PREBINDING = NO;
235 PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO;
236 PRELINK_LIBS = "";
237 PRODUCT_NAME = "lua51-lanes";
238 SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
239 SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
240 SHARED_PRECOMPS_DIR = "";
241 };
242 name = Release;
243 };
244/* End XCBuildConfiguration section */
245
246/* Begin XCConfigurationList section */
247 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "xcode" */ = {
248 isa = XCConfigurationList;
249 buildConfigurations = (
250 1DEB914B08733D8E0010E9CD /* Debug */,
251 1DEB914C08733D8E0010E9CD /* Release */,
252 );
253 defaultConfigurationIsVisible = 0;
254 defaultConfigurationName = Release;
255 };
256 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "xcode" */ = {
257 isa = XCConfigurationList;
258 buildConfigurations = (
259 1DEB914F08733D8E0010E9CD /* Debug */,
260 1DEB915008733D8E0010E9CD /* Release */,
261 );
262 defaultConfigurationIsVisible = 0;
263 defaultConfigurationName = Release;
264 };
265/* End XCConfigurationList section */
266 };
267 rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
268}
diff --git a/xcode/xcode.xcodeproj/soumya.pbxuser b/xcode/xcode.xcodeproj/soumya.pbxuser
new file mode 100644
index 0000000..20ae264
--- /dev/null
+++ b/xcode/xcode.xcodeproj/soumya.pbxuser
@@ -0,0 +1,124 @@
1// !$*UTF8*$!
2{
3 0429C3740C416BB800EC1476 /* Source Control */ = {
4 isa = PBXSourceControlManager;
5 fallbackIsa = XCSourceControlManager;
6 isSCMEnabled = 0;
7 scmConfiguration = {
8 };
9 scmType = "";
10 };
11 0429C3750C416BB800EC1476 /* Code sense */ = {
12 isa = PBXCodeSenseManager;
13 indexTemplatePath = "";
14 };
15 04C412EF0C42B7D500A0AD77 /* Lua */ = {
16 isa = PBXExecutable;
17 activeArgIndex = 0;
18 activeArgIndices = (
19 YES,
20 );
21 argumentStrings = (
22 test.lua,
23 );
24 autoAttachOnCrash = 1;
25 comments = "This is not stored in svn, is it?\n";
26 configStateDict = {
27 "PBXLSLaunchAction-0" = {
28 PBXLSLaunchAction = 0;
29 PBXLSLaunchStartAction = 1;
30 PBXLSLaunchStdioStyle = 2;
31 PBXLSLaunchStyle = 0;
32 class = PBXLSRunLaunchConfig;
33 displayName = "Executable Runner";
34 identifier = com.apple.Xcode.launch.runConfig;
35 remoteHostInfo = "";
36 startActionInfo = "";
37 };
38 };
39 customDataFormattersEnabled = 1;
40 debuggerPlugin = GDBDebugging;
41 disassemblyDisplayState = 0;
42 dylibVariantSuffix = "";
43 enableDebugStr = 1;
44 environmentEntries = (
45 {
46 active = YES;
47 name = LUA_CPATH;
48 value = "xcode/build/Debug/lib?.bundle";
49 },
50 );
51 executableSystemSymbolLevel = 0;
52 executableUserSymbolLevel = 0;
53 launchableReference = 04C412F00C42B7D500A0AD77 /* lua */;
54 libgmallocEnabled = 0;
55 name = Lua;
56 savedGlobals = {
57 };
58 sourceDirectories = (
59 );
60 startupPath = /Users/soumya/Slug/public/2007/SDL/;
61 };
62 04C412F00C42B7D500A0AD77 /* lua */ = {
63 isa = PBXFileReference;
64 explicitFileType = "compiled.mach-o.executable";
65 name = lua;
66 path = /sw/bin/lua;
67 sourceTree = "<absolute>";
68 };
69 08FB7793FE84155DC02AAC07 /* Project object */ = {
70 activeBuildConfigurationName = Debug;
71 activeExecutable = 04C412EF0C42B7D500A0AD77 /* Lua */;
72 activeTarget = D2AAC0620554660B00DB518D /* xcode */;
73 codeSenseManager = 0429C3750C416BB800EC1476 /* Code sense */;
74 executables = (
75 04C412EF0C42B7D500A0AD77 /* Lua */,
76 );
77 perUserDictionary = {
78 PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = {
79 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
80 PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID;
81 PBXFileTableDataSourceColumnWidthsKey = (
82 22,
83 300,
84 225,
85 );
86 PBXFileTableDataSourceColumnsKey = (
87 PBXExecutablesDataSource_ActiveFlagID,
88 PBXExecutablesDataSource_NameID,
89 PBXExecutablesDataSource_CommentsID,
90 );
91 };
92 PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = {
93 PBXFileTableDataSourceColumnSortingDirectionKey = "-1";
94 PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID;
95 PBXFileTableDataSourceColumnWidthsKey = (
96 20,
97 338,
98 20,
99 48,
100 43,
101 43,
102 20,
103 );
104 PBXFileTableDataSourceColumnsKey = (
105 PBXFileDataSource_FiletypeID,
106 PBXFileDataSource_Filename_ColumnID,
107 PBXFileDataSource_Built_ColumnID,
108 PBXFileDataSource_ObjectSize_ColumnID,
109 PBXFileDataSource_Errors_ColumnID,
110 PBXFileDataSource_Warnings_ColumnID,
111 PBXFileDataSource_Target_ColumnID,
112 );
113 };
114 PBXPerProjectTemplateStateSaveDate = 205699730;
115 PBXWorkspaceStateSaveDate = 205699730;
116 };
117 sourceControlManager = 0429C3740C416BB800EC1476 /* Source Control */;
118 userBuildSettings = {
119 };
120 };
121 D2AAC0620554660B00DB518D /* xcode */ = {
122 activeExec = 0;
123 };
124}