1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
/*
* TOOLS.H
*/
#ifndef TOOLS_H
#define TOOLS_H
#include "lauxlib.h"
#include "threading.h"
#include "deep.h"
// MUTEX_T
#include <assert.h>
// M$ compiler doesn't support 'inline' keyword in C files...
#if defined( _MSC_VER)
#define inline __inline
#endif
// For some reason, LuaJIT 64bits doesn't support lua_newstate()
#if defined(LUA_LJDIR) && (defined(__x86_64__) || defined(_M_X64))
#define PROPAGATE_ALLOCF 0
#else // LuaJIT x64
#define PROPAGATE_ALLOCF 1
#endif // LuaJIT x64
#if PROPAGATE_ALLOCF
#define PROPAGATE_ALLOCF_PREP( L) void* allocUD; lua_Alloc allocF = lua_getallocf( L, &allocUD)
#define PROPAGATE_ALLOCF_ALLOC() lua_newstate( allocF, allocUD)
#else // PROPAGATE_ALLOCF
#define PROPAGATE_ALLOCF_PREP( L)
#define PROPAGATE_ALLOCF_ALLOC() luaL_newstate()
#endif // PROPAGATE_ALLOCF
#define USE_DEBUG_SPEW 0
#if USE_DEBUG_SPEW
extern char const* debugspew_indent;
#define INDENT_BEGIN "%.*s "
#define INDENT_END , (U ? U->debugspew_indent_depth : 0), debugspew_indent
#define DEBUGSPEW_CODE(_code) _code
#else // USE_DEBUG_SPEW
#define DEBUGSPEW_CODE(_code)
#endif // USE_DEBUG_SPEW
// ################################################################################################
/*
* Do we want to activate full lane tracking feature? (EXPERIMENTAL)
*/
#define HAVE_LANE_TRACKING 1
// ################################################################################################
// this is pointed to by full userdata proxies, and allocated with malloc() to survive any lua_State lifetime
typedef struct
{
volatile int refcount;
void* deep;
// when stored in a keeper state, the full userdata doesn't have a metatable, so we need direct access to the idfunc
luaG_IdFunction idfunc;
} DEEP_PRELUDE;
// ################################################################################################
// everything regarding the a Lanes universe is stored in that global structure
// held as a full userdata in the master Lua state that required it for the first time
// don't forget to initialize all members in LG_configure()
struct s_Universe
{
// for verbose errors
bool_t verboseErrors;
lua_CFunction on_state_create_func;
struct s_Keepers* keepers;
// Initialized by 'init_once_LOCKED()': the deep userdata Linda object
// used for timers (each lane will get a proxy to this)
volatile DEEP_PRELUDE* timer_deep; // = NULL
#if HAVE_LANE_TRACKING
MUTEX_T tracking_cs;
struct s_lane* volatile tracking_first; // will change to TRACKING_END if we want to activate tracking
#endif // HAVE_LANE_TRACKING
MUTEX_T selfdestruct_cs;
// require() serialization
MUTEX_T require_cs;
// Lock for reference counter inc/dec locks (to be initialized by outside code) TODO: get rid of this and use atomics instead!
MUTEX_T deep_lock;
MUTEX_T mtid_lock;
int last_mt_id;
#if USE_DEBUG_SPEW
int debugspew_indent_depth;
#endif // USE_DEBUG_SPEW
struct s_lane* volatile selfdestruct_first;
// After a lane has removed itself from the chain, it still performs some processing.
// The terminal desinit sequence should wait for all such processing to terminate before force-killing threads
int volatile selfdestructing_count;
};
struct s_Universe* get_universe( lua_State* L);
extern void* const UNIVERSE_REGKEY;
// ################################################################################################
#ifdef NDEBUG
#define _ASSERT_L(lua,c) /*nothing*/
#define STACK_CHECK(L) /*nothing*/
#define STACK_MID(L,c) /*nothing*/
#define STACK_END(L,c) /*nothing*/
#define STACK_DUMP(L) /*nothing*/
#else
void ASSERT_IMPL( lua_State* L, bool_t cond_, char const* file_, int const line_, char const* text_);
#define _ASSERT_L(lua,c) ASSERT_IMPL( lua, (c) != 0, __FILE__, __LINE__, #c)
//
#define STACK_CHECK(L) { int const _oldtop_##L = lua_gettop( L)
#define STACK_MID(L,change) \
do \
{ \
int a = lua_gettop( L) - _oldtop_##L; \
int b = (change); \
if( a != b) \
luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", a, b, __FILE__, __LINE__ ); \
} while( 0)
#define STACK_END(L,change) STACK_MID(L,change); }
#define STACK_DUMP( L) luaG_dump( L)
#endif
#define ASSERT_L(c) _ASSERT_L(L,c)
#define STACK_GROW( L, n) do { if (!lua_checkstack(L,(int)(n))) luaL_error( L, "Cannot grow stack!" ); } while( 0)
#define LUAG_FUNC( func_name ) static int LG_##func_name( lua_State* L)
#define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d))
#define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i))
void luaG_dump( lua_State* L );
lua_State* luaG_newstate( struct s_Universe* U, lua_State* _from, char const* libs);
void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2);
// ################################################################################################
enum eLookupMode
{
eLM_LaneBody, // send the lane body directly from the source to the destination lane
eLM_ToKeeper, // send a function from a lane to a keeper state
eLM_FromKeeper // send a function from a keeper state to a lane
};
char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_);
void free_deep_prelude( lua_State* L, DEEP_PRELUDE* prelude_);
int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_);
int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_);
int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_);
int luaG_nameof( lua_State* L);
int luaG_new_require( lua_State* L);
void populate_func_lookup_table( lua_State* L, int _i, char const* _name);
void serialize_require( struct s_Universe* U, lua_State *L);
void initialize_on_state_create( struct s_Universe* U, lua_State* L);
void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_);
// ################################################################################################
extern char const* const CONFIG_REGKEY;
extern char const* const LOOKUP_REGKEY;
#endif // TOOLS_H
|