aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES10
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/deep.c38
-rw-r--r--src/deep.h25
-rw-r--r--src/keeper.c30
-rw-r--r--src/keeper.h27
-rw-r--r--src/lanes.c134
-rw-r--r--src/lanes.h1
-rw-r--r--src/macros_and_utils.h1
-rw-r--r--src/platform.h24
-rw-r--r--src/threading.h22
-rw-r--r--src/tools.c153
-rw-r--r--src/tools.h47
-rw-r--r--src/universe.c14
-rw-r--r--src/universe.h24
15 files changed, 311 insertions, 242 deletions
diff --git a/CHANGES b/CHANGES
index 92fb7f9..ab7399c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,15 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 126: Bge 29-Oct-18
4 * Add deep user data cloning support
5
6CHANGE 125: BGe 25-Oct-18
7 * Fix Lanes build by reorganizing types around a bit
8
9CHANGE 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
3CHANGE 123: BGe 2-Aug-17 13CHANGE 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)
13FIND_PROGRAM(LUAC NAMES luac5.1 luac51 luac) 13FIND_PROGRAM(LUAC NAMES luac5.1 luac51 luac)
14INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR}) 14INCLUDE_DIRECTORIES(${LUA_INCLUDE_DIR})
15 15
16if(USE_PTHREAD)
17ADD_DEFINITIONS(-DHAVE_WIN32_PTHREAD)
18endif(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
diff --git a/src/deep.c b/src/deep.c
index 737ebe9..82350f4 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -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*/
177static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupMode mode_) 177static 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
211void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_) 211void 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 */
227static int deep_userdata_gc( lua_State* L) 227static 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 */
273char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRELUDE* prelude, enum eLookupMode mode_) 273char 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
454int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) 454int 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*/
497void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) 497void* 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 */
522luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) 522luaG_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)
diff --git a/src/deep.h b/src/deep.h
index 8e999d6..aeeb828 100644
--- a/src/deep.h
+++ b/src/deep.h
@@ -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
13struct s_Universe;
14typedef struct s_Universe Universe;
15enum eLookupMode;
16typedef 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
18enum eDeepOp 26enum eDeepOp
19{ 27{
@@ -25,6 +33,21 @@ enum eDeepOp
25 33
26typedef void* (*luaG_IdFunction)( lua_State* L, enum eDeepOp op_); 34typedef 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
39struct 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};
46typedef struct s_DeepPrelude DeepPrelude;
47
48char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, LookupMode mode_);
49void free_deep_prelude( lua_State* L, DeepPrelude* prelude_);
50
28extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc); 51extern LANES_API int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc);
29extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index); 52extern LANES_API void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index);
30extern LANES_API void luaG_pushdeepversion( lua_State* L); 53extern 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
187int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) 187int 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
579void close_keepers( struct s_Universe* U, lua_State* L) 579void 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 */
629void init_keepers( struct s_Universe* U, lua_State* L) 629void 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
716struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_) 716Keeper* 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
742void keeper_release( struct s_Keeper* K) 742void 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
748void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode mode_) 748void 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*/
781int keeper_call( struct s_Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, void* linda, uint_t starting_index) 781int 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
8struct s_Universe;
9typedef struct s_Universe Universe;
10enum eLookupMode;
11typedef enum eLookupMode LookupMode;
12
4struct s_Keeper 13struct 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};
19typedef struct s_Keeper Keeper;
10 20
11struct s_Keepers 21struct 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};
26typedef struct s_Keepers Keepers;
16 27
17void init_keepers( struct s_Universe* U, lua_State* L); 28void init_keepers( Universe* U, lua_State* L);
18void close_keepers( struct s_Universe* U, lua_State* L); 29void close_keepers( Universe* U, lua_State* L);
19 30
20struct s_Keeper* keeper_acquire( struct s_Keepers* keepers_, ptrdiff_t magic_); 31Keeper* keeper_acquire( Keepers* keepers_, ptrdiff_t magic_);
21#define KEEPER_MAGIC_SHIFT 3 32#define KEEPER_MAGIC_SHIFT 3
22void keeper_release( struct s_Keeper* K); 33void keeper_release( Keeper* K);
23void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, enum eLookupMode const mode_); 34void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_);
24int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); 35int 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);
38int keepercall_set( lua_State* L); 49int keepercall_set( lua_State* L);
39int keepercall_count( lua_State* L); 50int keepercall_count( lua_State* L);
40 51
41int keeper_call( struct s_Universe* U, lua_State* K, keeper_api_t _func, lua_State* L, void* linda, uint_t starting_index); 52int 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//
125struct s_lane 126struct 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};
188typedef 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
195static inline struct s_lane* get_lane_from_registry( lua_State* L) 197static 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
209static void securize_debug_threadname( lua_State* L, struct s_lane* s) 211static 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*/
232static inline enum e_cancel_request cancel_test( lua_State* L) 234static 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 */
331static void tracking_add( struct s_lane* s) 333static 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 */
347static bool_t tracking_remove( struct s_lane* s) 349static 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
383static void lane_cleanup( struct s_lane* s) 385static 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
1438static cancel_result thread_cancel( lua_State* L, struct s_lane* s, double secs, bool_t force, double waitkill_timeout_) 1440static 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 */
1524static void selfdestruct_add( struct s_lane* s) 1526static 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 */
1537static bool_t selfdestruct_remove( struct s_lane* s) 1539static 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*/
1592static int selfdestruct_gc( lua_State* L) 1594static 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_)
1959LUAG_FUNC( set_debug_threadname) 1961LUAG_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
1976LUAG_FUNC( get_debug_threadname) 1978LUAG_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
2032static void thread_cleanup_handler( void* opaque) 2034static 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
2042static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) 2044static 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);
2200LUAG_FUNC( lane_new) 2202LUAG_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)
2470LUAG_FUNC( thread_gc) 2472LUAG_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]])
2548LUAG_FUNC( thread_cancel) 2550LUAG_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//
2607static char const * thread_status_string( struct s_lane* s) 2609static 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
2621static int push_thread_status( lua_State* L, struct s_lane* s) 2623static 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//
2639LUAG_FUNC( thread_join) 2641LUAG_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)
2873LUAG_FUNC( threads) 2875LUAG_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
3026LUAG_FUNC( configure) 3028LUAG_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
32typedef int bool_t; 14typedef 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
49extern luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_); 49extern luaG_IdFunction copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_);
50extern void push_registry_subtable( lua_State* L, void* key_); 50extern void push_registry_subtable( lua_State* L, void* key_);
51 51
52char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; 52char 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
108void initialize_on_state_create( struct s_Universe* U, lua_State* L) 108void 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)
142void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2) 142void 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
201static void open1lib( struct s_Universe* U, lua_State* L, char const* name_, size_t len_, lua_State* from_) 201static 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
588void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_) 588void 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 */
633lua_State* luaG_newstate( struct s_Universe* U, lua_State* from_, char const* libs_) 633lua_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*/
764static uint_t get_mt_id( struct s_Universe* U, lua_State* L, int i) 764static 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 */
831static char const* find_lookup_name( lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_, size_t* len_) 831static 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 */
902static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) 902static 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 */
1198static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) 1198static 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};
1279static 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_); 1279static 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
1281static 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_) 1281static 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 */
1430static 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_) 1430static 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
1483static 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_) 1483static 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
1529static 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*/
1539static 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_) 1591static 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*/
1808int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) 1827int 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
1866int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) 1885int 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
1873int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_) 1892int 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*/
1973void serialize_require( struct s_Universe* U, lua_State* L) 1992void 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 11struct s_Universe;
18// this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime 12typedef struct s_Universe Universe;
19struct 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
34void luaG_dump( lua_State* L ); 21void luaG_dump( lua_State* L );
35 22
36lua_State* luaG_newstate( struct s_Universe* U, lua_State* _from, char const* libs); 23lua_State* luaG_newstate( Universe* U, lua_State* _from, char const* libs);
37void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2); 24void 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};
34typedef enum eLookupMode LookupMode;
47 35
48char const* push_deep_proxy( struct s_Universe* U, lua_State* L, struct DEEP_PRELUDE* prelude, enum eLookupMode mode_); 36int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_);
49void free_deep_prelude( lua_State* L, struct DEEP_PRELUDE* prelude_);
50
51int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_);
52 37
53int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_); 38int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_);
54int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_); 39int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_);
55 40
56int luaG_nameof( lua_State* L); 41int luaG_nameof( lua_State* L);
57int luaG_new_require( lua_State* L); 42int luaG_new_require( lua_State* L);
58 43
59void populate_func_lookup_table( lua_State* L, int _i, char const* _name); 44void populate_func_lookup_table( lua_State* L, int _i, char const* _name);
60void serialize_require( struct s_Universe* U, lua_State *L); 45void serialize_require( Universe* U, lua_State *L);
61void initialize_on_state_create( struct s_Universe* U, lua_State* L); 46void initialize_on_state_create( Universe* U, lua_State* L);
62void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_); 47void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMode mode_);
63 48
64// ################################################################################################ 49// ################################################################################################
65 50
66extern char const* const CONFIG_REGKEY; 51extern char const* const CONFIG_REGKEY;
67extern char const* const LOOKUP_REGKEY; 52extern 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/
36static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f); 36static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f);
37 37
38// ################################################################################################ 38// ################################################################################################
39 39
40struct s_Universe* universe_create( lua_State* L) 40Universe* 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
52void universe_store( lua_State* L, struct s_Universe* U) 52void 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
63struct s_Universe* universe_get( lua_State* L) 63Universe* 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
11struct s_DeepPrelude;
12typedef struct s_DeepPrelude DeepPrelude;
13struct s_Keepers;
14typedef struct s_Keepers Keepers;
15struct s_Lane;
16typedef 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};
68typedef struct s_Universe Universe;
61 69
62struct s_Universe* universe_get( lua_State* L); 70Universe* universe_get( lua_State* L);
63struct s_Universe* universe_create( lua_State* L); 71Universe* universe_create( lua_State* L);
64void universe_store( lua_State* L, struct s_Universe* U); 72void universe_store( lua_State* L, Universe* U);
65 73
66#endif // UNIVERSE_H 74#endif // UNIVERSE_H