diff options
-rw-r--r-- | CHANGES | 10 | ||||
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/deep.c | 38 | ||||
-rw-r--r-- | src/deep.h | 25 | ||||
-rw-r--r-- | src/keeper.c | 30 | ||||
-rw-r--r-- | src/keeper.h | 27 | ||||
-rw-r--r-- | src/lanes.c | 134 | ||||
-rw-r--r-- | src/lanes.h | 1 | ||||
-rw-r--r-- | src/macros_and_utils.h | 1 | ||||
-rw-r--r-- | src/platform.h | 24 | ||||
-rw-r--r-- | src/threading.h | 22 | ||||
-rw-r--r-- | src/tools.c | 153 | ||||
-rw-r--r-- | src/tools.h | 47 | ||||
-rw-r--r-- | src/universe.c | 14 | ||||
-rw-r--r-- | src/universe.h | 24 |
15 files changed, 311 insertions, 242 deletions
@@ -1,5 +1,15 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 126: Bge 29-Oct-18 | ||
4 | * Add deep user data cloning support | ||
5 | |||
6 | CHANGE 125: BGe 25-Oct-18 | ||
7 | * Fix Lanes build by reorganizing types around a bit | ||
8 | |||
9 | CHANGE 124: BGe 9-Jul-18 | ||
10 | * Fix a stack overflow when copying large tables with verbose_errors option enabled | ||
11 | * Support for integer formatting in verbose errors | ||
12 | |||
3 | CHANGE 123: BGe 2-Aug-17 | 13 | CHANGE 123: BGe 2-Aug-17 |
4 | * added support for user-provided __gc in deep userdata | 14 | * added support for user-provided __gc in deep userdata |
5 | * more complete deep userdata sample | 15 | * more complete deep userdata sample |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ce1bd3..647047c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -13,6 +13,9 @@ FIND_PROGRAM(LUA NAMES lua5.1 lua51 lua) | |||
13 | FIND_PROGRAM(LUAC NAMES luac5.1 luac51 luac) | 13 | FIND_PROGRAM(LUAC NAMES luac5.1 luac51 luac) |
14 | INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) | 14 | INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) |
15 | 15 | ||
16 | if(USE_PTHREAD) | ||
17 | ADD_DEFINITIONS(-DHAVE_WIN32_PTHREAD) | ||
18 | endif(USE_PTHREAD) | ||
16 | #2DO - patch threading.c to suppot cygwin. | 19 | #2DO - patch threading.c to suppot cygwin. |
17 | # The following values are just a guess. | 20 | # The following values are just a guess. |
18 | # WARNING: test segfault under Cygwin | 21 | # WARNING: test segfault under Cygwin |
@@ -32,11 +32,6 @@ THE SOFTWARE. | |||
32 | =============================================================================== | 32 | =============================================================================== |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include "compat.h" | ||
36 | #include "tools.h" | ||
37 | #include "universe.h" | ||
38 | #include "deep.h" | ||
39 | |||
40 | #include <stdio.h> | 35 | #include <stdio.h> |
41 | #include <string.h> | 36 | #include <string.h> |
42 | #include <ctype.h> | 37 | #include <ctype.h> |
@@ -45,6 +40,11 @@ THE SOFTWARE. | |||
45 | #include <malloc.h> | 40 | #include <malloc.h> |
46 | #endif | 41 | #endif |
47 | 42 | ||
43 | #include "compat.h" | ||
44 | #include "deep.h" | ||
45 | #include "tools.h" | ||
46 | #include "universe.h" | ||
47 | |||
48 | /*-- Metatable copying --*/ | 48 | /*-- Metatable copying --*/ |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -174,12 +174,12 @@ static void get_deep_lookup( lua_State* L) | |||
174 | * Return the registered ID function for 'index' (deep userdata proxy), | 174 | * Return the registered ID function for 'index' (deep userdata proxy), |
175 | * or NULL if 'index' is not a deep userdata proxy. | 175 | * or NULL if 'index' is not a deep userdata proxy. |
176 | */ | 176 | */ |
177 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupMode mode_) | 177 | static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mode_) |
178 | { | 178 | { |
179 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 179 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
180 | if( mode_ == eLM_FromKeeper) | 180 | if( mode_ == eLM_FromKeeper) |
181 | { | 181 | { |
182 | struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, index); | 182 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, index); |
183 | // we can (and must) cast and fetch the internally stored idfunc | 183 | // we can (and must) cast and fetch the internally stored idfunc |
184 | return (*proxy)->idfunc; | 184 | return (*proxy)->idfunc; |
185 | } | 185 | } |
@@ -208,7 +208,7 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupM | |||
208 | } | 208 | } |
209 | 209 | ||
210 | 210 | ||
211 | void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_) | 211 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) |
212 | { | 212 | { |
213 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup | 213 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup |
214 | lua_pushlightuserdata( L, prelude_->deep); | 214 | lua_pushlightuserdata( L, prelude_->deep); |
@@ -226,9 +226,9 @@ void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_) | |||
226 | */ | 226 | */ |
227 | static int deep_userdata_gc( lua_State* L) | 227 | static int deep_userdata_gc( lua_State* L) |
228 | { | 228 | { |
229 | struct DEEP_PRELUDE** proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, 1); | 229 | DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1); |
230 | struct DEEP_PRELUDE* p = *proxy; | 230 | DeepPrelude* p = *proxy; |
231 | struct s_Universe* U = universe_get( L); | 231 | Universe* U = universe_get( L); |
232 | int v; | 232 | int v; |
233 | 233 | ||
234 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 234 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
@@ -270,9 +270,9 @@ static int deep_userdata_gc( lua_State* L) | |||
270 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 270 | * used in this Lua state (metatable, registring it). Otherwise, increments the |
271 | * reference count. | 271 | * reference count. |
272 | */ | 272 | */ |
273 | char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRELUDE* prelude, enum eLookupMode mode_) | 273 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, LookupMode mode_) |
274 | { | 274 | { |
275 | struct DEEP_PRELUDE** proxy; | 275 | DeepPrelude** proxy; |
276 | 276 | ||
277 | // Check if a proxy already exists | 277 | // Check if a proxy already exists |
278 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC | 278 | push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v"); // DPC |
@@ -297,7 +297,7 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRE | |||
297 | STACK_GROW( L, 7); | 297 | STACK_GROW( L, 7); |
298 | STACK_CHECK( L); | 298 | STACK_CHECK( L); |
299 | 299 | ||
300 | proxy = lua_newuserdata( L, sizeof(struct DEEP_PRELUDE*)); // DPC proxy | 300 | proxy = lua_newuserdata( L, sizeof(DeepPrelude*)); // DPC proxy |
301 | ASSERT_L( proxy); | 301 | ASSERT_L( proxy); |
302 | *proxy = prelude; | 302 | *proxy = prelude; |
303 | 303 | ||
@@ -454,7 +454,7 @@ char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRE | |||
454 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | 454 | int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) |
455 | { | 455 | { |
456 | char const* errmsg; | 456 | char const* errmsg; |
457 | struct DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(struct DEEP_PRELUDE)); | 457 | DeepPrelude* prelude = DEEP_MALLOC( sizeof( DeepPrelude)); |
458 | if( prelude == NULL) | 458 | if( prelude == NULL) |
459 | { | 459 | { |
460 | return luaL_error( L, "couldn't not allocate deep prelude: out of memory"); | 460 | return luaL_error( L, "couldn't not allocate deep prelude: out of memory"); |
@@ -496,7 +496,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | |||
496 | */ | 496 | */ |
497 | void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | 497 | void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) |
498 | { | 498 | { |
499 | struct DEEP_PRELUDE** proxy; | 499 | DeepPrelude** proxy; |
500 | 500 | ||
501 | STACK_CHECK( L); | 501 | STACK_CHECK( L); |
502 | // ensure it is actually a deep userdata | 502 | // ensure it is actually a deep userdata |
@@ -505,7 +505,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
505 | return NULL; // no metatable, or wrong kind | 505 | return NULL; // no metatable, or wrong kind |
506 | } | 506 | } |
507 | 507 | ||
508 | proxy = (struct DEEP_PRELUDE**) lua_touserdata( L, index); | 508 | proxy = (DeepPrelude**) lua_touserdata( L, index); |
509 | STACK_END( L, 0); | 509 | STACK_END( L, 0); |
510 | 510 | ||
511 | return (*proxy)->deep; | 511 | return (*proxy)->deep; |
@@ -519,7 +519,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
519 | * the id function of the copied value, or NULL for non-deep userdata | 519 | * the id function of the copied value, or NULL for non-deep userdata |
520 | * (not copied) | 520 | * (not copied) |
521 | */ | 521 | */ |
522 | luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) | 522 | luaG_IdFunction copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_) |
523 | { | 523 | { |
524 | char const* errmsg; | 524 | char const* errmsg; |
525 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); | 525 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); |
@@ -528,7 +528,7 @@ luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int | |||
528 | return NULL; // not a deep userdata | 528 | return NULL; // not a deep userdata |
529 | } | 529 | } |
530 | 530 | ||
531 | errmsg = push_deep_proxy( U, L2, *(struct DEEP_PRELUDE**) lua_touserdata( L, index), mode_); | 531 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, index), mode_); |
532 | if( errmsg != NULL) | 532 | if( errmsg != NULL) |
533 | { | 533 | { |
534 | // raise the error in the proper state (not the keeper) | 534 | // raise the error in the proper state (not the keeper) |
@@ -6,14 +6,22 @@ | |||
6 | * said modules will have to link against lanes (it is not really possible to separate the 'deep userdata' implementation from the rest of Lanes) | 6 | * said modules will have to link against lanes (it is not really possible to separate the 'deep userdata' implementation from the rest of Lanes) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | |||
10 | #include "lua.h" | 9 | #include "lua.h" |
10 | #include "platform.h" | ||
11 | |||
12 | // forwards | ||
13 | struct s_Universe; | ||
14 | typedef struct s_Universe Universe; | ||
15 | enum eLookupMode; | ||
16 | typedef enum eLookupMode LookupMode; | ||
11 | 17 | ||
18 | #if !defined LANES_API // when deep is compiled standalone outside Lanes | ||
12 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 19 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
13 | #define LANES_API __declspec(dllexport) | 20 | #define LANES_API __declspec(dllexport) |
14 | #else | 21 | #else |
15 | #define LANES_API | 22 | #define LANES_API |
16 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 23 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
24 | #endif // LANES_API | ||
17 | 25 | ||
18 | enum eDeepOp | 26 | enum eDeepOp |
19 | { | 27 | { |
@@ -25,6 +33,21 @@ enum eDeepOp | |||
25 | 33 | ||
26 | typedef void* (*luaG_IdFunction)( lua_State* L, enum eDeepOp op_); | 34 | typedef void* (*luaG_IdFunction)( lua_State* L, enum eDeepOp op_); |
27 | 35 | ||
36 | // ################################################################################################ | ||
37 | |||
38 | // this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime | ||
39 | struct s_DeepPrelude | ||
40 | { | ||
41 | volatile int refcount; | ||
42 | void* deep; | ||
43 | // when stored in a keeper state, the full userdata doesn't have a metatable, so we need direct access to the idfunc | ||
44 | luaG_IdFunction idfunc; | ||
45 | }; | ||
46 | typedef struct s_DeepPrelude DeepPrelude; | ||
47 | |||
48 | char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, LookupMode mode_); | ||
49 | void free_deep_prelude( lua_State* L, DeepPrelude* prelude_); | ||
50 | |||
28 | extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc); | 51 | extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc); |
29 | extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index); | 52 | extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index); |
30 | extern LANES_API void luaG_pushdeepversion( lua_State* L); | 53 | extern LANES_API void luaG_pushdeepversion( lua_State* L); |
diff --git a/src/keeper.c b/src/keeper.c index dbf083f..907334f 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -42,12 +42,12 @@ | |||
42 | #include <stdio.h> | 42 | #include <stdio.h> |
43 | #include <stdlib.h> | 43 | #include <stdlib.h> |
44 | #include <ctype.h> | 44 | #include <ctype.h> |
45 | #include <assert.h> | ||
45 | 46 | ||
46 | #include "threading.h" | 47 | #include "keeper.h" |
47 | #include "compat.h" | 48 | #include "compat.h" |
48 | #include "tools.h" | 49 | #include "tools.h" |
49 | #include "universe.h" | 50 | #include "universe.h" |
50 | #include "keeper.h" | ||
51 | 51 | ||
52 | //################################################################################### | 52 | //################################################################################### |
53 | // Keeper implementation | 53 | // Keeper implementation |
@@ -184,9 +184,9 @@ static void push_table( lua_State* L, int idx_) | |||
184 | STACK_END( L, 1); | 184 | STACK_END( L, 1); |
185 | } | 185 | } |
186 | 186 | ||
187 | int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) | 187 | int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) |
188 | { | 188 | { |
189 | struct s_Keeper* const K = keeper_acquire( U->keepers, magic_); | 189 | Keeper* const K = keeper_acquire( U->keepers, magic_); |
190 | lua_State* const KL = K ? K->L : NULL; | 190 | lua_State* const KL = K ? K->L : NULL; |
191 | if( KL == NULL) return 0; | 191 | if( KL == NULL) return 0; |
192 | STACK_GROW( KL, 4); | 192 | STACK_GROW( KL, 4); |
@@ -576,7 +576,7 @@ int keepercall_count( lua_State* L) | |||
576 | */ | 576 | */ |
577 | 577 | ||
578 | // called as __gc for the keepers array userdata | 578 | // called as __gc for the keepers array userdata |
579 | void close_keepers( struct s_Universe* U, lua_State* L) | 579 | void close_keepers( Universe* U, lua_State* L) |
580 | { | 580 | { |
581 | if( U->keepers != NULL) | 581 | if( U->keepers != NULL) |
582 | { | 582 | { |
@@ -609,7 +609,7 @@ void close_keepers( struct s_Universe* U, lua_State* L) | |||
609 | { | 609 | { |
610 | void* allocUD; | 610 | void* allocUD; |
611 | lua_Alloc allocF = lua_getallocf( L, &allocUD); | 611 | lua_Alloc allocF = lua_getallocf( L, &allocUD); |
612 | allocF( allocUD, U->keepers, sizeof( struct s_Keepers) + (nbKeepers - 1) * sizeof(struct s_Keeper), 0); | 612 | allocF( allocUD, U->keepers, sizeof( Keepers) + (nbKeepers - 1) * sizeof( Keeper), 0); |
613 | U->keepers = NULL; | 613 | U->keepers = NULL; |
614 | } | 614 | } |
615 | } | 615 | } |
@@ -626,7 +626,7 @@ void close_keepers( struct s_Universe* U, lua_State* L) | |||
626 | * function never fails. | 626 | * function never fails. |
627 | * settings table is at position 1 on the stack | 627 | * settings table is at position 1 on the stack |
628 | */ | 628 | */ |
629 | void init_keepers( struct s_Universe* U, lua_State* L) | 629 | void init_keepers( Universe* U, lua_State* L) |
630 | { | 630 | { |
631 | int i; | 631 | int i; |
632 | int nb_keepers; | 632 | int nb_keepers; |
@@ -639,10 +639,10 @@ void init_keepers( struct s_Universe* U, lua_State* L) | |||
639 | lua_pop( L, 1); // | 639 | lua_pop( L, 1); // |
640 | assert( nb_keepers >= 1); | 640 | assert( nb_keepers >= 1); |
641 | 641 | ||
642 | // struct s_Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states | 642 | // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states |
643 | { | 643 | { |
644 | size_t const bytes = sizeof( struct s_Keepers) + (nb_keepers - 1) * sizeof(struct s_Keeper); | 644 | size_t const bytes = sizeof( Keepers) + (nb_keepers - 1) * sizeof( Keeper); |
645 | U->keepers = (struct s_Keepers*) allocF( allocUD, NULL, 0, bytes); | 645 | U->keepers = (Keepers*) allocF( allocUD, NULL, 0, bytes); |
646 | if( U->keepers == NULL) | 646 | if( U->keepers == NULL) |
647 | { | 647 | { |
648 | (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory"); | 648 | (void) luaL_error( L, "init_keepers() failed while creating keeper array; out of memory"); |
@@ -713,7 +713,7 @@ void init_keepers( struct s_Universe* U, lua_State* L) | |||
713 | STACK_END( L, 0); | 713 | STACK_END( L, 0); |
714 | } | 714 | } |
715 | 715 | ||
716 | struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_) | 716 | Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_) |
717 | { | 717 | { |
718 | int const nbKeepers = keepers_->nb_keepers; | 718 | int const nbKeepers = keepers_->nb_keepers; |
719 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) | 719 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) |
@@ -731,7 +731,7 @@ struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_) | |||
731 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer | 731 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer |
732 | */ | 732 | */ |
733 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | 733 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); |
734 | struct s_Keeper* K = &keepers_->keeper_array[i]; | 734 | Keeper* K = &keepers_->keeper_array[i]; |
735 | 735 | ||
736 | MUTEX_LOCK( &K->keeper_cs); | 736 | MUTEX_LOCK( &K->keeper_cs); |
737 | //++ K->count; | 737 | //++ K->count; |
@@ -739,13 +739,13 @@ struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_) | |||
739 | } | 739 | } |
740 | } | 740 | } |
741 | 741 | ||
742 | void keeper_release( struct s_Keeper* K) | 742 | void keeper_release( Keeper* K) |
743 | { | 743 | { |
744 | //-- K->count; | 744 | //-- K->count; |
745 | if( K) MUTEX_UNLOCK( &K->keeper_cs); | 745 | if( K) MUTEX_UNLOCK( &K->keeper_cs); |
746 | } | 746 | } |
747 | 747 | ||
748 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) | 748 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode mode_) |
749 | { | 749 | { |
750 | int i, n = lua_gettop( L); | 750 | int i, n = lua_gettop( L); |
751 | for( i = val_i_; i <= n; ++ i) | 751 | for( i = val_i_; i <= n; ++ i) |
@@ -778,7 +778,7 @@ void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mod | |||
778 | * | 778 | * |
779 | * Returns: number of return values (pushed to 'L') or -1 in case of error | 779 | * Returns: number of return values (pushed to 'L') or -1 in case of error |
780 | */ | 780 | */ |
781 | int keeper_call( struct s_Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index) | 781 | int keeper_call( Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index) |
782 | { | 782 | { |
783 | int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; | 783 | int const args = starting_index ? (lua_gettop( L) - starting_index + 1) : 0; |
784 | int const Ktos = lua_gettop( K); | 784 | int const Ktos = lua_gettop( K); |
diff --git a/src/keeper.h b/src/keeper.h index 7dbbc16..06cf3be 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
@@ -1,27 +1,38 @@ | |||
1 | #if !defined( __keeper_h__) | 1 | #if !defined( __keeper_h__) |
2 | #define __keeper_h__ 1 | 2 | #define __keeper_h__ 1 |
3 | 3 | ||
4 | #include "lua.h" | ||
5 | #include "threading.h" | ||
6 | |||
7 | // forwards | ||
8 | struct s_Universe; | ||
9 | typedef struct s_Universe Universe; | ||
10 | enum eLookupMode; | ||
11 | typedef enum eLookupMode LookupMode; | ||
12 | |||
4 | struct s_Keeper | 13 | struct s_Keeper |
5 | { | 14 | { |
6 | MUTEX_T keeper_cs; | 15 | MUTEX_T keeper_cs; |
7 | lua_State* L; | 16 | lua_State* L; |
8 | //int count; | 17 | //int count; |
9 | }; | 18 | }; |
19 | typedef struct s_Keeper Keeper; | ||
10 | 20 | ||
11 | struct s_Keepers | 21 | struct s_Keepers |
12 | { | 22 | { |
13 | int nb_keepers; | 23 | int nb_keepers; |
14 | struct s_Keeper keeper_array[1]; | 24 | Keeper keeper_array[1]; |
15 | }; | 25 | }; |
26 | typedef struct s_Keepers Keepers; | ||
16 | 27 | ||
17 | void init_keepers( struct s_Universe* U, lua_State* L); | 28 | void init_keepers( Universe* U, lua_State* L); |
18 | void close_keepers( struct s_Universe* U, lua_State* L); | 29 | void close_keepers( Universe* U, lua_State* L); |
19 | 30 | ||
20 | struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_); | 31 | Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_); |
21 | #define KEEPER_MAGIC_SHIFT 3 | 32 | #define KEEPER_MAGIC_SHIFT 3 |
22 | void keeper_release( struct s_Keeper* K); | 33 | void keeper_release( Keeper* K); |
23 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode const mode_); | 34 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_); |
24 | int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); | 35 | int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); |
25 | 36 | ||
26 | #define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) | 37 | #define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) |
27 | 38 | ||
@@ -38,6 +49,6 @@ int keepercall_get( lua_State* L); | |||
38 | int keepercall_set( lua_State* L); | 49 | int keepercall_set( lua_State* L); |
39 | int keepercall_count( lua_State* L); | 50 | int keepercall_count( lua_State* L); |
40 | 51 | ||
41 | int keeper_call( struct s_Universe* U, lua_State* K, keeper_api_t _func, lua_State* L, void* linda, uint_t starting_index); | 52 | int keeper_call( Universe* U, lua_State* K, keeper_api_t _func, lua_State* L, void* linda, uint_t starting_index); |
42 | 53 | ||
43 | #endif // __keeper_h__ \ No newline at end of file | 54 | #endif // __keeper_h__ \ No newline at end of file |
diff --git a/src/lanes.c b/src/lanes.c index 3268c8b..0a04d88 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -85,13 +85,14 @@ THE SOFTWARE. | |||
85 | #include <stdio.h> | 85 | #include <stdio.h> |
86 | #include <stdlib.h> | 86 | #include <stdlib.h> |
87 | #include <ctype.h> | 87 | #include <ctype.h> |
88 | #include <assert.h> | ||
88 | 89 | ||
90 | #include "lanes.h" | ||
89 | #include "threading.h" | 91 | #include "threading.h" |
90 | #include "compat.h" | 92 | #include "compat.h" |
91 | #include "tools.h" | 93 | #include "tools.h" |
92 | #include "universe.h" | 94 | #include "universe.h" |
93 | #include "keeper.h" | 95 | #include "keeper.h" |
94 | #include "lanes.h" | ||
95 | 96 | ||
96 | #if !(defined( PLATFORM_XBOX) || 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> |
@@ -122,7 +123,7 @@ enum e_cancel_request | |||
122 | // NOTE: values to be changed by either thread, during execution, without | 123 | // NOTE: values to be changed by either thread, during execution, without |
123 | // locking, are marked "volatile" | 124 | // locking, are marked "volatile" |
124 | // | 125 | // |
125 | struct s_lane | 126 | struct s_Lane |
126 | { | 127 | { |
127 | THREAD_T thread; | 128 | THREAD_T thread; |
128 | // | 129 | // |
@@ -132,7 +133,7 @@ struct s_lane | |||
132 | char const* debug_name; | 133 | char const* debug_name; |
133 | 134 | ||
134 | lua_State* L; | 135 | lua_State* L; |
135 | struct s_Universe* U; | 136 | Universe* U; |
136 | // | 137 | // |
137 | // M: prepares the state, and reads results | 138 | // M: prepares the state, and reads results |
138 | // S: while S is running, M must keep out of modifying the state | 139 | // S: while S is running, M must keep out of modifying the state |
@@ -172,29 +173,30 @@ struct s_lane | |||
172 | // M: sets to NORMAL, if issued a kill changes to KILLED | 173 | // M: sets to NORMAL, if issued a kill changes to KILLED |
173 | // S: not used | 174 | // S: not used |
174 | 175 | ||
175 | struct s_lane* volatile selfdestruct_next; | 176 | struct s_Lane* volatile selfdestruct_next; |
176 | // | 177 | // |
177 | // M: sets to non-NULL if facing lane handle '__gc' cycle but the lane | 178 | // M: sets to non-NULL if facing lane handle '__gc' cycle but the lane |
178 | // is still running | 179 | // is still running |
179 | // S: cleans up after itself if non-NULL at lane exit | 180 | // S: cleans up after itself if non-NULL at lane exit |
180 | 181 | ||
181 | #if HAVE_LANE_TRACKING | 182 | #if HAVE_LANE_TRACKING |
182 | struct s_lane* volatile tracking_next; | 183 | struct s_Lane* volatile tracking_next; |
183 | #endif // HAVE_LANE_TRACKING | 184 | #endif // HAVE_LANE_TRACKING |
184 | // | 185 | // |
185 | // For tracking only | 186 | // For tracking only |
186 | }; | 187 | }; |
188 | typedef struct s_Lane Lane; | ||
187 | 189 | ||
188 | // To allow free-running threads (longer lifespan than the handle's) | 190 | // To allow free-running threads (longer lifespan than the handle's) |
189 | // 'struct s_lane' are malloc/free'd and the handle only carries a pointer. | 191 | // 'Lane' are malloc/free'd and the handle only carries a pointer. |
190 | // This is not deep userdata since the handle's not portable among lanes. | 192 | // This is not deep userdata since the handle's not portable among lanes. |
191 | // | 193 | // |
192 | #define lua_toLane( L, i) (*((struct s_lane**) luaL_checkudata( L, i, "Lane"))) | 194 | #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) |
193 | 195 | ||
194 | #define CANCEL_TEST_KEY ((void*)get_lane_from_registry) // used as registry key | 196 | #define CANCEL_TEST_KEY ((void*)get_lane_from_registry) // used as registry key |
195 | static inline struct s_lane* get_lane_from_registry( lua_State* L) | 197 | static inline Lane* get_lane_from_registry( lua_State* L) |
196 | { | 198 | { |
197 | struct s_lane* s; | 199 | Lane* s; |
198 | STACK_GROW( L, 1); | 200 | STACK_GROW( L, 1); |
199 | STACK_CHECK( L); | 201 | STACK_CHECK( L); |
200 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); | 202 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); |
@@ -206,7 +208,7 @@ static inline struct s_lane* get_lane_from_registry( lua_State* L) | |||
206 | } | 208 | } |
207 | 209 | ||
208 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed | 210 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed |
209 | static void securize_debug_threadname( lua_State* L, struct s_lane* s) | 211 | static void securize_debug_threadname( lua_State* L, Lane* s) |
210 | { | 212 | { |
211 | STACK_CHECK( L); | 213 | STACK_CHECK( L); |
212 | STACK_GROW( L, 3); | 214 | STACK_GROW( L, 3); |
@@ -231,7 +233,7 @@ static void securize_debug_threadname( lua_State* L, struct s_lane* s) | |||
231 | */ | 233 | */ |
232 | static inline enum e_cancel_request cancel_test( lua_State* L) | 234 | static inline enum e_cancel_request cancel_test( lua_State* L) |
233 | { | 235 | { |
234 | struct s_lane* const s = get_lane_from_registry( L); | 236 | Lane* const s = get_lane_from_registry( L); |
235 | // 's' is NULL for the original main state (and no-one can cancel that) | 237 | // 's' is NULL for the original main state (and no-one can cancel that) |
236 | return s ? s->cancel_request : CANCEL_NONE; | 238 | return s ? s->cancel_request : CANCEL_NONE; |
237 | } | 239 | } |
@@ -320,15 +322,15 @@ static bool_t push_registry_table( lua_State* L, void* key, bool_t create) | |||
320 | 322 | ||
321 | #if HAVE_LANE_TRACKING | 323 | #if HAVE_LANE_TRACKING |
322 | 324 | ||
323 | // The chain is ended by '(struct s_lane*)(-1)', not NULL: | 325 | // The chain is ended by '(Lane*)(-1)', not NULL: |
324 | // 'tracking_first -> ... -> ... -> (-1)' | 326 | // 'tracking_first -> ... -> ... -> (-1)' |
325 | #define TRACKING_END ((struct s_lane *)(-1)) | 327 | #define TRACKING_END ((Lane *)(-1)) |
326 | 328 | ||
327 | /* | 329 | /* |
328 | * Add the lane to tracking chain; the ones still running at the end of the | 330 | * Add the lane to tracking chain; the ones still running at the end of the |
329 | * whole process will be cancelled. | 331 | * whole process will be cancelled. |
330 | */ | 332 | */ |
331 | static void tracking_add( struct s_lane* s) | 333 | static void tracking_add( Lane* s) |
332 | { | 334 | { |
333 | 335 | ||
334 | MUTEX_LOCK( &s->U->tracking_cs); | 336 | MUTEX_LOCK( &s->U->tracking_cs); |
@@ -344,7 +346,7 @@ static void tracking_add( struct s_lane* s) | |||
344 | /* | 346 | /* |
345 | * A free-running lane has ended; remove it from tracking chain | 347 | * A free-running lane has ended; remove it from tracking chain |
346 | */ | 348 | */ |
347 | static bool_t tracking_remove( struct s_lane* s) | 349 | static bool_t tracking_remove( Lane* s) |
348 | { | 350 | { |
349 | bool_t found = FALSE; | 351 | bool_t found = FALSE; |
350 | MUTEX_LOCK( &s->U->tracking_cs); | 352 | MUTEX_LOCK( &s->U->tracking_cs); |
@@ -355,7 +357,7 @@ static bool_t tracking_remove( struct s_lane* s) | |||
355 | // | 357 | // |
356 | if( s->tracking_next != NULL) | 358 | if( s->tracking_next != NULL) |
357 | { | 359 | { |
358 | struct s_lane** ref = (struct s_lane**) &s->U->tracking_first; | 360 | Lane** ref = (Lane**) &s->U->tracking_first; |
359 | 361 | ||
360 | while( *ref != TRACKING_END) | 362 | while( *ref != TRACKING_END) |
361 | { | 363 | { |
@@ -366,7 +368,7 @@ static bool_t tracking_remove( struct s_lane* s) | |||
366 | found = TRUE; | 368 | found = TRUE; |
367 | break; | 369 | break; |
368 | } | 370 | } |
369 | ref = (struct s_lane**) &((*ref)->tracking_next); | 371 | ref = (Lane**) &((*ref)->tracking_next); |
370 | } | 372 | } |
371 | assert( found); | 373 | assert( found); |
372 | } | 374 | } |
@@ -380,7 +382,7 @@ static bool_t tracking_remove( struct s_lane* s) | |||
380 | //--- | 382 | //--- |
381 | // low-level cleanup | 383 | // low-level cleanup |
382 | 384 | ||
383 | static void lane_cleanup( struct s_lane* s) | 385 | static void lane_cleanup( Lane* s) |
384 | { | 386 | { |
385 | // Clean up after a (finished) thread | 387 | // Clean up after a (finished) thread |
386 | // | 388 | // |
@@ -414,7 +416,7 @@ struct s_Linda | |||
414 | { | 416 | { |
415 | SIGNAL_T read_happened; | 417 | SIGNAL_T read_happened; |
416 | SIGNAL_T write_happened; | 418 | SIGNAL_T write_happened; |
417 | struct s_Universe* U; // the universe this linda belongs to | 419 | Universe* U; // the universe this linda belongs to |
418 | ptrdiff_t group; // a group to control keeper allocation between lindas | 420 | ptrdiff_t group; // a group to control keeper allocation between lindas |
419 | enum e_cancel_request simulate_cancel; | 421 | enum e_cancel_request simulate_cancel; |
420 | char name[1]; | 422 | char name[1]; |
@@ -504,8 +506,8 @@ LUAG_FUNC( linda_send) | |||
504 | 506 | ||
505 | { | 507 | { |
506 | bool_t try_again = TRUE; | 508 | bool_t try_again = TRUE; |
507 | struct s_lane* const s = get_lane_from_registry( L); | 509 | Lane* const s = get_lane_from_registry( L); |
508 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 510 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
509 | lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' | 511 | lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' |
510 | if( KL == NULL) return 0; | 512 | if( KL == NULL) return 0; |
511 | STACK_CHECK( KL); | 513 | STACK_CHECK( KL); |
@@ -666,8 +668,8 @@ LUAG_FUNC( linda_receive) | |||
666 | 668 | ||
667 | { | 669 | { |
668 | bool_t try_again = TRUE; | 670 | bool_t try_again = TRUE; |
669 | struct s_lane* const s = get_lane_from_registry( L); | 671 | Lane* const s = get_lane_from_registry( L); |
670 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 672 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
671 | if( K == NULL) return 0; | 673 | if( K == NULL) return 0; |
672 | for( ;;) | 674 | for( ;;) |
673 | { | 675 | { |
@@ -770,7 +772,7 @@ LUAG_FUNC( linda_set) | |||
770 | check_key_types( L, 2, 2); | 772 | check_key_types( L, 2, 2); |
771 | 773 | ||
772 | { | 774 | { |
773 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 775 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
774 | if( K == NULL) return 0; | 776 | if( K == NULL) return 0; |
775 | 777 | ||
776 | if( linda->simulate_cancel == CANCEL_NONE) | 778 | if( linda->simulate_cancel == CANCEL_NONE) |
@@ -826,7 +828,7 @@ LUAG_FUNC( linda_count) | |||
826 | check_key_types( L, 2, lua_gettop( L)); | 828 | check_key_types( L, 2, lua_gettop( L)); |
827 | 829 | ||
828 | { | 830 | { |
829 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 831 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
830 | if( K == NULL) return 0; | 832 | if( K == NULL) return 0; |
831 | pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2); | 833 | pushed = keeper_call( linda->U, K->L, KEEPER_API( count), L, linda, 2); |
832 | keeper_release( K); | 834 | keeper_release( K); |
@@ -855,7 +857,7 @@ LUAG_FUNC( linda_get) | |||
855 | // make sure the key is of a valid type (throws an error if not the case) | 857 | // make sure the key is of a valid type (throws an error if not the case) |
856 | check_key_types( L, 2, 2); | 858 | check_key_types( L, 2, 2); |
857 | { | 859 | { |
858 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 860 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
859 | if( K == NULL) return 0; | 861 | if( K == NULL) return 0; |
860 | 862 | ||
861 | if( linda->simulate_cancel == CANCEL_NONE) | 863 | if( linda->simulate_cancel == CANCEL_NONE) |
@@ -904,7 +906,7 @@ LUAG_FUNC( linda_limit) | |||
904 | check_key_types( L, 2, 2); | 906 | check_key_types( L, 2, 2); |
905 | 907 | ||
906 | { | 908 | { |
907 | struct s_Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 909 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
908 | if( K == NULL) return 0; | 910 | if( K == NULL) return 0; |
909 | 911 | ||
910 | if( linda->simulate_cancel == CANCEL_NONE) | 912 | if( linda->simulate_cancel == CANCEL_NONE) |
@@ -939,7 +941,7 @@ LUAG_FUNC( linda_cancel) | |||
939 | { | 941 | { |
940 | struct s_Linda* linda = lua_toLinda( L, 1); | 942 | struct s_Linda* linda = lua_toLinda( L, 1); |
941 | char const* who = luaL_optstring( L, 2, "both"); | 943 | char const* who = luaL_optstring( L, 2, "both"); |
942 | struct s_Keeper* K; | 944 | Keeper* K; |
943 | 945 | ||
944 | // make sure we got 3 arguments: the linda, a key and a limit | 946 | // make sure we got 3 arguments: the linda, a key and a limit |
945 | luaL_argcheck( L, lua_gettop( L) <= 2, 2, "wrong number of arguments"); | 947 | luaL_argcheck( L, lua_gettop( L) <= 2, 2, "wrong number of arguments"); |
@@ -1171,7 +1173,7 @@ static void* linda_id( lua_State* L, enum eDeepOp op_) | |||
1171 | 1173 | ||
1172 | case eDO_delete: | 1174 | case eDO_delete: |
1173 | { | 1175 | { |
1174 | struct s_Keeper* K; | 1176 | Keeper* K; |
1175 | struct s_Linda* linda = lua_touserdata( L, 1); | 1177 | struct s_Linda* linda = lua_touserdata( L, 1); |
1176 | ASSERT_L( linda); | 1178 | ASSERT_L( linda); |
1177 | 1179 | ||
@@ -1435,7 +1437,7 @@ typedef enum | |||
1435 | CR_Killed | 1437 | CR_Killed |
1436 | } cancel_result; | 1438 | } cancel_result; |
1437 | 1439 | ||
1438 | static cancel_result thread_cancel( lua_State* L, struct s_lane* s, double secs, bool_t force, double waitkill_timeout_) | 1440 | static cancel_result thread_cancel( lua_State* L, Lane* s, double secs, bool_t force, double waitkill_timeout_) |
1439 | { | 1441 | { |
1440 | cancel_result result; | 1442 | cancel_result result; |
1441 | 1443 | ||
@@ -1512,16 +1514,16 @@ static cancel_result thread_cancel( lua_State* L, struct s_lane* s, double secs, | |||
1512 | // | 1514 | // |
1513 | // Protects modifying the selfdestruct chain | 1515 | // Protects modifying the selfdestruct chain |
1514 | 1516 | ||
1515 | #define SELFDESTRUCT_END ((struct s_lane*)(-1)) | 1517 | #define SELFDESTRUCT_END ((Lane*)(-1)) |
1516 | // | 1518 | // |
1517 | // The chain is ended by '(struct s_lane*)(-1)', not NULL: | 1519 | // The chain is ended by '(Lane*)(-1)', not NULL: |
1518 | // 'selfdestruct_first -> ... -> ... -> (-1)' | 1520 | // 'selfdestruct_first -> ... -> ... -> (-1)' |
1519 | 1521 | ||
1520 | /* | 1522 | /* |
1521 | * Add the lane to selfdestruct chain; the ones still running at the end of the | 1523 | * Add the lane to selfdestruct chain; the ones still running at the end of the |
1522 | * whole process will be cancelled. | 1524 | * whole process will be cancelled. |
1523 | */ | 1525 | */ |
1524 | static void selfdestruct_add( struct s_lane* s) | 1526 | static void selfdestruct_add( Lane* s) |
1525 | { | 1527 | { |
1526 | MUTEX_LOCK( &s->U->selfdestruct_cs); | 1528 | MUTEX_LOCK( &s->U->selfdestruct_cs); |
1527 | assert( s->selfdestruct_next == NULL); | 1529 | assert( s->selfdestruct_next == NULL); |
@@ -1534,7 +1536,7 @@ static void selfdestruct_add( struct s_lane* s) | |||
1534 | /* | 1536 | /* |
1535 | * A free-running lane has ended; remove it from selfdestruct chain | 1537 | * A free-running lane has ended; remove it from selfdestruct chain |
1536 | */ | 1538 | */ |
1537 | static bool_t selfdestruct_remove( struct s_lane* s) | 1539 | static bool_t selfdestruct_remove( Lane* s) |
1538 | { | 1540 | { |
1539 | bool_t found = FALSE; | 1541 | bool_t found = FALSE; |
1540 | MUTEX_LOCK( &s->U->selfdestruct_cs); | 1542 | MUTEX_LOCK( &s->U->selfdestruct_cs); |
@@ -1545,7 +1547,7 @@ static bool_t selfdestruct_remove( struct s_lane* s) | |||
1545 | // | 1547 | // |
1546 | if( s->selfdestruct_next != NULL) | 1548 | if( s->selfdestruct_next != NULL) |
1547 | { | 1549 | { |
1548 | struct s_lane** ref = (struct s_lane**) &s->U->selfdestruct_first; | 1550 | Lane** ref = (Lane**) &s->U->selfdestruct_first; |
1549 | 1551 | ||
1550 | while( *ref != SELFDESTRUCT_END ) | 1552 | while( *ref != SELFDESTRUCT_END ) |
1551 | { | 1553 | { |
@@ -1558,7 +1560,7 @@ static bool_t selfdestruct_remove( struct s_lane* s) | |||
1558 | found = TRUE; | 1560 | found = TRUE; |
1559 | break; | 1561 | break; |
1560 | } | 1562 | } |
1561 | ref = (struct s_lane**) &((*ref)->selfdestruct_next); | 1563 | ref = (Lane**) &((*ref)->selfdestruct_next); |
1562 | } | 1564 | } |
1563 | assert( found); | 1565 | assert( found); |
1564 | } | 1566 | } |
@@ -1591,7 +1593,7 @@ void * protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize) | |||
1591 | */ | 1593 | */ |
1592 | static int selfdestruct_gc( lua_State* L) | 1594 | static int selfdestruct_gc( lua_State* L) |
1593 | { | 1595 | { |
1594 | struct s_Universe* U = (struct s_Universe*) lua_touserdata( L, 1); | 1596 | Universe* U = (Universe*) lua_touserdata( L, 1); |
1595 | 1597 | ||
1596 | while( U->selfdestruct_first != SELFDESTRUCT_END) // true at most once! | 1598 | while( U->selfdestruct_first != SELFDESTRUCT_END) // true at most once! |
1597 | { | 1599 | { |
@@ -1599,7 +1601,7 @@ static int selfdestruct_gc( lua_State* L) | |||
1599 | // | 1601 | // |
1600 | MUTEX_LOCK( &U->selfdestruct_cs); | 1602 | MUTEX_LOCK( &U->selfdestruct_cs); |
1601 | { | 1603 | { |
1602 | struct s_lane* s = U->selfdestruct_first; | 1604 | Lane* s = U->selfdestruct_first; |
1603 | while( s != SELFDESTRUCT_END) | 1605 | while( s != SELFDESTRUCT_END) |
1604 | { | 1606 | { |
1605 | // attempt a regular unforced hard cancel with a small timeout | 1607 | // attempt a regular unforced hard cancel with a small timeout |
@@ -1645,7 +1647,7 @@ static int selfdestruct_gc( lua_State* L) | |||
1645 | double t_now = 0.0; | 1647 | double t_now = 0.0; |
1646 | MUTEX_LOCK( &U->selfdestruct_cs); | 1648 | MUTEX_LOCK( &U->selfdestruct_cs); |
1647 | { | 1649 | { |
1648 | struct s_lane* s = U->selfdestruct_first; | 1650 | Lane* s = U->selfdestruct_first; |
1649 | while( s != SELFDESTRUCT_END) | 1651 | while( s != SELFDESTRUCT_END) |
1650 | { | 1652 | { |
1651 | if( s->cancel_request == CANCEL_HARD) | 1653 | if( s->cancel_request == CANCEL_HARD) |
@@ -1689,10 +1691,10 @@ static int selfdestruct_gc( lua_State* L) | |||
1689 | // these are not running, and the state can be closed | 1691 | // these are not running, and the state can be closed |
1690 | MUTEX_LOCK( &U->selfdestruct_cs); | 1692 | MUTEX_LOCK( &U->selfdestruct_cs); |
1691 | { | 1693 | { |
1692 | struct s_lane* s = U->selfdestruct_first; | 1694 | Lane* s = U->selfdestruct_first; |
1693 | while( s != SELFDESTRUCT_END) | 1695 | while( s != SELFDESTRUCT_END) |
1694 | { | 1696 | { |
1695 | struct s_lane* next_s = s->selfdestruct_next; | 1697 | Lane* next_s = s->selfdestruct_next; |
1696 | s->selfdestruct_next = NULL; // detach from selfdestruct chain | 1698 | s->selfdestruct_next = NULL; // detach from selfdestruct chain |
1697 | if( !THREAD_ISNULL( s->thread)) // can be NULL if previous 'soft' termination succeeded | 1699 | if( !THREAD_ISNULL( s->thread)) // can be NULL if previous 'soft' termination succeeded |
1698 | { | 1700 | { |
@@ -1719,7 +1721,7 @@ static int selfdestruct_gc( lua_State* L) | |||
1719 | lua_settop( L, 0); | 1721 | lua_settop( L, 0); |
1720 | // no need to mutex-protect this as all threads in the universe are gone at that point | 1722 | // no need to mutex-protect this as all threads in the universe are gone at that point |
1721 | -- U->timer_deep->refcount; // should be 0 now | 1723 | -- U->timer_deep->refcount; // should be 0 now |
1722 | free_deep_prelude( L, (struct DEEP_PRELUDE*) U->timer_deep); | 1724 | free_deep_prelude( L, (DeepPrelude*) U->timer_deep); |
1723 | U->timer_deep = NULL; | 1725 | U->timer_deep = NULL; |
1724 | 1726 | ||
1725 | close_keepers( U, L); | 1727 | close_keepers( U, L); |
@@ -1959,7 +1961,7 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | |||
1959 | LUAG_FUNC( set_debug_threadname) | 1961 | LUAG_FUNC( set_debug_threadname) |
1960 | { | 1962 | { |
1961 | // C s_lane structure is a light userdata upvalue | 1963 | // C s_lane structure is a light userdata upvalue |
1962 | struct s_lane* s = lua_touserdata( L, lua_upvalueindex( 1)); | 1964 | Lane* s = lua_touserdata( L, lua_upvalueindex( 1)); |
1963 | luaL_checktype( L, -1, LUA_TSTRING); // "name" | 1965 | luaL_checktype( L, -1, LUA_TSTRING); // "name" |
1964 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... | 1966 | // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... |
1965 | lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud | 1967 | lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud |
@@ -1975,7 +1977,7 @@ LUAG_FUNC( set_debug_threadname) | |||
1975 | 1977 | ||
1976 | LUAG_FUNC( get_debug_threadname) | 1978 | LUAG_FUNC( get_debug_threadname) |
1977 | { | 1979 | { |
1978 | struct s_lane* const s = lua_toLane( L, 1); | 1980 | Lane* const s = lua_toLane( L, 1); |
1979 | luaL_argcheck( L, lua_gettop( L) == 1, 2, "too many arguments"); | 1981 | luaL_argcheck( L, lua_gettop( L) == 1, 2, "too many arguments"); |
1980 | lua_pushstring( L, s->debug_name); | 1982 | lua_pushstring( L, s->debug_name); |
1981 | return 1; | 1983 | return 1; |
@@ -2031,7 +2033,7 @@ static char const* get_errcode_name( int _code) | |||
2031 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR // implies THREADAPI == THREADAPI_PTHREAD | 2033 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR // implies THREADAPI == THREADAPI_PTHREAD |
2032 | static void thread_cleanup_handler( void* opaque) | 2034 | static void thread_cleanup_handler( void* opaque) |
2033 | { | 2035 | { |
2034 | struct s_lane* s= (struct s_lane*) opaque; | 2036 | Lane* s= (Lane*) opaque; |
2035 | MUTEX_LOCK( &s->done_lock); | 2037 | MUTEX_LOCK( &s->done_lock); |
2036 | s->status = CANCELLED; | 2038 | s->status = CANCELLED; |
2037 | SIGNAL_ONE( &s->done_signal); // wake up master (while 's->done_lock' is on) | 2039 | SIGNAL_ONE( &s->done_signal); // wake up master (while 's->done_lock' is on) |
@@ -2041,12 +2043,12 @@ static void thread_cleanup_handler( void* opaque) | |||
2041 | 2043 | ||
2042 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) | 2044 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) |
2043 | { | 2045 | { |
2044 | struct s_lane* s = (struct s_lane*) vs; | 2046 | Lane* s = (Lane*) vs; |
2045 | int rc, rc2; | 2047 | int rc, rc2; |
2046 | lua_State* L = s->L; | 2048 | lua_State* L = s->L; |
2047 | // Called with the lane function and arguments on the stack | 2049 | // Called with the lane function and arguments on the stack |
2048 | int const nargs = lua_gettop( L) - 1; | 2050 | int const nargs = lua_gettop( L) - 1; |
2049 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 2051 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
2050 | THREAD_MAKE_ASYNCH_CANCELLABLE(); | 2052 | THREAD_MAKE_ASYNCH_CANCELLABLE(); |
2051 | THREAD_CLEANUP_PUSH( thread_cleanup_handler, s); | 2053 | THREAD_CLEANUP_PUSH( thread_cleanup_handler, s); |
2052 | s->status = RUNNING; // PENDING -> RUNNING | 2054 | s->status = RUNNING; // PENDING -> RUNNING |
@@ -2144,7 +2146,7 @@ LUAG_FUNC( require) | |||
2144 | { | 2146 | { |
2145 | char const* name = lua_tostring( L, 1); | 2147 | char const* name = lua_tostring( L, 1); |
2146 | int const nargs = lua_gettop( L); | 2148 | int const nargs = lua_gettop( L); |
2147 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 2149 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
2148 | STACK_CHECK( L); | 2150 | STACK_CHECK( L); |
2149 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); | 2151 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); |
2150 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 2152 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -2170,7 +2172,7 @@ LUAG_FUNC( register) | |||
2170 | // ignore extra parameters, just in case | 2172 | // ignore extra parameters, just in case |
2171 | lua_settop( L, 2); | 2173 | lua_settop( L, 2); |
2172 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); | 2174 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); |
2173 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 2175 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
2174 | STACK_CHECK( L); // "name" mod_table | 2176 | STACK_CHECK( L); // "name" mod_table |
2175 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); | 2177 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); |
2176 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 2178 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -2200,8 +2202,8 @@ LUAG_FUNC( thread_gc); | |||
2200 | LUAG_FUNC( lane_new) | 2202 | LUAG_FUNC( lane_new) |
2201 | { | 2203 | { |
2202 | lua_State* L2; | 2204 | lua_State* L2; |
2203 | struct s_lane* s; | 2205 | Lane* s; |
2204 | struct s_lane** ud; | 2206 | Lane** ud; |
2205 | 2207 | ||
2206 | char const* libs_str = lua_tostring( L, 2); | 2208 | char const* libs_str = lua_tostring( L, 2); |
2207 | uint_t cancelstep_idx = luaG_optunsigned( L, 3, 0); | 2209 | uint_t cancelstep_idx = luaG_optunsigned( L, 3, 0); |
@@ -2213,7 +2215,7 @@ LUAG_FUNC( lane_new) | |||
2213 | 2215 | ||
2214 | #define FIXED_ARGS 8 | 2216 | #define FIXED_ARGS 8 |
2215 | int const nargs = lua_gettop(L) - FIXED_ARGS; | 2217 | int const nargs = lua_gettop(L) - FIXED_ARGS; |
2216 | struct s_Universe* U = universe_get( L); | 2218 | Universe* U = universe_get( L); |
2217 | ASSERT_L( nargs >= 0); | 2219 | ASSERT_L( nargs >= 0); |
2218 | 2220 | ||
2219 | // public Lanes API accepts a generic range -3/+3 | 2221 | // public Lanes API accepts a generic range -3/+3 |
@@ -2386,8 +2388,8 @@ LUAG_FUNC( lane_new) | |||
2386 | 2388 | ||
2387 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 2389 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
2388 | // | 2390 | // |
2389 | ud = lua_newuserdata( L, sizeof( struct s_lane*)); // func libs cancelstep priority globals package required gc_cb lane | 2391 | ud = lua_newuserdata( L, sizeof( Lane*)); // func libs cancelstep priority globals package required gc_cb lane |
2390 | s = *ud = (struct s_lane*) malloc( sizeof( struct s_lane)); | 2392 | s = *ud = (Lane*) malloc( sizeof( Lane)); |
2391 | if( s == NULL) | 2393 | if( s == NULL) |
2392 | { | 2394 | { |
2393 | return luaL_error( L, "could not create lane: out of memory"); | 2395 | return luaL_error( L, "could not create lane: out of memory"); |
@@ -2470,7 +2472,7 @@ LUAG_FUNC( lane_new) | |||
2470 | LUAG_FUNC( thread_gc) | 2472 | LUAG_FUNC( thread_gc) |
2471 | { | 2473 | { |
2472 | bool_t have_gc_cb = FALSE; | 2474 | bool_t have_gc_cb = FALSE; |
2473 | struct s_lane* s = lua_toLane( L, 1); // ud | 2475 | Lane* s = lua_toLane( L, 1); // ud |
2474 | 2476 | ||
2475 | // if there a gc callback? | 2477 | // if there a gc callback? |
2476 | lua_getuservalue( L, 1); // ud uservalue | 2478 | lua_getuservalue( L, 1); // ud uservalue |
@@ -2547,7 +2549,7 @@ LUAG_FUNC( thread_gc) | |||
2547 | // lane_h:cancel( [timeout] [, force [, forcekill_timeout]]) | 2549 | // lane_h:cancel( [timeout] [, force [, forcekill_timeout]]) |
2548 | LUAG_FUNC( thread_cancel) | 2550 | LUAG_FUNC( thread_cancel) |
2549 | { | 2551 | { |
2550 | struct s_lane* s = lua_toLane( L, 1); | 2552 | Lane* s = lua_toLane( L, 1); |
2551 | double secs = 0.0; | 2553 | double secs = 0.0; |
2552 | int force_i = 2; | 2554 | int force_i = 2; |
2553 | int forcekill_timeout_i = 3; | 2555 | int forcekill_timeout_i = 3; |
@@ -2604,7 +2606,7 @@ LUAG_FUNC( thread_cancel) | |||
2604 | // / "error" finished at an error, error value is there | 2606 | // / "error" finished at an error, error value is there |
2605 | // / "cancelled" execution cancelled by M (state gone) | 2607 | // / "cancelled" execution cancelled by M (state gone) |
2606 | // | 2608 | // |
2607 | static char const * thread_status_string( struct s_lane* s) | 2609 | static char const * thread_status_string( Lane* s) |
2608 | { | 2610 | { |
2609 | enum e_status st = s->status; // read just once (volatile) | 2611 | enum e_status st = s->status; // read just once (volatile) |
2610 | char const* str = | 2612 | char const* str = |
@@ -2618,7 +2620,7 @@ static char const * thread_status_string( struct s_lane* s) | |||
2618 | return str; | 2620 | return str; |
2619 | } | 2621 | } |
2620 | 2622 | ||
2621 | static int push_thread_status( lua_State* L, struct s_lane* s) | 2623 | static int push_thread_status( lua_State* L, Lane* s) |
2622 | { | 2624 | { |
2623 | char const* const str = thread_status_string( s); | 2625 | char const* const str = thread_status_string( s); |
2624 | ASSERT_L( str); | 2626 | ASSERT_L( str); |
@@ -2638,7 +2640,7 @@ static int push_thread_status( lua_State* L, struct s_lane* s) | |||
2638 | // | 2640 | // |
2639 | LUAG_FUNC( thread_join) | 2641 | LUAG_FUNC( thread_join) |
2640 | { | 2642 | { |
2641 | struct s_lane* const s = lua_toLane( L, 1); | 2643 | Lane* const s = lua_toLane( L, 1); |
2642 | double wait_secs = luaL_optnumber( L, 2, -1.0); | 2644 | double wait_secs = luaL_optnumber( L, 2, -1.0); |
2643 | lua_State* L2 = s->L; | 2645 | lua_State* L2 = s->L; |
2644 | int ret; | 2646 | int ret; |
@@ -2661,7 +2663,7 @@ LUAG_FUNC( thread_join) | |||
2661 | } | 2663 | } |
2662 | else | 2664 | else |
2663 | { | 2665 | { |
2664 | struct s_Universe* U = universe_get( L); | 2666 | Universe* U = universe_get( L); |
2665 | // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed | 2667 | // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed |
2666 | // so store it in the userdata uservalue at a key that can't possibly collide | 2668 | // so store it in the userdata uservalue at a key that can't possibly collide |
2667 | securize_debug_threadname( L, s); | 2669 | securize_debug_threadname( L, s); |
@@ -2722,7 +2724,7 @@ LUAG_FUNC( thread_index) | |||
2722 | int const UD = 1; | 2724 | int const UD = 1; |
2723 | int const KEY = 2; | 2725 | int const KEY = 2; |
2724 | int const USR = 3; | 2726 | int const USR = 3; |
2725 | struct s_lane* const s = lua_toLane( L, UD); | 2727 | Lane* const s = lua_toLane( L, UD); |
2726 | ASSERT_L( lua_gettop( L) == 2); | 2728 | ASSERT_L( lua_gettop( L) == 2); |
2727 | 2729 | ||
2728 | STACK_GROW( L, 8); // up to 8 positions are needed in case of error propagation | 2730 | STACK_GROW( L, 8); // up to 8 positions are needed in case of error propagation |
@@ -2873,14 +2875,14 @@ LUAG_FUNC( thread_index) | |||
2873 | LUAG_FUNC( threads) | 2875 | LUAG_FUNC( threads) |
2874 | { | 2876 | { |
2875 | int const top = lua_gettop( L); | 2877 | int const top = lua_gettop( L); |
2876 | struct s_Universe* U = universe_get( L); | 2878 | Universe* U = universe_get( L); |
2877 | 2879 | ||
2878 | // List _all_ still running threads | 2880 | // List _all_ still running threads |
2879 | // | 2881 | // |
2880 | MUTEX_LOCK( &U->tracking_cs); | 2882 | MUTEX_LOCK( &U->tracking_cs); |
2881 | if( U->tracking_first && U->tracking_first != TRACKING_END) | 2883 | if( U->tracking_first && U->tracking_first != TRACKING_END) |
2882 | { | 2884 | { |
2883 | struct s_lane* s = U->tracking_first; | 2885 | Lane* s = U->tracking_first; |
2884 | lua_newtable( L); // {} | 2886 | lua_newtable( L); // {} |
2885 | while( s != TRACKING_END) | 2887 | while( s != TRACKING_END) |
2886 | { | 2888 | { |
@@ -3025,7 +3027,7 @@ static volatile long s_initCount = 0; | |||
3025 | // param 1: settings table | 3027 | // param 1: settings table |
3026 | LUAG_FUNC( configure) | 3028 | LUAG_FUNC( configure) |
3027 | { | 3029 | { |
3028 | struct s_Universe* U = universe_get( L); | 3030 | Universe* U = universe_get( L); |
3029 | bool_t const from_master_state = (U == NULL); | 3031 | bool_t const from_master_state = (U == NULL); |
3030 | char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); | 3032 | char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); |
3031 | _ASSERT_L( L, lua_type( L, 1) == LUA_TTABLE); | 3033 | _ASSERT_L( L, lua_type( L, 1) == LUA_TTABLE); |
@@ -3129,7 +3131,7 @@ LUAG_FUNC( configure) | |||
3129 | STACK_MID( L, 1); | 3131 | STACK_MID( L, 1); |
3130 | 3132 | ||
3131 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer | 3133 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer |
3132 | U->timer_deep = *(struct DEEP_PRELUDE**) lua_touserdata( L, -1); | 3134 | U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); |
3133 | ASSERT_L( U->timer_deep && (U->timer_deep->refcount == 1) && U->timer_deep->deep && U->timer_deep->idfunc == linda_id); | 3135 | ASSERT_L( U->timer_deep && (U->timer_deep->refcount == 1) && U->timer_deep->deep && U->timer_deep->idfunc == linda_id); |
3134 | // increment refcount that this linda remains alive as long as the universe is. | 3136 | // increment refcount that this linda remains alive as long as the universe is. |
3135 | ++ U->timer_deep->refcount; | 3137 | ++ U->timer_deep->refcount; |
@@ -3159,7 +3161,7 @@ LUAG_FUNC( configure) | |||
3159 | 3161 | ||
3160 | { | 3162 | { |
3161 | char const* errmsg; | 3163 | char const* errmsg; |
3162 | errmsg = push_deep_proxy( U, L, (struct DEEP_PRELUDE*) U->timer_deep, eLM_LaneBody);// settings M timer_deep | 3164 | errmsg = push_deep_proxy( U, L, (DeepPrelude*) U->timer_deep, eLM_LaneBody);// settings M timer_deep |
3163 | if( errmsg != NULL) | 3165 | if( errmsg != NULL) |
3164 | { | 3166 | { |
3165 | return luaL_error( L, errmsg); | 3167 | return luaL_error( L, errmsg); |
diff --git a/src/lanes.h b/src/lanes.h index d07750a..23fa711 100644 --- a/src/lanes.h +++ b/src/lanes.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __lanes_h__ 1 | 2 | #define __lanes_h__ 1 |
3 | 3 | ||
4 | #include "lua.h" | 4 | #include "lua.h" |
5 | #include "platform.h" | ||
5 | 6 | ||
6 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 7 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
7 | #define LANES_API __declspec(dllexport) | 8 | #define LANES_API __declspec(dllexport) |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index d584c2b..2a619b3 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #define MACROS_AND_UTILS_H | 5 | #define MACROS_AND_UTILS_H |
6 | 6 | ||
7 | #include "lua.h" | 7 | #include "lua.h" |
8 | #include "lualib.h" | ||
8 | 9 | ||
9 | // M$ compiler doesn't support 'inline' keyword in C files... | 10 | // M$ compiler doesn't support 'inline' keyword in C files... |
10 | #if defined( _MSC_VER) | 11 | #if defined( _MSC_VER) |
diff --git a/src/platform.h b/src/platform.h new file mode 100644 index 0000000..da5264e --- /dev/null +++ b/src/platform.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef __LANES_PLATFORM_H__ | ||
2 | #define __LANES_PLATFORM_H__ 1 | ||
3 | |||
4 | #ifdef _WIN32_WCE | ||
5 | #define PLATFORM_POCKETPC | ||
6 | #elif defined(_XBOX) | ||
7 | #define PLATFORM_XBOX | ||
8 | #elif (defined _WIN32) | ||
9 | #define PLATFORM_WIN32 | ||
10 | #elif (defined __linux__) | ||
11 | #define PLATFORM_LINUX | ||
12 | #elif (defined __APPLE__) && (defined __MACH__) | ||
13 | #define PLATFORM_OSX | ||
14 | #elif (defined __NetBSD__) || (defined __FreeBSD__) || (defined BSD) | ||
15 | #define PLATFORM_BSD | ||
16 | #elif (defined __QNX__) | ||
17 | #define PLATFORM_QNX | ||
18 | #elif (defined __CYGWIN__) | ||
19 | #define PLATFORM_CYGWIN | ||
20 | #else | ||
21 | #error "Unknown platform!" | ||
22 | #endif | ||
23 | |||
24 | #endif // __LANES_PLATFORM_H__ | ||
diff --git a/src/threading.h b/src/threading.h index bfa9ab8..4114dba 100644 --- a/src/threading.h +++ b/src/threading.h | |||
@@ -4,30 +4,12 @@ | |||
4 | #ifndef __threading_h__ | 4 | #ifndef __threading_h__ |
5 | #define __threading_h__ 1 | 5 | #define __threading_h__ 1 |
6 | 6 | ||
7 | /* Platform detection | 7 | /* |
8 | * win32-pthread: | 8 | * win32-pthread: |
9 | * define HAVE_WIN32_PTHREAD and PTW32_INCLUDE_WINDOWS_H in your project configuration when building for win32-pthread. | 9 | * define HAVE_WIN32_PTHREAD and PTW32_INCLUDE_WINDOWS_H in your project configuration when building for win32-pthread. |
10 | * link against pthreadVC2.lib, and of course have pthreadVC2.dll somewhere in your path. | 10 | * link against pthreadVC2.lib, and of course have pthreadVC2.dll somewhere in your path. |
11 | */ | 11 | */ |
12 | #ifdef _WIN32_WCE | 12 | #include "platform.h" |
13 | #define PLATFORM_POCKETPC | ||
14 | #elif defined(_XBOX) | ||
15 | #define PLATFORM_XBOX | ||
16 | #elif (defined _WIN32) | ||
17 | #define PLATFORM_WIN32 | ||
18 | #elif (defined __linux__) | ||
19 | #define PLATFORM_LINUX | ||
20 | #elif (defined __APPLE__) && (defined __MACH__) | ||
21 | #define PLATFORM_OSX | ||
22 | #elif (defined __NetBSD__) || (defined __FreeBSD__) || (defined BSD) | ||
23 | #define PLATFORM_BSD | ||
24 | #elif (defined __QNX__) | ||
25 | #define PLATFORM_QNX | ||
26 | #elif (defined __CYGWIN__) | ||
27 | #define PLATFORM_CYGWIN | ||
28 | #else | ||
29 | #error "Unknown platform!" | ||
30 | #endif | ||
31 | 13 | ||
32 | typedef int bool_t; | 14 | typedef int bool_t; |
33 | #ifndef FALSE | 15 | #ifndef FALSE |
diff --git a/src/tools.c b/src/tools.c index 13e714d..051e3cc 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -31,22 +31,22 @@ THE SOFTWARE. | |||
31 | =============================================================================== | 31 | =============================================================================== |
32 | */ | 32 | */ |
33 | 33 | ||
34 | #include "compat.h" | ||
35 | #include "universe.h" | ||
36 | #include "tools.h" | ||
37 | #include "keeper.h" | ||
38 | #include "lanes.h" | ||
39 | |||
40 | #include <stdio.h> | 34 | #include <stdio.h> |
41 | #include <string.h> | 35 | #include <string.h> |
42 | #include <ctype.h> | 36 | #include <ctype.h> |
43 | #include <stdlib.h> | 37 | #include <stdlib.h> |
44 | #if !defined(__APPLE__) | 38 | #if !defined(__APPLE__) |
45 | #include <malloc.h> | 39 | #include <malloc.h> |
46 | #endif | 40 | #endif // __APPLE__ |
41 | |||
42 | #include "tools.h" | ||
43 | #include "compat.h" | ||
44 | #include "universe.h" | ||
45 | #include "keeper.h" | ||
46 | #include "lanes.h" | ||
47 | 47 | ||
48 | // functions implemented in deep.c | 48 | // functions implemented in deep.c |
49 | extern luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_); | 49 | extern luaG_IdFunction copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_); |
50 | extern void push_registry_subtable( lua_State* L, void* key_); | 50 | extern void push_registry_subtable( lua_State* L, void* key_); |
51 | 51 | ||
52 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; | 52 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; |
@@ -105,7 +105,7 @@ void luaG_dump( lua_State* L) | |||
105 | fprintf( stderr, "\n"); | 105 | fprintf( stderr, "\n"); |
106 | } | 106 | } |
107 | 107 | ||
108 | void initialize_on_state_create( struct s_Universe* U, lua_State* L) | 108 | void initialize_on_state_create( Universe* U, lua_State* L) |
109 | { | 109 | { |
110 | STACK_CHECK( L); | 110 | STACK_CHECK( L); |
111 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 111 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil |
@@ -139,7 +139,7 @@ void initialize_on_state_create( struct s_Universe* U, lua_State* L) | |||
139 | // ################################################################################################ | 139 | // ################################################################################################ |
140 | 140 | ||
141 | // just like lua_xmove, args are (from, to) | 141 | // just like lua_xmove, args are (from, to) |
142 | void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2) | 142 | void luaG_copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) |
143 | { | 143 | { |
144 | STACK_GROW( L, 1); | 144 | STACK_GROW( L, 1); |
145 | // copy settings from from source to destination registry | 145 | // copy settings from from source to destination registry |
@@ -198,7 +198,7 @@ static const luaL_Reg libs[] = | |||
198 | { NULL, NULL } | 198 | { NULL, NULL } |
199 | }; | 199 | }; |
200 | 200 | ||
201 | static void open1lib( struct s_Universe* U, lua_State* L, char const* name_, size_t len_, lua_State* from_) | 201 | static void open1lib( Universe* U, lua_State* L, char const* name_, size_t len_, lua_State* from_) |
202 | { | 202 | { |
203 | int i; | 203 | int i; |
204 | for( i = 0; libs[i].name; ++ i) | 204 | for( i = 0; libs[i].name; ++ i) |
@@ -341,7 +341,7 @@ static void update_lookup_entry( lua_State* L, int _ctx_base, int _depth) | |||
341 | size_t prevNameLength, newNameLength; | 341 | size_t prevNameLength, newNameLength; |
342 | char const* prevName; | 342 | char const* prevName; |
343 | DEBUGSPEW_CODE( char const *newName); | 343 | DEBUGSPEW_CODE( char const *newName); |
344 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 344 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
345 | 345 | ||
346 | STACK_CHECK( L); | 346 | STACK_CHECK( L); |
347 | // first, raise an error if the function is already known | 347 | // first, raise an error if the function is already known |
@@ -412,7 +412,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
412 | int const cache = _ctx_base + 2; | 412 | int const cache = _ctx_base + 2; |
413 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 413 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
414 | int const breadth_first_cache = lua_gettop( L) + 1; | 414 | int const breadth_first_cache = lua_gettop( L) + 1; |
415 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 415 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
416 | 416 | ||
417 | STACK_GROW( L, 6); | 417 | STACK_GROW( L, 6); |
418 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 418 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
@@ -530,7 +530,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
530 | int const ctx_base = lua_gettop( L) + 1; | 530 | int const ctx_base = lua_gettop( L) + 1; |
531 | int const in_base = lua_absindex( L, _i); | 531 | int const in_base = lua_absindex( L, _i); |
532 | int start_depth = 0; | 532 | int start_depth = 0; |
533 | DEBUGSPEW_CODE( struct s_Universe* U = universe_get( L)); | 533 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
534 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); | 534 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); |
535 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 535 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
536 | STACK_GROW( L, 3); | 536 | STACK_GROW( L, 3); |
@@ -585,7 +585,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
585 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 585 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
586 | } | 586 | } |
587 | 587 | ||
588 | void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_) | 588 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_) |
589 | { | 589 | { |
590 | if( U->on_state_create_func != NULL) | 590 | if( U->on_state_create_func != NULL) |
591 | { | 591 | { |
@@ -630,7 +630,7 @@ void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, | |||
630 | * *NOT* called for keeper states! | 630 | * *NOT* called for keeper states! |
631 | * | 631 | * |
632 | */ | 632 | */ |
633 | lua_State* luaG_newstate( struct s_Universe* U, lua_State* from_, char const* libs_) | 633 | lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) |
634 | { | 634 | { |
635 | // re-use alloc function from the originating state | 635 | // re-use alloc function from the originating state |
636 | #if PROPAGATE_ALLOCF | 636 | #if PROPAGATE_ALLOCF |
@@ -761,7 +761,7 @@ lua_State* luaG_newstate( struct s_Universe* U, lua_State* from_, char const* li | |||
761 | /* | 761 | /* |
762 | * Get a unique ID for metatable at [i]. | 762 | * Get a unique ID for metatable at [i]. |
763 | */ | 763 | */ |
764 | static uint_t get_mt_id( struct s_Universe* U, lua_State* L, int i) | 764 | static uint_t get_mt_id( Universe* U, lua_State* L, int i) |
765 | { | 765 | { |
766 | uint_t id; | 766 | uint_t id; |
767 | 767 | ||
@@ -828,9 +828,9 @@ static int table_lookup_sentinel( lua_State* L) | |||
828 | /* | 828 | /* |
829 | * retrieve the name of a function/table in the lookup database | 829 | * retrieve the name of a function/table in the lookup database |
830 | */ | 830 | */ |
831 | static char const* find_lookup_name( lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_, size_t* len_) | 831 | static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, char const* upName_, size_t* len_) |
832 | { | 832 | { |
833 | DEBUGSPEW_CODE( struct s_Universe* const U = universe_get( L)); | 833 | DEBUGSPEW_CODE( Universe* const U = universe_get( L)); |
834 | char const* fqn; | 834 | char const* fqn; |
835 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... | 835 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... |
836 | STACK_CHECK( L); | 836 | STACK_CHECK( L); |
@@ -899,7 +899,7 @@ static char const* find_lookup_name( lua_State* L, uint_t i, enum eLookupMode mo | |||
899 | /* | 899 | /* |
900 | * Push a looked-up table, or nothing if we found nothing | 900 | * Push a looked-up table, or nothing if we found nothing |
901 | */ | 901 | */ |
902 | static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 902 | static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) |
903 | { | 903 | { |
904 | // get the name of the table we want to send | 904 | // get the name of the table we want to send |
905 | size_t len; | 905 | size_t len; |
@@ -1195,7 +1195,7 @@ int luaG_nameof( lua_State* L) | |||
1195 | /* | 1195 | /* |
1196 | * Push a looked-up native/LuaJIT function. | 1196 | * Push a looked-up native/LuaJIT function. |
1197 | */ | 1197 | */ |
1198 | static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1198 | static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) |
1199 | { | 1199 | { |
1200 | // get the name of the function we want to send | 1200 | // get the name of the function we want to send |
1201 | size_t len; | 1201 | size_t len; |
@@ -1276,9 +1276,9 @@ enum e_vt | |||
1276 | VT_KEY, | 1276 | VT_KEY, |
1277 | VT_METATABLE | 1277 | VT_METATABLE |
1278 | }; | 1278 | }; |
1279 | static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, enum eLookupMode mode_, char const* upName_); | 1279 | static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, LookupMode mode_, char const* upName_); |
1280 | 1280 | ||
1281 | static void inter_copy_func( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1281 | static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) |
1282 | { | 1282 | { |
1283 | int n, needToPush; | 1283 | int n, needToPush; |
1284 | luaL_Buffer b; | 1284 | luaL_Buffer b; |
@@ -1427,7 +1427,7 @@ static void inter_copy_func( struct s_Universe* U, lua_State* L2, uint_t L2_cach | |||
1427 | * | 1427 | * |
1428 | * Always pushes a function to 'L2'. | 1428 | * Always pushes a function to 'L2'. |
1429 | */ | 1429 | */ |
1430 | static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1430 | static void push_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) |
1431 | { | 1431 | { |
1432 | FuncSubType funcSubType; | 1432 | FuncSubType funcSubType; |
1433 | /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions | 1433 | /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions |
@@ -1480,7 +1480,7 @@ static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cac | |||
1480 | } | 1480 | } |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | static bool_t push_cached_metatable( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1483 | static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) |
1484 | { | 1484 | { |
1485 | if( lua_getmetatable( L, i)) // ... mt | 1485 | if( lua_getmetatable( L, i)) // ... mt |
1486 | { | 1486 | { |
@@ -1526,6 +1526,58 @@ static bool_t push_cached_metatable( struct s_Universe* U, lua_State* L2, uint_t | |||
1526 | return FALSE; | 1526 | return FALSE; |
1527 | } | 1527 | } |
1528 | 1528 | ||
1529 | static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, enum e_vt vt, LookupMode mode_, char const* upName_) | ||
1530 | { | ||
1531 | uint_t val_i = lua_gettop( L); | ||
1532 | uint_t key_i = val_i - 1; | ||
1533 | |||
1534 | // Only basic key types are copied over; others ignored | ||
1535 | if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) | ||
1536 | { | ||
1537 | char* valPath = (char*) upName_; | ||
1538 | if( U->verboseErrors) | ||
1539 | { | ||
1540 | // for debug purposes, let's try to build a useful name | ||
1541 | if( lua_type( L, key_i) == LUA_TSTRING) | ||
1542 | { | ||
1543 | char const* key = lua_tostring( L, key_i); | ||
1544 | size_t const keyRawLen = lua_rawlen( L, key_i); | ||
1545 | size_t const bufLen = strlen( upName_) + keyRawLen + 2; | ||
1546 | valPath = (char*) alloca( bufLen); | ||
1547 | sprintf( valPath, "%s.%*s", upName_, (int) keyRawLen, key); | ||
1548 | key = NULL; | ||
1549 | } | ||
1550 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | ||
1551 | else if( lua_isinteger( L, key_i)) | ||
1552 | { | ||
1553 | lua_Integer key = lua_tointeger( L, key_i); | ||
1554 | valPath = (char*) alloca( strlen( upName_) + 32 + 3); | ||
1555 | sprintf( valPath, "%s[" LUA_INTEGER_FMT "]", upName_, key); | ||
1556 | } | ||
1557 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 | ||
1558 | else if( lua_type( L, key_i) == LUA_TNUMBER) | ||
1559 | { | ||
1560 | lua_Number key = lua_tonumber( L, key_i); | ||
1561 | valPath = (char*) alloca( strlen( upName_) + 32 + 3); | ||
1562 | sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key); | ||
1563 | } | ||
1564 | } | ||
1565 | /* | ||
1566 | * Contents of metatables are copied with cache checking; | ||
1567 | * important to detect loops. | ||
1568 | */ | ||
1569 | if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) | ||
1570 | { | ||
1571 | ASSERT_L( lua_istable( L2, -3)); | ||
1572 | lua_rawset( L2, -3); // add to table (pops key & val) | ||
1573 | } | ||
1574 | else | ||
1575 | { | ||
1576 | luaL_error( L, "Unable to copy over type '%s' (in %s)", luaL_typename( L, val_i), (vt == VT_NORMAL) ? "table" : "metatable"); | ||
1577 | } | ||
1578 | } | ||
1579 | } | ||
1580 | |||
1529 | /* | 1581 | /* |
1530 | * Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove | 1582 | * Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove |
1531 | * the original value. | 1583 | * the original value. |
@@ -1536,7 +1588,7 @@ static bool_t push_cached_metatable( struct s_Universe* U, lua_State* L2, uint_t | |||
1536 | * | 1588 | * |
1537 | * Returns TRUE if value was pushed, FALSE if its type is non-supported. | 1589 | * Returns TRUE if value was pushed, FALSE if its type is non-supported. |
1538 | */ | 1590 | */ |
1539 | static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_) | 1591 | static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) |
1540 | { | 1592 | { |
1541 | bool_t ret = TRUE; | 1593 | bool_t ret = TRUE; |
1542 | bool_t ignore = FALSE; | 1594 | bool_t ignore = FALSE; |
@@ -1575,7 +1627,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca | |||
1575 | break; | 1627 | break; |
1576 | } | 1628 | } |
1577 | else | 1629 | else |
1578 | #endif | 1630 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
1579 | { | 1631 | { |
1580 | lua_Number v = lua_tonumber( L, i); | 1632 | lua_Number v = lua_tonumber( L, i); |
1581 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_NUMBER_FMT "\n" INDENT_END, v)); | 1633 | DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_NUMBER_FMT "\n" INDENT_END, v)); |
@@ -1735,41 +1787,8 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca | |||
1735 | lua_pushnil( L); // start iteration | 1787 | lua_pushnil( L); // start iteration |
1736 | while( lua_next( L, i)) | 1788 | while( lua_next( L, i)) |
1737 | { | 1789 | { |
1738 | uint_t val_i = lua_gettop( L); | 1790 | // need a function to prevent overflowing the stack with verboseErrors-induced alloca() |
1739 | uint_t key_i = val_i - 1; | 1791 | inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); |
1740 | |||
1741 | // Only basic key types are copied over; others ignored | ||
1742 | if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) | ||
1743 | { | ||
1744 | char* valPath = (char*) upName_; | ||
1745 | if( U->verboseErrors) | ||
1746 | { | ||
1747 | // for debug purposes, let's try to build a useful name | ||
1748 | if( lua_type( L, key_i) == LUA_TSTRING) | ||
1749 | { | ||
1750 | valPath = (char*) alloca( strlen( upName_) + strlen( lua_tostring( L, key_i)) + 2); | ||
1751 | sprintf( valPath, "%s.%s", upName_, lua_tostring( L, key_i)); | ||
1752 | } | ||
1753 | else if( lua_type( L, key_i) == LUA_TNUMBER) | ||
1754 | { | ||
1755 | valPath = (char*) alloca( strlen( upName_) + 32 + 3); | ||
1756 | sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, lua_tonumber( L, key_i)); | ||
1757 | } | ||
1758 | } | ||
1759 | /* | ||
1760 | * Contents of metatables are copied with cache checking; | ||
1761 | * important to detect loops. | ||
1762 | */ | ||
1763 | if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) | ||
1764 | { | ||
1765 | ASSERT_L( lua_istable( L2, -3)); | ||
1766 | lua_rawset( L2, -3); // add to table (pops key & val) | ||
1767 | } | ||
1768 | else | ||
1769 | { | ||
1770 | (void) luaL_error( L, "Unable to copy over type '%s' (in %s)", luaL_typename( L, val_i), (vt == VT_NORMAL) ? "table" : "metatable"); | ||
1771 | } | ||
1772 | } | ||
1773 | lua_pop( L, 1); // pop value (next round) | 1792 | lua_pop( L, 1); // pop value (next round) |
1774 | } | 1793 | } |
1775 | STACK_MID( L, 0); | 1794 | STACK_MID( L, 0); |
@@ -1805,7 +1824,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca | |||
1805 | * | 1824 | * |
1806 | * Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. | 1825 | * Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. |
1807 | */ | 1826 | */ |
1808 | int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) | 1827 | int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_) |
1809 | { | 1828 | { |
1810 | uint_t top_L = lua_gettop( L); | 1829 | uint_t top_L = lua_gettop( L); |
1811 | uint_t top_L2 = lua_gettop( L2); | 1830 | uint_t top_L2 = lua_gettop( L2); |
@@ -1863,14 +1882,14 @@ int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n | |||
1863 | } | 1882 | } |
1864 | 1883 | ||
1865 | 1884 | ||
1866 | int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) | 1885 | int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_) |
1867 | { | 1886 | { |
1868 | int ret = luaG_inter_copy( U, L, L2, n, mode_); | 1887 | int ret = luaG_inter_copy( U, L, L2, n, mode_); |
1869 | lua_pop( L, (int) n); | 1888 | lua_pop( L, (int) n); |
1870 | return ret; | 1889 | return ret; |
1871 | } | 1890 | } |
1872 | 1891 | ||
1873 | int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_) | 1892 | int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_) |
1874 | { | 1893 | { |
1875 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 1894 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); |
1876 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1895 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -1937,7 +1956,7 @@ int luaG_new_require( lua_State* L) | |||
1937 | { | 1956 | { |
1938 | int rc, i; | 1957 | int rc, i; |
1939 | int args = lua_gettop( L); | 1958 | int args = lua_gettop( L); |
1940 | struct s_Universe* U = universe_get( L); | 1959 | Universe* U = universe_get( L); |
1941 | //char const* modname = luaL_checkstring( L, 1); | 1960 | //char const* modname = luaL_checkstring( L, 1); |
1942 | 1961 | ||
1943 | STACK_GROW( L, args + 1); | 1962 | STACK_GROW( L, args + 1); |
@@ -1970,7 +1989,7 @@ int luaG_new_require( lua_State* L) | |||
1970 | /* | 1989 | /* |
1971 | * Serialize calls to 'require', if it exists | 1990 | * Serialize calls to 'require', if it exists |
1972 | */ | 1991 | */ |
1973 | void serialize_require( struct s_Universe* U, lua_State* L) | 1992 | void serialize_require( Universe* U, lua_State* L) |
1974 | { | 1993 | { |
1975 | STACK_GROW( L, 1); | 1994 | STACK_GROW( L, 1); |
1976 | STACK_CHECK( L); | 1995 | STACK_CHECK( L); |
diff --git a/src/tools.h b/src/tools.h index 9155747..df429f7 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -1,28 +1,15 @@ | |||
1 | /* | 1 | #ifndef __LANES_TOOLS_H__ |
2 | * TOOLS.H | 2 | #define __LANES_TOOLS_H__ |
3 | */ | ||
4 | #ifndef TOOLS_H | ||
5 | #define TOOLS_H | ||
6 | 3 | ||
7 | #include "lauxlib.h" | 4 | //#include "lauxlib.h" |
8 | #include "threading.h" | 5 | #include "threading.h" |
9 | #include "deep.h" | 6 | #include "deep.h" |
10 | // MUTEX_T | ||
11 | |||
12 | #include <assert.h> | ||
13 | 7 | ||
14 | #include "macros_and_utils.h" | 8 | #include "macros_and_utils.h" |
15 | 9 | ||
16 | // ################################################################################################ | 10 | // forwards |
17 | 11 | struct s_Universe; | |
18 | // this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime | 12 | typedef struct s_Universe Universe; |
19 | struct DEEP_PRELUDE | ||
20 | { | ||
21 | volatile int refcount; | ||
22 | void* deep; | ||
23 | // when stored in a keeper state, the full userdata doesn't have a metatable, so we need direct access to the idfunc | ||
24 | luaG_IdFunction idfunc; | ||
25 | }; | ||
26 | 13 | ||
27 | // ################################################################################################ | 14 | // ################################################################################################ |
28 | 15 | ||
@@ -33,8 +20,8 @@ struct DEEP_PRELUDE | |||
33 | 20 | ||
34 | void luaG_dump( lua_State* L ); | 21 | void luaG_dump( lua_State* L ); |
35 | 22 | ||
36 | lua_State* luaG_newstate( struct s_Universe* U, lua_State* _from, char const* libs); | 23 | lua_State* luaG_newstate( Universe* U, lua_State* _from, char const* libs); |
37 | void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2); | 24 | void luaG_copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2); |
38 | 25 | ||
39 | // ################################################################################################ | 26 | // ################################################################################################ |
40 | 27 | ||
@@ -44,26 +31,24 @@ enum eLookupMode | |||
44 | eLM_ToKeeper, // send a function from a lane to a keeper state | 31 | eLM_ToKeeper, // send a function from a lane to a keeper state |
45 | eLM_FromKeeper // send a function from a keeper state to a lane | 32 | eLM_FromKeeper // send a function from a keeper state to a lane |
46 | }; | 33 | }; |
34 | typedef enum eLookupMode LookupMode; | ||
47 | 35 | ||
48 | char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRELUDE* prelude, enum eLookupMode mode_); | 36 | int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_); |
49 | void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_); | ||
50 | |||
51 | int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_); | ||
52 | 37 | ||
53 | int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_); | 38 | int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_); |
54 | int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_); | 39 | int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_); |
55 | 40 | ||
56 | int luaG_nameof( lua_State* L); | 41 | int luaG_nameof( lua_State* L); |
57 | int luaG_new_require( lua_State* L); | 42 | int luaG_new_require( lua_State* L); |
58 | 43 | ||
59 | void populate_func_lookup_table( lua_State* L, int _i, char const* _name); | 44 | void populate_func_lookup_table( lua_State* L, int _i, char const* _name); |
60 | void serialize_require( struct s_Universe* U, lua_State *L); | 45 | void serialize_require( Universe* U, lua_State *L); |
61 | void initialize_on_state_create( struct s_Universe* U, lua_State* L); | 46 | void initialize_on_state_create( Universe* U, lua_State* L); |
62 | void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_); | 47 | void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_); |
63 | 48 | ||
64 | // ################################################################################################ | 49 | // ################################################################################################ |
65 | 50 | ||
66 | extern char const* const CONFIG_REGKEY; | 51 | extern char const* const CONFIG_REGKEY; |
67 | extern char const* const LOOKUP_REGKEY; | 52 | extern char const* const LOOKUP_REGKEY; |
68 | 53 | ||
69 | #endif // TOOLS_H | 54 | #endif // __LANES_TOOLS_H__ |
diff --git a/src/universe.c b/src/universe.c index ba78396..8bcdcfe 100644 --- a/src/universe.c +++ b/src/universe.c | |||
@@ -28,19 +28,19 @@ THE SOFTWARE. | |||
28 | =============================================================================== | 28 | =============================================================================== |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include "universe.h" | ||
31 | #include "compat.h" | 32 | #include "compat.h" |
32 | #include "macros_and_utils.h" | 33 | #include "macros_and_utils.h" |
33 | #include "universe.h" | ||
34 | 34 | ||
35 | // crc64/we of string "UNIVERSE_REGKEY" generated at https://www.nitrxgen.net/hashgen/ | 35 | // crc64/we of string "UNIVERSE_REGKEY" generated at https://www.nitrxgen.net/hashgen/ |
36 | static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f); | 36 | static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f); |
37 | 37 | ||
38 | // ################################################################################################ | 38 | // ################################################################################################ |
39 | 39 | ||
40 | struct s_Universe* universe_create( lua_State* L) | 40 | Universe* universe_create( lua_State* L) |
41 | { | 41 | { |
42 | struct s_Universe* U = (struct s_Universe*) lua_newuserdata( L, sizeof(struct s_Universe)); // universe | 42 | Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe |
43 | memset( U, 0, sizeof( struct s_Universe)); | 43 | memset( U, 0, sizeof( Universe)); |
44 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY | 44 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY |
45 | lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe | 45 | lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe |
46 | lua_rawset( L, LUA_REGISTRYINDEX); // universe | 46 | lua_rawset( L, LUA_REGISTRYINDEX); // universe |
@@ -49,7 +49,7 @@ struct s_Universe* universe_create( lua_State* L) | |||
49 | 49 | ||
50 | // ################################################################################################ | 50 | // ################################################################################################ |
51 | 51 | ||
52 | void universe_store( lua_State* L, struct s_Universe* U) | 52 | void universe_store( lua_State* L, Universe* U) |
53 | { | 53 | { |
54 | STACK_CHECK( L); | 54 | STACK_CHECK( L); |
55 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | 55 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); |
@@ -60,9 +60,9 @@ void universe_store( lua_State* L, struct s_Universe* U) | |||
60 | 60 | ||
61 | // ################################################################################################ | 61 | // ################################################################################################ |
62 | 62 | ||
63 | struct s_Universe* universe_get( lua_State* L) | 63 | Universe* universe_get( lua_State* L) |
64 | { | 64 | { |
65 | struct s_Universe* universe; | 65 | Universe* universe; |
66 | STACK_GROW( L, 2); | 66 | STACK_GROW( L, 2); |
67 | STACK_CHECK( L); | 67 | STACK_CHECK( L); |
68 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | 68 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); |
diff --git a/src/universe.h b/src/universe.h index 0ca5bf7..a75cead 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -6,7 +6,14 @@ | |||
6 | 6 | ||
7 | #include "lua.h" | 7 | #include "lua.h" |
8 | #include "threading.h" | 8 | #include "threading.h" |
9 | // MUTEX_T | 9 | |
10 | // forwards | ||
11 | struct s_DeepPrelude; | ||
12 | typedef struct s_DeepPrelude DeepPrelude; | ||
13 | struct s_Keepers; | ||
14 | typedef struct s_Keepers Keepers; | ||
15 | struct s_Lane; | ||
16 | typedef struct s_Lane Lane; | ||
10 | 17 | ||
11 | // ################################################################################################ | 18 | // ################################################################################################ |
12 | 19 | ||
@@ -27,15 +34,15 @@ struct s_Universe | |||
27 | 34 | ||
28 | lua_CFunction on_state_create_func; | 35 | lua_CFunction on_state_create_func; |
29 | 36 | ||
30 | struct s_Keepers* keepers; | 37 | Keepers* keepers; |
31 | 38 | ||
32 | // Initialized by 'init_once_LOCKED()': the deep userdata Linda object | 39 | // Initialized by 'init_once_LOCKED()': the deep userdata Linda object |
33 | // used for timers (each lane will get a proxy to this) | 40 | // used for timers (each lane will get a proxy to this) |
34 | volatile struct DEEP_PRELUDE* timer_deep; // = NULL | 41 | volatile DeepPrelude* timer_deep; // = NULL |
35 | 42 | ||
36 | #if HAVE_LANE_TRACKING | 43 | #if HAVE_LANE_TRACKING |
37 | MUTEX_T tracking_cs; | 44 | MUTEX_T tracking_cs; |
38 | struct s_lane* volatile tracking_first; // will change to TRACKING_END if we want to activate tracking | 45 | Lane* volatile tracking_first; // will change to TRACKING_END if we want to activate tracking |
39 | #endif // HAVE_LANE_TRACKING | 46 | #endif // HAVE_LANE_TRACKING |
40 | 47 | ||
41 | MUTEX_T selfdestruct_cs; | 48 | MUTEX_T selfdestruct_cs; |
@@ -53,14 +60,15 @@ struct s_Universe | |||
53 | int debugspew_indent_depth; | 60 | int debugspew_indent_depth; |
54 | #endif // USE_DEBUG_SPEW | 61 | #endif // USE_DEBUG_SPEW |
55 | 62 | ||
56 | struct s_lane* volatile selfdestruct_first; | 63 | Lane* volatile selfdestruct_first; |
57 | // After a lane has removed itself from the chain, it still performs some processing. | 64 | // After a lane has removed itself from the chain, it still performs some processing. |
58 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads | 65 | // The terminal desinit sequence should wait for all such processing to terminate before force-killing threads |
59 | int volatile selfdestructing_count; | 66 | int volatile selfdestructing_count; |
60 | }; | 67 | }; |
68 | typedef struct s_Universe Universe; | ||
61 | 69 | ||
62 | struct s_Universe* universe_get( lua_State* L); | 70 | Universe* universe_get( lua_State* L); |
63 | struct s_Universe* universe_create( lua_State* L); | 71 | Universe* universe_create( lua_State* L); |
64 | void universe_store( lua_State* L, struct s_Universe* U); | 72 | void universe_store( lua_State* L, Universe* U); |
65 | 73 | ||
66 | #endif // UNIVERSE_H | 74 | #endif // UNIVERSE_H |