diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2013-02-13 20:30:04 +0100 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2013-02-13 20:30:26 +0100 |
commit | 577bca074df12c520f49e9361381f0cad78200c1 (patch) | |
tree | 188a4d1e3366a9351ea5b9689efbaf3f98996100 | |
parent | 131c11c2ae327de5b4db743a6a81eb9b57470d0e (diff) | |
download | lanes-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-- | CHANGES | 7 | ||||
-rw-r--r-- | docs/index.html | 68 | ||||
-rw-r--r-- | lanes-3.5.1-1.rockspec (renamed from lanes-3.4.2-1.rockspec) | 4 | ||||
-rw-r--r-- | src/keeper.c | 2 | ||||
-rw-r--r-- | src/lanes.c | 82 | ||||
-rw-r--r-- | src/lanes.h | 17 | ||||
-rw-r--r-- | src/lanes.lua | 30 | ||||
-rw-r--r-- | src/threading.c | 21 | ||||
-rw-r--r-- | src/threading.h | 18 | ||||
-rw-r--r-- | src/tools.c | 80 | ||||
-rw-r--r-- | src/tools.h | 1 |
11 files changed, 263 insertions, 67 deletions
@@ -1,5 +1,12 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 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 | |||
3 | CHANGE 58: BGe 30-Jan-13 | 10 | CHANGE 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> · | 38 | <a href="#description">Description</a> · |
39 | <a href="#systems">Supported systems</a> · | 39 | <a href="#systems">Supported systems</a> · |
40 | <a href="#installing">Building and Installing</a> | 40 | <a href="#installing">Building and Installing</a> · |
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 | ||
8 | package = "Lanes" | 8 | package = "Lanes" |
9 | 9 | ||
10 | version = "3.4.2-1" | 10 | version = "3.5.1-1" |
11 | 11 | ||
12 | source= { | 12 | source= { |
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 | ||
17 | description = { | 17 | description = { |
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 | ||
55 | char const* VERSION = "3.5.0"; | 55 | char 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 | */ | ||
2589 | void 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 | ||
2845 | int | 2866 | int 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) | ||
2849 | luaopen_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 | |||
2895 | static 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 | ||
2906 | void 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 | |||
12 | extern int LANES_API luaopen_lanes_core( lua_State* L); | ||
13 | |||
14 | // Call this to work with embedded Lanes instead of calling luaopen_lanes_core() | ||
15 | extern 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 | ||
202 | local valid_libs= { | 202 | local 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) |
87 | static void FAIL( const char *funcname, int rc ) { | 87 | static 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 | */ |
103 | time_d now_secs(void) { | 103 | time_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 | ||
50 | static 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 | |||
66 | void 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 | |||
45 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 83 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
46 | DEBUGSPEW_CODE( int debugspew_indent_depth = 0); | 84 | DEBUGSPEW_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 | ||
139 | static 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 | |||
101 | static const luaL_Reg libs[] = | 147 | static 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 | */ |
497 | extern void register_core_libfuncs_for_keeper( lua_State* L); | ||
446 | 498 | ||
447 | lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) | 499 | lua_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 |
30 | void 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 |