summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2013-02-13 20:30:04 +0100
committerBenoit Germain <bnt.germain@gmail.com>2013-02-13 20:30:26 +0100
commit577bca074df12c520f49e9361381f0cad78200c1 (patch)
tree188a4d1e3366a9351ea5b9689efbaf3f98996100
parent131c11c2ae327de5b4db743a6a81eb9b57470d0e (diff)
downloadlanes-3.5.1.tar.gz
lanes-3.5.1.tar.bz2
lanes-3.5.1.zip
version 3.5.1v3.5.1
* new lanes.h header and API call luaopen_lanes_embedded() for embedders * "lanes.core" is an acceptable library in the generator libs argument * library "*" wildcard also opens lanes.core * tweaked code for Xbox 360 build
-rw-r--r--CHANGES7
-rw-r--r--docs/index.html68
-rw-r--r--lanes-3.5.1-1.rockspec (renamed from lanes-3.4.2-1.rockspec)4
-rw-r--r--src/keeper.c2
-rw-r--r--src/lanes.c82
-rw-r--r--src/lanes.h17
-rw-r--r--src/lanes.lua30
-rw-r--r--src/threading.c21
-rw-r--r--src/threading.h18
-rw-r--r--src/tools.c80
-rw-r--r--src/tools.h1
11 files changed, 263 insertions, 67 deletions
diff --git a/CHANGES b/CHANGES
index 3957956..b6a3d53 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,12 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 59: BGe 12-Feb-13
4 * version 3.5.1
5 * new lanes.h header and API call luaopen_lanes_embedded() for embedders
6 * "lanes.core" is an acceptable library in the generator libs argument
7 * library "*" wildcard also opens lanes.core
8 * tweaked code for Xbox 360 build
9
3CHANGE 58: BGe 30-Jan-13 10CHANGE 58: BGe 30-Jan-13
4 * version 3.5.0 11 * version 3.5.0
5 * new: API lanes.require(), use it instead of regular require() for modules that export C functions you need to send over. 12 * new: API lanes.require(), use it instead of regular require() for modules that export C functions you need to send over.
diff --git a/docs/index.html b/docs/index.html
index 8b21a97..89710ab 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -37,7 +37,8 @@
37 <p class="bar"> 37 <p class="bar">
38 <a href="#description">Description</a> &middot; 38 <a href="#description">Description</a> &middot;
39 <a href="#systems">Supported systems</a> &middot; 39 <a href="#systems">Supported systems</a> &middot;
40 <a href="#installing">Building and Installing</a> 40 <a href="#installing">Building and Installing</a> &middot;
41 <a href="#embedding">Embedding</a>
41 </p> 42 </p>
42 43
43 <p class="bar"> 44 <p class="bar">
@@ -69,7 +70,7 @@
69 </p> 70 </p>
70 71
71 <p> 72 <p>
72 This document was revised on 30-Jan-13, and applies to version <tt>3.5.0</tt>. 73 This document was revised on 12-Feb-13, and applies to version <tt>3.5.1</tt>.
73 </p> 74 </p>
74 </font> 75 </font>
75 </center> 76 </center>
@@ -164,6 +165,65 @@
164</pre> 165</pre>
165 166
166 167
168<!-- embedding +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
169<hr/>
170<h2 id="embedding">Embedding</h2>
171<p>
172 When Lanes is embedded, it is possible to statically initialize with
173</p>
174<table border=1 bgcolor="#E0E0FF" cellpadding="10" style="width:50%">
175 <tr>
176 <td>
177 <pre> extern void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes);</pre>
178 </td>
179 </tr>
180</table>
181<p>
182 <tt>luaopen_lanes_embedded</tt> leaves the module table on the stack. <tt>lanes.configure()</tt> must still be called in order to use Lanes.
183 <br/>
184 If <tt>_luaopen_lanes</tt> is <tt>NULL</tt>, a default loader will simply attempt the equivalent of <tt>luaL_dofile( L, "lanes.lua")</tt>.
185</p>
186
187<p>
188 To embed Lanes, compile source files in you application. In any Lua state were you want to use Lanes, initialize it as follows:
189</p>
190
191<p>
192 <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%">
193 <tr>
194 <td>
195 <pre> #include "lanes.h"</pre>
196 <br/>
197 <pre> int load_lanes_lua( lua_State* L)</pre>
198 <pre> {</pre>
199 <pre> // retrieve lanes.lua from wherever it is stored and return the result of its execution</pre>
200 <pre> // trivial example 1:</pre>
201 <pre> luaL_dofile( L, "lanes.lua");</pre>
202 <br/>
203 <pre> // trivial example 2:</pre>
204 <pre> luaL_dostring( L, bin2c_lanes_lua);</pre>
205 <pre> }</pre>
206 <br/>
207 <pre> void embed_lanes( lua_State* L)</pre>
208 <pre> {</pre>
209 <pre> // we need base libraries for Lanes for work</pre>
210 <pre> luaL_openlibs( L);</pre>
211 <pre> ...</pre>
212 <pre> // will attempt luaL_dofile( L, "lanes.lua");</pre>
213 <pre> luaopen_lanes_embedded( L, NULL);</pre>
214 <pre> lua_pop( L, 1);</pre>
215 <pre> // another example with a custom loader</pre>
216 <pre> luaopen_lanes_embedded( L, load_lanes_lua);</pre>
217 <pre> lua_pop( L, 1);</pre>
218 <br/>
219 <pre> // a little test to make sure things work as expected</pre>
220 <pre> luaL_dostring( L, "local lanes = require 'lanes'.configure{with_timers = false}; local l = lanes.linda()");</pre>
221 <pre> }</pre>
222 </td>
223 </tr>
224 </table>
225</p>
226
167<!-- launching +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 227<!-- launching +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
168<hr/> 228<hr/>
169 229
@@ -438,7 +498,7 @@
438 </td> 498 </td>
439 <td/> 499 <td/>
440 <td> 500 <td>
441 All standard libraries (including those specific to LuaJIT and not listed above). This must be used alone. 501 All standard libraries (including those specific to LuaJIT and not listed above), as well as <tt>lanes.core</tt>. This must be used alone.
442 </td> 502 </td>
443 </tr> 503 </tr>
444 </table> 504 </table>
@@ -765,7 +825,7 @@
765</p> 825</p>
766 826
767<p> 827<p>
768 If the lane is still running after the timeout expired and <tt>force_kill</tt> is <tt>true</tt>, the OS thread running the lane is forcefully killed. This means no GC, and should generally be the last resort. 828 If the lane is still running after the timeout expired and <tt>force_kill</tt> is <tt>true</tt>, the OS thread running the lane is forcefully killed. This means no GC, probable OS resource leaks (thread stack, locks, DLL notifications), and should generally be the last resort.
769</p> 829</p>
770 830
771<p> 831<p>
diff --git a/lanes-3.4.2-1.rockspec b/lanes-3.5.1-1.rockspec
index 23699ea..39191f2 100644
--- a/lanes-3.4.2-1.rockspec
+++ b/lanes-3.5.1-1.rockspec
@@ -7,11 +7,11 @@
7 7
8package = "Lanes" 8package = "Lanes"
9 9
10version = "3.4.2-1" 10version = "3.5.1-1"
11 11
12source= { 12source= {
13 url= "git://github.com/LuaLanes/lanes.git", 13 url= "git://github.com/LuaLanes/lanes.git",
14 branch= "v3.4.2" 14 branch= "v3.5.1"
15} 15}
16 16
17description = { 17description = {
diff --git a/src/keeper.c b/src/keeper.c
index 3511b56..848fe2a 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -572,7 +572,7 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
572 // 572 //
573 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs 573 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs
574 // the others because they export functions that we may store in a keeper for transfer between lanes 574 // the others because they export functions that we may store in a keeper for transfer between lanes
575 K = luaG_newstate( L, _on_state_create, "*"); 575 K = luaG_newstate( L, _on_state_create, "K");
576 576
577 STACK_CHECK( K); 577 STACK_CHECK( K);
578 578
diff --git a/src/lanes.c b/src/lanes.c
index 2b3d8ac..7bd29ee 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.5.0"; 55char const* VERSION = "3.5.1";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -92,8 +92,9 @@ THE SOFTWARE.
92#include "threading.h" 92#include "threading.h"
93#include "tools.h" 93#include "tools.h"
94#include "keeper.h" 94#include "keeper.h"
95#include "lanes.h"
95 96
96#if !((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)) 97#if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC))
97# include <sys/time.h> 98# include <sys/time.h>
98#endif 99#endif
99 100
@@ -2580,6 +2581,26 @@ static const struct luaL_Reg lanes_functions [] = {
2580 {NULL, NULL} 2581 {NULL, NULL}
2581}; 2582};
2582 2583
2584
2585/*
2586 * minimal function registration for keepers, just so that we can populate the transfer databases with them
2587 * without recursively deadlocking ourselves during one-time inits
2588 */
2589void register_core_libfuncs_for_keeper( lua_State* L)
2590{
2591 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register_core_libfuncs_for_keeper()\n" INDENT_END));
2592 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2593 STACK_GROW( L, 1);
2594 STACK_CHECK( L);
2595 lua_newtable( L);
2596 luaG_registerlibfuncs( L, lanes_functions);
2597 STACK_MID( L, 1);
2598 populate_func_lookup_table( L, -1, "lanes.core");
2599 lua_pop( L, 1);
2600 STACK_END( L, 0);
2601 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2602}
2603
2583/* 2604/*
2584* One-time initializations 2605* One-time initializations
2585*/ 2606*/
@@ -2645,7 +2666,7 @@ static void init_once_LOCKED( lua_State* L, int const _on_state_create, int cons
2645 { 2666 {
2646 (void) luaL_error( L, "Unable to initialize: %s", err ); 2667 (void) luaL_error( L, "Unable to initialize: %s", err );
2647 } 2668 }
2648 2669
2649 // Initialize 'timer_deep'; a common Linda object shared by all states 2670 // Initialize 'timer_deep'; a common Linda object shared by all states
2650 // 2671 //
2651 ASSERT_L( timer_deep == NULL); 2672 ASSERT_L( timer_deep == NULL);
@@ -2842,43 +2863,54 @@ void EnableCrashingOnCrashes()
2842#endif // PLATFORM_WIN32 2863#endif // PLATFORM_WIN32
2843} 2864}
2844 2865
2845int 2866int LANES_API luaopen_lanes_core( lua_State* L)
2846#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2847__declspec(dllexport)
2848#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2849luaopen_lanes_core( lua_State* L)
2850{ 2867{
2851 EnableCrashingOnCrashes(); 2868 EnableCrashingOnCrashes();
2852 2869
2853 STACK_GROW( L, 3); 2870 STACK_GROW( L, 3);
2854 STACK_CHECK( L); 2871 STACK_CHECK( L);
2855 2872
2856 // sanity check: let's see if _"VERSION" matches what we we built against
2857 lua_getglobal( L, "_VERSION");
2858 lua_pushstring( L, LUA_VERSION_NUM == 501 ? "Lua 5.1" : "Lua 5.2");
2859 if( !lua_rawequal( L, -1, -2))
2860 {
2861 return luaL_error( L, "Lanes is built against %s, but you are running %s", lua_tostring( L, -1), lua_tostring( L, -2));
2862 }
2863 lua_pop( L, 2);
2864
2865 // Create main module interface table 2873 // Create main module interface table
2866 // we only have 1 closure, which must be called to configure Lanes 2874 // we only have 1 closure, which must be called to configure Lanes
2867 lua_newtable(L); 2875 lua_newtable(L); // M
2868 lua_pushvalue(L, 1); // module name 2876 lua_pushvalue(L, 1); // M "lanes.core"
2869 lua_pushvalue(L, -2); // module table 2877 lua_pushvalue(L, -2); // M "lanes.core" M
2870 lua_pushcclosure( L, LG_configure, 2); 2878 lua_pushcclosure( L, LG_configure, 2); // M LG_configure()
2871 if( s_initCount == 0) 2879 if( s_initCount == 0)
2872 { 2880 {
2873 lua_setfield( L, -2, "configure"); 2881 lua_setfield( L, -2, "configure"); // M
2874 } 2882 }
2875 else // already initialized: call it immediately and be done 2883 else // already initialized: call it immediately and be done
2876 { 2884 {
2877 lua_pushinteger( L, 666); // any value will do, it will be ignored 2885 // any parameter value will do, they will be ignored
2878 lua_pushnil( L); // almost idem 2886 lua_pushinteger( L, 666); // M LG_configure() 666
2879 lua_call( L, 2, 0); 2887 lua_pushnil( L); // M LG_configure() 666 nil
2888 lua_call( L, 2, 0); // M
2880 } 2889 }
2881 2890
2882 STACK_END( L, 1); 2891 STACK_END( L, 1);
2883 return 1; 2892 return 1;
2884} 2893}
2894
2895static int default_luaopen_lanes( lua_State* L)
2896{
2897 int rc = luaL_loadfile( L, "lanes.lua") || lua_pcall( L, 0, 1, 0);
2898 if( rc != LUA_OK)
2899 {
2900 return luaL_error( L, "failed to initialize embedded Lanes");
2901 }
2902 return 1;
2903}
2904
2905// call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application
2906void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes)
2907{
2908 STACK_CHECK( L);
2909 // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded
2910 luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core
2911 lua_pop( L, 1); // ...
2912 STACK_MID( L, 0);
2913 // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it
2914 luaL_requiref( L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes
2915 STACK_END( L, 1);
2916}
diff --git a/src/lanes.h b/src/lanes.h
new file mode 100644
index 0000000..d07750a
--- /dev/null
+++ b/src/lanes.h
@@ -0,0 +1,17 @@
1#if !defined( __lanes_h__)
2#define __lanes_h__ 1
3
4#include "lua.h"
5
6#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
7#define LANES_API __declspec(dllexport)
8#else
9#define LANES_API
10#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
11
12extern int LANES_API luaopen_lanes_core( lua_State* L);
13
14// Call this to work with embedded Lanes instead of calling luaopen_lanes_core()
15extern void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes);
16
17#endif // __lanes_h__ \ No newline at end of file
diff --git a/src/lanes.lua b/src/lanes.lua
index f4eef81..729116e 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -52,7 +52,7 @@ lanes.configure = function( _params)
52 end 52 end
53 53
54 -- 54 --
55 -- Cache globals for code that might run under sandboxing 55 -- Cache globals for code that might run under sandboxing
56 -- 56 --
57 local assert = assert 57 local assert = assert
58 local string_gmatch = assert( string.gmatch) 58 local string_gmatch = assert( string.gmatch)
@@ -199,18 +199,20 @@ end
199-- and call the generator later (maybe multiple times, with different parameters) 199-- and call the generator later (maybe multiple times, with different parameters)
200-- or add on actual thread arguments to also ignite the thread on the same call. 200-- or add on actual thread arguments to also ignite the thread on the same call.
201 201
202local valid_libs= { 202local valid_libs=
203 ["package"]= true, 203{
204 ["table"]= true, 204 ["package"] = true,
205 ["io"]= true, 205 ["table"] = true,
206 ["os"]= true, 206 ["io"] = true,
207 ["string"]= true, 207 ["os"] = true,
208 ["math"]= true, 208 ["string"] = true,
209 ["debug"]= true, 209 ["math"] = true,
210 ["bit32"]= true, -- Lua 5.2 only, ignored silently under 5.1 210 ["debug"] = true,
211 -- 211 ["bit32"] = true, -- Lua 5.2 only, ignored silently under 5.1
212 ["base"]= true, 212 --
213 ["coroutine"]= true 213 ["base"] = true,
214 ["coroutine"] = true, -- part of "base" in Lua 5.1
215 ["lanes.core"] = true
214} 216}
215 217
216-- PUBLIC LANES API 218-- PUBLIC LANES API
@@ -253,7 +255,7 @@ local function gen( ... )
253 if libs and libs ~= "*" then 255 if libs and libs ~= "*" then
254 local found = {} 256 local found = {}
255 -- check that the caller only provides reserved library names 257 -- check that the caller only provides reserved library names
256 for s in string_gmatch(libs, "[%a%d]+") do 258 for s in string_gmatch(libs, "[%a%d.]+") do
257 if not valid_libs[s] then 259 if not valid_libs[s] then
258 error( "Bad library name: " .. s) 260 error( "Bad library name: " .. s)
259 else 261 else
diff --git a/src/threading.c b/src/threading.c
index d19fe1a..754b6d1 100644
--- a/src/threading.c
+++ b/src/threading.c
@@ -42,7 +42,7 @@ THE SOFTWARE.
42#include "threading.h" 42#include "threading.h"
43#include "lua.h" 43#include "lua.h"
44 44
45#if !defined( PLATFORM_WIN32) && !defined( PLATFORM_POCKETPC) 45#if !defined( PLATFORM_XBOX) && !defined( PLATFORM_WIN32) && !defined( PLATFORM_POCKETPC)
46# include <sys/time.h> 46# include <sys/time.h>
47#endif // non-WIN32 timing 47#endif // non-WIN32 timing
48 48
@@ -83,7 +83,7 @@ THE SOFTWARE.
83* FAIL is for unexpected API return values - essentially programming 83* FAIL is for unexpected API return values - essentially programming
84* error in _this_ code. 84* error in _this_ code.
85*/ 85*/
86#if defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 86#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
87static void FAIL( const char *funcname, int rc ) { 87static void FAIL( const char *funcname, int rc ) {
88 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); 88 fprintf( stderr, "%s() failed! (%d)\n", funcname, rc );
89#ifdef _MSC_VER 89#ifdef _MSC_VER
@@ -102,7 +102,7 @@ static void FAIL( const char *funcname, int rc ) {
102*/ 102*/
103time_d now_secs(void) { 103time_d now_secs(void) {
104 104
105#if defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 105#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
106 /* 106 /*
107 * Windows FILETIME values are "100-nanosecond intervals since 107 * Windows FILETIME values are "100-nanosecond intervals since
108 * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as 108 * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as
@@ -226,7 +226,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) {
226// valid values N * 4KB 226// valid values N * 4KB
227// 227//
228#ifndef _THREAD_STACK_SIZE 228#ifndef _THREAD_STACK_SIZE
229# if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PLATFORM_CYGWIN) 229# if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) || defined( PLATFORM_CYGWIN)
230# define _THREAD_STACK_SIZE 0 230# define _THREAD_STACK_SIZE 0
231 // Win32: does it work with less? 231 // Win32: does it work with less?
232# elif (defined PLATFORM_OSX) 232# elif (defined PLATFORM_OSX)
@@ -311,10 +311,15 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs)
311 return TRUE; 311 return TRUE;
312 } 312 }
313 // 313 //
314 void THREAD_KILL( THREAD_T *ref ) { 314 void THREAD_KILL( THREAD_T *ref )
315 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError()); 315 {
316 *ref= NULL; 316 // nonexistent on Xbox360, simply disable until a better solution is found
317 } 317 #if !defined( PLATFORM_XBOX)
318 // in theory no-one should call this as it is very dangerous (memory and mutex leaks, no notification of DLLs, etc.)
319 if (!TerminateThread( *ref, 0 )) FAIL("TerminateThread", GetLastError());
320 #endif // PLATFORM_XBOX
321 *ref= NULL;
322 }
318 323
319#if !defined __GNUC__ 324#if !defined __GNUC__
320 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx 325 //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
diff --git a/src/threading.h b/src/threading.h
index 1d304fa..1b218b9 100644
--- a/src/threading.h
+++ b/src/threading.h
@@ -11,6 +11,8 @@
11 */ 11 */
12#ifdef _WIN32_WCE 12#ifdef _WIN32_WCE
13 #define PLATFORM_POCKETPC 13 #define PLATFORM_POCKETPC
14#elif defined(_XBOX)
15 #define PLATFORM_XBOX
14#elif (defined _WIN32) 16#elif (defined _WIN32)
15 #define PLATFORM_WIN32 17 #define PLATFORM_WIN32
16#elif (defined __linux__) 18#elif (defined __linux__)
@@ -47,7 +49,7 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
47#define THREADAPI_WINDOWS 1 49#define THREADAPI_WINDOWS 1
48#define THREADAPI_PTHREAD 2 50#define THREADAPI_PTHREAD 2
49 51
50#if( defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD) 52#if( defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) && !defined( HAVE_WIN32_PTHREAD)
51#define THREADAPI THREADAPI_WINDOWS 53#define THREADAPI THREADAPI_WINDOWS
52#else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 54#else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
53#define THREADAPI THREADAPI_PTHREAD 55#define THREADAPI THREADAPI_PTHREAD
@@ -57,10 +59,14 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
57*/ 59*/
58 60
59#if THREADAPI == THREADAPI_WINDOWS 61#if THREADAPI == THREADAPI_WINDOWS
60 #define WIN32_LEAN_AND_MEAN 62 #if defined ( PLATFORM_XBOX)
61 // 'SignalObjectAndWait' needs this (targets Windows 2000 and above) 63 #include <xtl.h>
62 #define _WIN32_WINNT 0x0400 64 #else // !PLATFORM_XBOX
63 #include <windows.h> 65 #define WIN32_LEAN_AND_MEAN
66 // 'SignalObjectAndWait' needs this (targets Windows 2000 and above)
67 #define _WIN32_WINNT 0x0400
68 #include <windows.h>
69 #endif // !PLATFORM_XBOX
64 #include <process.h> 70 #include <process.h>
65 71
66 // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx 72 // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx
@@ -119,7 +125,7 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
119 // 125 //
120 #if defined( PLATFORM_OSX) 126 #if defined( PLATFORM_OSX)
121 #define YIELD() pthread_yield_np() 127 #define YIELD() pthread_yield_np()
122 #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) 128 #elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) // no PTHREAD for PLATFORM_XBOX
123 // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield() 129 // for some reason win32-pthread doesn't have pthread_yield(), but sched_yield()
124 #define YIELD() sched_yield() 130 #define YIELD() sched_yield()
125 #else 131 #else
diff --git a/src/tools.c b/src/tools.c
index 13a3ebd..f72663f 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -33,6 +33,7 @@ THE SOFTWARE.
33 33
34#include "tools.h" 34#include "tools.h"
35#include "keeper.h" 35#include "keeper.h"
36#include "lanes.h"
36 37
37#include "lualib.h" 38#include "lualib.h"
38#include "lauxlib.h" 39#include "lauxlib.h"
@@ -42,6 +43,43 @@ THE SOFTWARE.
42#include <ctype.h> 43#include <ctype.h>
43#include <stdlib.h> 44#include <stdlib.h>
44 45
46/*
47** Copied from Lua 5.2 loadlib.c
48*/
49#if LUA_VERSION_NUM == 501
50static int luaL_getsubtable (lua_State *L, int idx, const char *fname)
51{
52 lua_getfield(L, idx, fname);
53 if (lua_istable(L, -1))
54 return 1; /* table already there */
55 else
56 {
57 lua_pop(L, 1); /* remove previous result */
58 idx = lua_absindex(L, idx);
59 lua_newtable(L);
60 lua_pushvalue(L, -1); /* copy to be left at top */
61 lua_setfield(L, idx, fname); /* assign new table to field */
62 return 0; /* false, because did not find table there */
63 }
64}
65
66void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb)
67{
68 lua_pushcfunction(L, openf);
69 lua_pushstring(L, modname); /* argument to open function */
70 lua_call(L, 1, 1); /* open module */
71 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
72 lua_pushvalue(L, -2); /* make copy of module (call result) */
73 lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
74 lua_pop(L, 1); /* remove _LOADED table */
75 if (glb)
76 {
77 lua_pushvalue(L, -1); /* copy of 'mod' */
78 lua_setglobal(L, modname); /* _G[modname] = module */
79 }
80}
81#endif // LUA_VERSION_NUM
82
45DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); 83DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+");
46DEBUGSPEW_CODE( int debugspew_indent_depth = 0); 84DEBUGSPEW_CODE( int debugspew_indent_depth = 0);
47 85
@@ -98,14 +136,24 @@ void luaG_dump( lua_State* L ) {
98 136
99/*---=== luaG_newstate ===---*/ 137/*---=== luaG_newstate ===---*/
100 138
139static int require_lanes_core( lua_State* L)
140{
141 // leaves a copy of 'lanes.core' module table on the stack
142 luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0);
143 return 1;
144}
145
146
101static const luaL_Reg libs[] = 147static const luaL_Reg libs[] =
102{ 148{
103 { LUA_LOADLIBNAME, luaopen_package}, 149 { LUA_LOADLIBNAME, luaopen_package},
104 { LUA_TABLIBNAME, luaopen_table}, 150 { LUA_TABLIBNAME, luaopen_table},
105 { LUA_STRLIBNAME, luaopen_string}, 151 { LUA_STRLIBNAME, luaopen_string},
106 { LUA_MATHLIBNAME, luaopen_math}, 152 { LUA_MATHLIBNAME, luaopen_math},
153#ifndef PLATFORM_XBOX // no os/io libs on xbox
107 { LUA_OSLIBNAME, luaopen_os}, 154 { LUA_OSLIBNAME, luaopen_os},
108 { LUA_IOLIBNAME, luaopen_io}, 155 { LUA_IOLIBNAME, luaopen_io},
156#endif // PLATFORM_XBOX
109#if LUA_VERSION_NUM >= 502 157#if LUA_VERSION_NUM >= 502
110 { LUA_BITLIBNAME, luaopen_bit32}, 158 { LUA_BITLIBNAME, luaopen_bit32},
111 { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base! 159 { LUA_COLIBNAME, luaopen_coroutine}, // Lua 5.2: coroutine is no longer a part of base!
@@ -113,6 +161,7 @@ static const luaL_Reg libs[] =
113 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package 161 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package
114#endif // LUA_VERSION_NUM 162#endif // LUA_VERSION_NUM
115 { LUA_DBLIBNAME, luaopen_debug}, 163 { LUA_DBLIBNAME, luaopen_debug},
164 { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function)
116 // 165 //
117 { "base", NULL}, // ignore "base" (already acquired it) 166 { "base", NULL}, // ignore "base" (already acquired it)
118 { NULL, NULL } 167 { NULL, NULL }
@@ -135,9 +184,11 @@ static void open1lib( lua_State* L, char const* name, size_t len)
135 lua_pop( L, 1); 184 lua_pop( L, 1);
136#else // LUA_VERSION_NUM 185#else // LUA_VERSION_NUM
137 STACK_GROW( L, 1); 186 STACK_GROW( L, 1);
187 // push function and 1 argument on the stack
138 lua_pushcfunction( L, libs[i].func); 188 lua_pushcfunction( L, libs[i].func);
139 // pushes the module table on the stack 189 lua_pushstring( L, libs[i].name);
140 lua_call( L, 0, 0); 190 // call function, pushes the module table on the stack
191 lua_call( L, 1, 0);
141#endif // LUA_VERSION_NUM 192#endif // LUA_VERSION_NUM
142 STACK_END( L, 0); 193 STACK_END( L, 0);
143 } 194 }
@@ -443,6 +494,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name)
443* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. 494* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
444* 495*
445*/ 496*/
497extern void register_core_libfuncs_for_keeper( lua_State* L);
446 498
447lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) 499lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs)
448{ 500{
@@ -475,10 +527,24 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
475 // 527 //
476 if( libs) 528 if( libs)
477 { 529 {
478 if( libs[0] == '*' && libs[1] == 0) // special "*" case (mainly to help with LuaJIT compatibility) 530 // special "*" case (mainly to help with LuaJIT compatibility)
531 // "K" is used when opening keeper states: almost the same as "*", but for the fact we don't open lanes.core
532 // as we are called from luaopen_lanes_core() already, and that would deadlock
533 if( (libs[0] == '*' || libs[0] == 'K') && libs[1] == 0)
479 { 534 {
480 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 535 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END));
481 luaL_openlibs( L); 536 luaL_openlibs( L);
537 if( libs[0] == '*')
538 {
539 // don't forget lanes.core for regular lane states
540 open1lib( L, "lanes.core", 10);
541 }
542 else
543 {
544 // In keeper states however, we only want to register the lanes.core functions to be able to transfer them through lindas
545 // (we don't care about a full lanes.core init in the keeper states as we won't call anything in there)
546 register_core_libfuncs_for_keeper( L);
547 }
482 libs = NULL; // done with libs 548 libs = NULL; // done with libs
483 } 549 }
484 else 550 else
@@ -504,12 +570,12 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
504 unsigned int len = 0; 570 unsigned int len = 0;
505 for( p = libs; *p; p += len) 571 for( p = libs; *p; p += len)
506 { 572 {
507 len = 0; 573 // skip delimiters ('.' can be part of name for "lanes.core")
508 // skip delimiters 574 while( *p && !isalnum( *p) && *p != '.')
509 while( *p && !isalnum( *p))
510 ++ p; 575 ++ p;
511 // skip name 576 // skip name
512 while( isalnum( p[len])) 577 len = 0;
578 while( isalnum( p[len]) || p[len] == '.')
513 ++ len; 579 ++ len;
514 // open library 580 // open library
515 open1lib( L, p, len); 581 open1lib( L, p, len);
diff --git a/src/tools.h b/src/tools.h
index a06e23f..10711d4 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -27,6 +27,7 @@
27#define luaG_registerlibfuncs( L, _funcs) luaL_register( L, NULL, _funcs) 27#define luaG_registerlibfuncs( L, _funcs) luaL_register( L, NULL, _funcs)
28#define LUA_OK 0 28#define LUA_OK 0
29#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value 29#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value
30void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int glb); // implementation copied from Lua 5.2 sources
30#endif // LUA_VERSION_NUM == 501 31#endif // LUA_VERSION_NUM == 501
31 32
32// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way 33// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way