aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2019-04-26 12:20:06 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2019-04-26 12:20:06 +0200
commit9c84074c89661cd1e776eff3d4aa5329a2ac9524 (patch)
tree3c424371c1f21f4dee493793c8316059bf8217c6 /src
parent32f8cdfc73ed90dcf88ffcf4bfc1a3e4d5a69e6c (diff)
downloadlanes-9c84074c89661cd1e776eff3d4aa5329a2ac9524.tar.gz
lanes-9c84074c89661cd1e776eff3d4aa5329a2ac9524.tar.bz2
lanes-9c84074c89661cd1e776eff3d4aa5329a2ac9524.zip
Lane cancellation rework
opt.cancelstep is gone, hook is installed by lane:cancel() if requested lane:cancel() rework (see doc)
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/cancel.c117
-rw-r--r--src/cancel.h15
-rw-r--r--src/lanes.c67
-rw-r--r--src/lanes.h2
-rw-r--r--src/lanes.lua17
-rw-r--r--src/lanes_private.h3
7 files changed, 133 insertions, 90 deletions
diff --git a/src/Makefile b/src/Makefile
index aff06ba..9dc75a1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,7 +7,7 @@
7 7
8MODULE=lanes 8MODULE=lanes
9 9
10SRC=lanes.c compat.c threading.c tools.c linda.c deep.c keeper.c universe.c 10SRC=lanes.c cancel.c compat.c threading.c tools.c linda.c deep.c keeper.c universe.c
11 11
12OBJ=$(SRC:.c=.o) 12OBJ=$(SRC:.c=.o)
13 13
diff --git a/src/cancel.c b/src/cancel.c
index 11e100d..8ce00c8 100644
--- a/src/cancel.c
+++ b/src/cancel.c
@@ -77,12 +77,13 @@ LUAG_FUNC( cancel_test)
77// ################################################################################################ 77// ################################################################################################
78// ################################################################################################ 78// ################################################################################################
79 79
80void cancel_hook( lua_State* L, lua_Debug* ar) 80static void cancel_hook( lua_State* L, lua_Debug* ar)
81{ 81{
82 (void)ar; 82 (void)ar;
83 DEBUGSPEW_CODE( fprintf( stderr, "cancel_hook\n")); 83 DEBUGSPEW_CODE( fprintf( stderr, "cancel_hook\n"));
84 if( cancel_test( L) != CANCEL_NONE) 84 if( cancel_test( L) != CANCEL_NONE)
85 { 85 {
86 lua_sethook( L, NULL, 0, 0);
86 cancel_error( L); 87 cancel_error( L);
87 } 88 }
88} 89}
@@ -110,10 +111,10 @@ void cancel_hook( lua_State* L, lua_Debug* ar)
110 111
111// ################################################################################################ 112// ################################################################################################
112 113
113static cancel_result thread_cancel_soft( Lane* s, bool_t wake_lindas_) 114static cancel_result thread_cancel_soft( Lane* s, double secs_, bool_t wake_lindas_)
114{ 115{
115 s->cancel_request = CANCEL_SOFT; // it's now signaled to stop 116 s->cancel_request = CANCEL_SOFT; // it's now signaled to stop
116 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own 117 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own
117 if( wake_lindas_) // wake the thread so that execution returns from any pending linda operation if desired 118 if( wake_lindas_) // wake the thread so that execution returns from any pending linda operation if desired
118 { 119 {
119 SIGNAL_T *waiting_on = s->waiting_on; 120 SIGNAL_T *waiting_on = s->waiting_on;
@@ -122,8 +123,8 @@ static cancel_result thread_cancel_soft( Lane* s, bool_t wake_lindas_)
122 SIGNAL_ALL( waiting_on); 123 SIGNAL_ALL( waiting_on);
123 } 124 }
124 } 125 }
125 // say we succeeded though 126
126 return CR_Cancelled; 127 return THREAD_WAIT( &s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CR_Cancelled : CR_Timeout;
127} 128}
128 129
129// ################################################################################################ 130// ################################################################################################
@@ -163,9 +164,9 @@ static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bo
163 (void) waitkill_timeout_; // unused 164 (void) waitkill_timeout_; // unused
164 (void) L; // unused 165 (void) L; // unused
165#endif // THREADAPI == THREADAPI_PTHREAD 166#endif // THREADAPI == THREADAPI_PTHREAD
166 s->mstatus = KILLED; // mark 'gc' to wait for it 167 s->mstatus = KILLED; // mark 'gc' to wait for it
167 // note that s->status value must remain to whatever it was at the time of the kill 168 // note that s->status value must remain to whatever it was at the time of the kill
168 // because we need to know if we can lua_close() the Lua State or not. 169 // because we need to know if we can lua_close() the Lua State or not.
169 result = CR_Killed; 170 result = CR_Killed;
170 } 171 }
171 return result; 172 return result;
@@ -173,7 +174,7 @@ static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bo
173 174
174// ################################################################################################ 175// ################################################################################################
175 176
176cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_) 177cancel_result thread_cancel( lua_State* L, Lane* s, CancelOp op_, double secs_, bool_t force_, double waitkill_timeout_)
177{ 178{
178 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here 179 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
179 // We can read 's->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) 180 // We can read 's->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
@@ -190,9 +191,9 @@ cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_,
190 191
191 // signal the linda the wake up the thread so that it can react to the cancel query 192 // signal the linda the wake up the thread so that it can react to the cancel query
192 // let us hope we never land here with a pointer on a linda that has been destroyed... 193 // let us hope we never land here with a pointer on a linda that has been destroyed...
193 if( secs_ < 0.0) 194 if( op_ == CO_Soft)
194 { 195 {
195 return thread_cancel_soft( s, force_); 196 return thread_cancel_soft( s, secs_, force_);
196 } 197 }
197 198
198 return thread_cancel_hard( L, s, secs_, force_, waitkill_timeout_); 199 return thread_cancel_hard( L, s, secs_, force_, waitkill_timeout_);
@@ -201,49 +202,97 @@ cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_,
201// ################################################################################################ 202// ################################################################################################
202// ################################################################################################ 203// ################################################################################################
203 204
204// lane_h:cancel( [timeout] [, force [, forcekill_timeout]]) 205// > 0: the mask
206// = 0: soft
207// < 0: hard
208static CancelOp which_op( lua_State* L, int idx_)
209{
210 if( lua_type( L, idx_) == LUA_TSTRING)
211 {
212 CancelOp op = CO_Invalid;
213 char const* str = lua_tostring( L, idx_);
214 if( strcmp( str, "soft") == 0)
215 {
216 op = CO_Soft;
217 }
218 else if( strcmp( str, "count") == 0)
219 {
220 op = CO_Count;
221 }
222 else if( strcmp( str, "line") == 0)
223 {
224 op = CO_Line;
225 }
226 else if( strcmp( str, "call") == 0)
227 {
228 op = CO_Call;
229 }
230 else if( strcmp( str, "ret") == 0)
231 {
232 op = CO_Ret;
233 }
234 else if( strcmp( str, "hard") == 0)
235 {
236 op = CO_Hard;
237 }
238 lua_remove( L, idx_); // argument is processed, remove it
239 if( op == CO_Invalid)
240 {
241 luaL_error( L, "invalid hook option %s", str);
242 }
243 return op;
244 }
245 return CO_Hard;
246}
247// ################################################################################################
248
249// bool[,reason] = lane_h:cancel( [mode, hookcount] [, timeout] [, force [, forcekill_timeout]])
205LUAG_FUNC( thread_cancel) 250LUAG_FUNC( thread_cancel)
206{ 251{
207 Lane* s = lua_toLane( L, 1); 252 Lane* s = lua_toLane( L, 1);
208 double secs = 0.0; 253 double secs = 0.0;
209 int force_i = 2; 254 CancelOp op = which_op( L, 2); // this removes the op string from the stack
210 int forcekill_timeout_i = 3;
211 255
212 if( lua_isnumber( L, 2)) 256 if( op > 0) // hook is requested
213 { 257 {
214 secs = lua_tonumber( L, 2); 258 int hook_count = (int) lua_tointeger( L, 2);
215 if( secs < 0.0 && lua_gettop( L) > 3) 259 lua_remove( L, 2); // argument is processed, remove it
260 if( hook_count < 1)
216 { 261 {
217 return luaL_error( L, "can't force_kill a soft cancel"); 262 return luaL_error( L, "hook count cannot be < 1");
218 } 263 }
219 // negative timeout and force flag means we want to wake linda-waiting threads 264 lua_sethook( s->L, cancel_hook, op, hook_count);
220 ++ force_i;
221 ++ forcekill_timeout_i;
222 } 265 }
223 else if( lua_isnil( L, 2)) 266
267 if( lua_type( L, 2) == LUA_TNUMBER)
224 { 268 {
225 ++ force_i; 269 secs = lua_tonumber( L, 2);
226 ++ forcekill_timeout_i; 270 lua_remove( L, 2); // argument is processed, remove it
271 if( secs < 0.0)
272 {
273 return luaL_error( L, "cancel timeout cannot be < 0");
274 }
227 } 275 }
228 276
229 { 277 {
230 bool_t force = lua_toboolean( L, force_i); // FALSE if nothing there 278 bool_t force = lua_toboolean( L, 2); // FALSE if nothing there
231 double forcekill_timeout = luaL_optnumber( L, forcekill_timeout_i, 0.0); 279 double forcekill_timeout = luaL_optnumber( L, 3, 0.0);
232 280
233 switch( thread_cancel( L, s, secs, force, forcekill_timeout)) 281 switch( thread_cancel( L, s, op, secs, force, forcekill_timeout))
234 { 282 {
235 case CR_Timeout: 283 case CR_Timeout:
236 lua_pushboolean( L, 0); 284 lua_pushboolean( L, 0);
237 lua_pushstring( L, "timeout"); 285 lua_pushstring( L, "timeout");
238 return 2; 286 return 2;
239 287
240 case CR_Cancelled: 288 case CR_Cancelled:
241 lua_pushboolean( L, 1); 289 lua_pushboolean( L, 1);
242 return 1; 290 push_thread_status( L, s);
291 return 2;
243 292
244 case CR_Killed: 293 case CR_Killed:
245 lua_pushboolean( L, 0); 294 lua_pushboolean( L, 1);
246 lua_pushstring( L, "killed"); 295 push_thread_status( L, s);
247 return 2; 296 return 2;
248 } 297 }
249 } 298 }
diff --git a/src/cancel.h b/src/cancel.h
index 3112809..e7656ac 100644
--- a/src/cancel.h
+++ b/src/cancel.h
@@ -29,15 +29,24 @@ typedef enum
29 CR_Killed 29 CR_Killed
30} cancel_result; 30} cancel_result;
31 31
32typedef enum
33{
34 CO_Invalid = -2,
35 CO_Hard = -1,
36 CO_Soft = 0,
37 CO_Count = LUA_MASKCOUNT,
38 CO_Line = LUA_MASKLINE,
39 CO_Call = LUA_MASKCALL,
40 CO_Ret = LUA_MASKRET,
41} CancelOp;
42
32// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ 43// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/
33static DECLARE_CONST_UNIQUE_KEY(CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel 44static DECLARE_CONST_UNIQUE_KEY(CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel
34 45
35// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/ 46// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/
36static DECLARE_CONST_UNIQUE_KEY(CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key 47static DECLARE_CONST_UNIQUE_KEY(CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key
37 48
38void cancel_hook( lua_State* L, lua_Debug* ar); 49cancel_result thread_cancel( lua_State* L, Lane* s, CancelOp op_, double secs_, bool_t force_, double waitkill_timeout_);
39
40cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_);
41 50
42static inline int cancel_error( lua_State* L) 51static inline int cancel_error( lua_State* L)
43{ 52{
diff --git a/src/lanes.c b/src/lanes.c
index cbac6da..8f159a9 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -452,7 +452,7 @@ static int selfdestruct_gc( lua_State* L)
452 while( s != SELFDESTRUCT_END) 452 while( s != SELFDESTRUCT_END)
453 { 453 {
454 // attempt a regular unforced hard cancel with a small timeout 454 // attempt a regular unforced hard cancel with a small timeout
455 bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, 0.0001, FALSE, 0.0); 455 bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, CO_Hard, 0.0001, FALSE, 0.0);
456 // if we failed, and we know the thread is waiting on a linda 456 // if we failed, and we know the thread is waiting on a linda
457 if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL) 457 if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL)
458 { 458 {
@@ -1027,7 +1027,6 @@ static DECLARE_CONST_UNIQUE_KEY( GCCB_KEY, 0xcfb1f046ef074e88);
1027//--- 1027//---
1028// lane_ud = lane_new( function 1028// lane_ud = lane_new( function
1029// , [libs_str] 1029// , [libs_str]
1030// , [cancelstep_uint=0]
1031// , [priority_int=0] 1030// , [priority_int=0]
1032// , [globals_tbl] 1031// , [globals_tbl]
1033// , [package_tbl] 1032// , [package_tbl]
@@ -1044,14 +1043,13 @@ LUAG_FUNC( lane_new)
1044 Lane** ud; 1043 Lane** ud;
1045 1044
1046 char const* libs_str = lua_tostring( L, 2); 1045 char const* libs_str = lua_tostring( L, 2);
1047 uint_t cancelstep_idx = luaG_optunsigned( L, 3, 0); 1046 int const priority = (int) luaL_optinteger( L, 3, 0);
1048 int const priority = (int) luaL_optinteger( L, 4, 0); 1047 uint_t globals_idx = lua_isnoneornil( L, 4) ? 0 : 4;
1049 uint_t globals_idx = lua_isnoneornil( L, 5) ? 0 : 5; 1048 uint_t package_idx = lua_isnoneornil( L, 5) ? 0 : 5;
1050 uint_t package_idx = lua_isnoneornil( L, 6) ? 0 : 6; 1049 uint_t required_idx = lua_isnoneornil( L, 6) ? 0 : 6;
1051 uint_t required_idx = lua_isnoneornil( L, 7) ? 0 : 7; 1050 uint_t gc_cb_idx = lua_isnoneornil( L, 7) ? 0 : 7;
1052 uint_t gc_cb_idx = lua_isnoneornil( L, 8) ? 0 : 8; 1051
1053 1052#define FIXED_ARGS 7
1054#define FIXED_ARGS 8
1055 int const nargs = lua_gettop(L) - FIXED_ARGS; 1053 int const nargs = lua_gettop(L) - FIXED_ARGS;
1056 Universe* U = universe_get( L); 1054 Universe* U = universe_get( L);
1057 ASSERT_L( nargs >= 0); 1055 ASSERT_L( nargs >= 0);
@@ -1074,7 +1072,7 @@ LUAG_FUNC( lane_new)
1074 STACK_GROW( L2, nargs + 3); // 1072 STACK_GROW( L2, nargs + 3); //
1075 STACK_CHECK( L2, 0); 1073 STACK_CHECK( L2, 0);
1076 1074
1077 STACK_GROW( L, 3); // func libs cancelstep priority globals package required gc_cb [... args ...] 1075 STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...]
1078 STACK_CHECK( L, 0); 1076 STACK_CHECK( L, 0);
1079 1077
1080 // give a default "Lua" name to the thread to see VM name in Decoda debugger 1078 // give a default "Lua" name to the thread to see VM name in Decoda debugger
@@ -1103,8 +1101,8 @@ LUAG_FUNC( lane_new)
1103 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required_idx)); 1101 return luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required_idx));
1104 } 1102 }
1105 1103
1106 lua_pushnil( L); // func libs cancelstep priority globals package required gc_cb [... args ...] nil 1104 lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil
1107 while( lua_next( L, required_idx) != 0) // func libs cancelstep priority globals package required gc_cb [... args ...] n "modname" 1105 while( lua_next( L, required_idx) != 0) // func libs priority globals package required gc_cb [... args ...] n "modname"
1108 { 1106 {
1109 if( lua_type( L, -1) != LUA_TSTRING || lua_type( L, -2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired) 1107 if( lua_type( L, -1) != LUA_TSTRING || lua_type( L, -2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired)
1110 { 1108 {
@@ -1130,7 +1128,7 @@ LUAG_FUNC( lane_new)
1130 if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode 1128 if( lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode
1131 { 1129 {
1132 // propagate error to main state if any 1130 // propagate error to main state if any
1133 luaG_inter_move( U, L2, L, 1, eLM_LaneBody); // func libs cancelstep priority globals package required gc_cb [... args ...] n "modname" error 1131 luaG_inter_move( U, L2, L, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] n "modname" error
1134 return lua_error( L); 1132 return lua_error( L);
1135 } 1133 }
1136 // after requiring the module, register the functions it exported in our name<->function database 1134 // after requiring the module, register the functions it exported in our name<->function database
@@ -1138,9 +1136,9 @@ LUAG_FUNC( lane_new)
1138 lua_pop( L2, 1); // 1136 lua_pop( L2, 1); //
1139 } 1137 }
1140 } 1138 }
1141 lua_pop( L, 1); // func libs cancelstep priority globals package required gc_cb [... args ...] n 1139 lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] n
1142 ++ nbRequired; 1140 ++ nbRequired;
1143 } // func libs cancelstep priority globals package required gc_cb [... args ...] 1141 } // func libs priority globals package required gc_cb [... args ...]
1144 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1142 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1145 } 1143 }
1146 STACK_MID( L, 0); 1144 STACK_MID( L, 0);
@@ -1158,16 +1156,16 @@ LUAG_FUNC( lane_new)
1158 } 1156 }
1159 1157
1160 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1158 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1161 lua_pushnil( L); // func libs cancelstep priority globals package required gc_cb [... args ...] nil 1159 lua_pushnil( L); // func libs priority globals package required gc_cb [... args ...] nil
1162 // Lua 5.2 wants us to push the globals table on the stack 1160 // Lua 5.2 wants us to push the globals table on the stack
1163 lua_pushglobaltable( L2); // _G 1161 lua_pushglobaltable( L2); // _G
1164 while( lua_next( L, globals_idx)) // func libs cancelstep priority globals package required gc_cb [... args ...] k v 1162 while( lua_next( L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v
1165 { 1163 {
1166 luaG_inter_copy( U, L, L2, 2, eLM_LaneBody); // _G k v 1164 luaG_inter_copy( U, L, L2, 2, eLM_LaneBody); // _G k v
1167 // assign it in L2's globals table 1165 // assign it in L2's globals table
1168 lua_rawset( L2, -3); // _G 1166 lua_rawset( L2, -3); // _G
1169 lua_pop( L, 1); // func libs cancelstep priority globals package required gc_cb [... args ...] k 1167 lua_pop( L, 1); // func libs priority globals package required gc_cb [... args ...] k
1170 } // func libs cancelstep priority globals package required gc_cb [... args ...] 1168 } // func libs priority globals package required gc_cb [... args ...]
1171 lua_pop( L2, 1); // 1169 lua_pop( L2, 1); //
1172 1170
1173 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1171 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
@@ -1181,8 +1179,8 @@ LUAG_FUNC( lane_new)
1181 int res; 1179 int res;
1182 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); 1180 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END));
1183 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1181 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1184 lua_pushvalue( L, 1); // func libs cancelstep priority globals package required gc_cb [... args ...] func 1182 lua_pushvalue( L, 1); // func libs priority globals package required gc_cb [... args ...] func
1185 res = luaG_inter_move( U, L, L2, 1, eLM_LaneBody); // func libs cancelstep priority globals package required gc_cb [... args ...] // func 1183 res = luaG_inter_move( U, L, L2, 1, eLM_LaneBody); // func libs priority globals package required gc_cb [... args ...] // func
1186 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1184 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1187 if( res != 0) 1185 if( res != 0)
1188 { 1186 {
@@ -1207,7 +1205,7 @@ LUAG_FUNC( lane_new)
1207 int res; 1205 int res;
1208 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); 1206 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END));
1209 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1207 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1210 res = luaG_inter_move( U, L, L2, nargs, eLM_LaneBody); // func libs cancelstep priority globals package required gc_cb // func [... args ...] 1208 res = luaG_inter_move( U, L, L2, nargs, eLM_LaneBody); // func libs priority globals package required gc_cb // func [... args ...]
1211 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1209 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1212 if( res != 0) 1210 if( res != 0)
1213 { 1211 {
@@ -1222,7 +1220,7 @@ LUAG_FUNC( lane_new)
1222 // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) 1220 // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread)
1223 // 1221 //
1224 // a Lane full userdata needs a single uservalue 1222 // a Lane full userdata needs a single uservalue
1225 ud = lua_newuserdatauv( L, sizeof( Lane*), 1); // func libs cancelstep priority globals package required gc_cb lane 1223 ud = lua_newuserdatauv( L, sizeof( Lane*), 1); // func libs priority globals package required gc_cb lane
1226 s = *ud = (Lane*) malloc( sizeof( Lane)); 1224 s = *ud = (Lane*) malloc( sizeof( Lane));
1227 if( s == NULL) 1225 if( s == NULL)
1228 { 1226 {
@@ -1252,8 +1250,8 @@ LUAG_FUNC( lane_new)
1252 1250
1253 // Set metatable for the userdata 1251 // Set metatable for the userdata
1254 // 1252 //
1255 lua_pushvalue( L, lua_upvalueindex( 1)); // func libs cancelstep priority globals package required gc_cb lane mt 1253 lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt
1256 lua_setmetatable( L, -2); // func libs cancelstep priority globals package required gc_cb lane 1254 lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane
1257 STACK_MID( L, 1); 1255 STACK_MID( L, 1);
1258 1256
1259 // Create uservalue for the userdata 1257 // Create uservalue for the userdata
@@ -1263,21 +1261,16 @@ LUAG_FUNC( lane_new)
1263 // Store the gc_cb callback in the uservalue 1261 // Store the gc_cb callback in the uservalue
1264 if( gc_cb_idx > 0) 1262 if( gc_cb_idx > 0)
1265 { 1263 {
1266 push_unique_key( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k 1264 push_unique_key( L, GCCB_KEY); // func libs priority globals package required gc_cb lane uv k
1267 lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb 1265 lua_pushvalue( L, gc_cb_idx); // func libs priority globals package required gc_cb lane uv k gc_cb
1268 lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv 1266 lua_rawset( L, -3); // func libs priority globals package required gc_cb lane uv
1269 } 1267 }
1270 1268
1271 lua_setiuservalue( L, -2, 1); // func libs cancelstep priority globals package required gc_cb lane 1269 lua_setiuservalue( L, -2, 1); // func libs priority globals package required gc_cb lane
1272 1270
1273 // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). 1271 // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive).
1274 REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...] 1272 REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...]
1275 1273
1276 if( cancelstep_idx)
1277 {
1278 lua_sethook( L2, cancel_hook, LUA_MASKCOUNT, cancelstep_idx);
1279 }
1280
1281 STACK_END( L, 1); 1274 STACK_END( L, 1);
1282 STACK_END( L2, 1 + nargs); 1275 STACK_END( L2, 1 + nargs);
1283 1276
@@ -1402,7 +1395,7 @@ static char const * thread_status_string( Lane* s)
1402 return str; 1395 return str;
1403} 1396}
1404 1397
1405static int push_thread_status( lua_State* L, Lane* s) 1398int push_thread_status( lua_State* L, Lane* s)
1406{ 1399{
1407 char const* const str = thread_status_string( s); 1400 char const* const str = thread_status_string( s);
1408 ASSERT_L( str); 1401 ASSERT_L( str);
diff --git a/src/lanes.h b/src/lanes.h
index de60d6d..da0dd26 100644
--- a/src/lanes.h
+++ b/src/lanes.h
@@ -11,7 +11,7 @@
11#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 11#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
12 12
13#define LANES_VERSION_MAJOR 3 13#define LANES_VERSION_MAJOR 3
14#define LANES_VERSION_MINOR 13 14#define LANES_VERSION_MINOR 14
15#define LANES_VERSION_PATCH 0 15#define LANES_VERSION_PATCH 0
16 16
17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH)))) 17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH))))
diff --git a/src/lanes.lua b/src/lanes.lua
index ba9da81..4d6deac 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -146,7 +146,7 @@ lanes.configure = function( settings_)
146 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>", 146 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>",
147 description= "Running multiple Lua states in parallel", 147 description= "Running multiple Lua states in parallel",
148 license= "MIT/X11", 148 license= "MIT/X11",
149 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-18, Benoit Germain", 149 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-19, Benoit Germain",
150 version = assert( core.version) 150 version = assert( core.version)
151 } 151 }
152 152
@@ -198,13 +198,6 @@ lanes.configure = function( settings_)
198 -- 198 --
199 -- 'opt': .priority: int (-3..+3) smaller is lower priority (0 = default) 199 -- 'opt': .priority: int (-3..+3) smaller is lower priority (0 = default)
200 -- 200 --
201 -- .cancelstep: bool | uint
202 -- false: cancellation check only at pending Linda operations
203 -- (send/receive) so no runtime performance penalty (default)
204 -- true: adequate cancellation check (same as 100)
205 -- >0: cancellation check every x Lua lines (small number= faster
206 -- reaction but more performance overhead)
207 --
208 -- .globals: table of globals to set for a new thread (passed by value) 201 -- .globals: table of globals to set for a new thread (passed by value)
209 -- 202 --
210 -- .required: table of packages to require 203 -- .required: table of packages to require
@@ -246,10 +239,6 @@ lanes.configure = function( settings_)
246 local tv = type( v_) 239 local tv = type( v_)
247 return (tv == "number") and v_ or raise_option_error( "priority", tv, v_) 240 return (tv == "number") and v_ or raise_option_error( "priority", tv, v_)
248 end, 241 end,
249 cancelstep = function( v_)
250 local tv = type( v_)
251 return (tv == "number") and v_ or (v_ == true) and 100 or (v_ == false) and 0 or raise_option_error( "cancelstep", tv, v_)
252 end,
253 globals = function( v_) 242 globals = function( v_)
254 local tv = type( v_) 243 local tv = type( v_)
255 return (tv == "table") and v_ or raise_option_error( "globals", tv, v_) 244 return (tv == "table") and v_ or raise_option_error( "globals", tv, v_)
@@ -334,10 +323,10 @@ lanes.configure = function( settings_)
334 end 323 end
335 end 324 end
336 325
337 local cancelstep, priority, globals, package, required, gc_cb = opt.cancelstep, opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb 326 local priority, globals, package, required, gc_cb = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb
338 return function( ...) 327 return function( ...)
339 -- must pass functions args last else they will be truncated to the first one 328 -- must pass functions args last else they will be truncated to the first one
340 return core_lane_new( func, libs, cancelstep, priority, globals, package, required, gc_cb, ...) 329 return core_lane_new( func, libs, priority, globals, package, required, gc_cb, ...)
341 end 330 end
342 end -- gen() 331 end -- gen()
343 332
diff --git a/src/lanes_private.h b/src/lanes_private.h
index ac05129..1a15969 100644
--- a/src/lanes_private.h
+++ b/src/lanes_private.h
@@ -89,4 +89,7 @@ static inline Lane* get_lane_from_registry( lua_State* L)
89 return s; 89 return s;
90} 90}
91 91
92int push_thread_status( lua_State* L, Lane* s);
93
94
92#endif // __lanes_private_h__ \ No newline at end of file 95#endif // __lanes_private_h__ \ No newline at end of file