diff options
Diffstat (limited to 'src/llthread.c')
-rw-r--r-- | src/llthread.c | 338 |
1 files changed, 72 insertions, 266 deletions
diff --git a/src/llthread.c b/src/llthread.c index f7a9b59..4f20840 100644 --- a/src/llthread.c +++ b/src/llthread.c | |||
@@ -58,7 +58,6 @@ typedef int join_timeout_t; | |||
58 | typedef pthread_t os_thread_t; | 58 | typedef pthread_t os_thread_t; |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | |||
62 | LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L); | 61 | LLTHREADS_EXPORT_API int luaopen_llthreads(lua_State *L); |
63 | 62 | ||
64 | #define LLTHREAD_T_NAME "LLThread" | 63 | #define LLTHREAD_T_NAME "LLThread" |
@@ -67,217 +66,13 @@ static const char *LLTHREAD_LOGGER_HOLDER = LLTHREAD_T_NAME " logger holder"; | |||
67 | 66 | ||
68 | //{ traceback | 67 | //{ traceback |
69 | 68 | ||
70 | #define ERROR_LEN 1024 | 69 | #include "traceback.inc" |
71 | |||
72 | /****************************************************************************** | ||
73 | * traceback() function from Lua 5.1/5.2 source. | ||
74 | * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. | ||
75 | * | ||
76 | * Permission is hereby granted, free of charge, to any person obtaining | ||
77 | * a copy of this software and associated documentation files (the | ||
78 | * "Software"), to deal in the Software without restriction, including | ||
79 | * without limitation the rights to use, copy, modify, merge, publish, | ||
80 | * distribute, sublicense, and/or sell copies of the Software, and to | ||
81 | * permit persons to whom the Software is furnished to do so, subject to | ||
82 | * the following conditions: | ||
83 | * | ||
84 | * The above copyright notice and this permission notice shall be | ||
85 | * included in all copies or substantial portions of the Software. | ||
86 | * | ||
87 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
88 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
89 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
90 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
91 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
92 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
93 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
94 | ******************************************************************************/ | ||
95 | #if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501) | ||
96 | /* from Lua 5.1 */ | ||
97 | static int traceback (lua_State *L) { | ||
98 | if (!lua_isstring(L, 1)) /* 'message' not a string? */ | ||
99 | return 1; /* keep it intact */ | ||
100 | lua_getglobal(L, "debug"); | ||
101 | if (!lua_istable(L, -1)) { | ||
102 | lua_pop(L, 1); | ||
103 | return 1; | ||
104 | } | ||
105 | lua_getfield(L, -1, "traceback"); | ||
106 | if (!lua_isfunction(L, -1)) { | ||
107 | lua_pop(L, 2); | ||
108 | return 1; | ||
109 | } | ||
110 | lua_pushvalue(L, 1); /* pass error message */ | ||
111 | lua_pushinteger(L, 2); /* skip this function and traceback */ | ||
112 | lua_call(L, 2, 1); /* call debug.traceback */ | ||
113 | return 1; | ||
114 | } | ||
115 | #else | ||
116 | /* from Lua 5.2 */ | ||
117 | static int traceback (lua_State *L) { | ||
118 | const char *msg = lua_tostring(L, 1); | ||
119 | if (msg) | ||
120 | luaL_traceback(L, L, msg, 1); | ||
121 | else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ | ||
122 | if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ | ||
123 | lua_pushliteral(L, "(no error message)"); | ||
124 | } | ||
125 | return 1; | ||
126 | } | ||
127 | #endif | ||
128 | 70 | ||
129 | //} | 71 | //} |
130 | 72 | ||
131 | //{ copy values | 73 | //{ copy values |
132 | 74 | ||
133 | /* maximum recursive depth of table copies. */ | 75 | #include "copy.inc" |
134 | #define MAX_COPY_DEPTH 30 | ||
135 | |||
136 | typedef struct { | ||
137 | lua_State *from_L; | ||
138 | lua_State *to_L; | ||
139 | int has_cache; | ||
140 | int cache_idx; | ||
141 | int is_arg; | ||
142 | } llthread_copy_state; | ||
143 | |||
144 | static int llthread_copy_table_from_cache(llthread_copy_state *state, int idx) { | ||
145 | void *ptr; | ||
146 | |||
147 | /* convert table to pointer for lookup in cache. */ | ||
148 | ptr = (void *)lua_topointer(state->from_L, idx); | ||
149 | if(ptr == NULL) return 0; /* can't convert to pointer. */ | ||
150 | |||
151 | /* check if we need to create the cache. */ | ||
152 | if(!state->has_cache) { | ||
153 | lua_newtable(state->to_L); | ||
154 | lua_replace(state->to_L, state->cache_idx); | ||
155 | state->has_cache = 1; | ||
156 | } | ||
157 | |||
158 | lua_pushlightuserdata(state->to_L, ptr); | ||
159 | lua_rawget(state->to_L, state->cache_idx); | ||
160 | if(lua_isnil(state->to_L, -1)) { | ||
161 | /* not in cache. */ | ||
162 | lua_pop(state->to_L, 1); | ||
163 | /* create new table and add to cache. */ | ||
164 | lua_newtable(state->to_L); | ||
165 | lua_pushlightuserdata(state->to_L, ptr); | ||
166 | lua_pushvalue(state->to_L, -2); | ||
167 | lua_rawset(state->to_L, state->cache_idx); | ||
168 | return 0; | ||
169 | } | ||
170 | /* found table in cache. */ | ||
171 | return 1; | ||
172 | } | ||
173 | |||
174 | static int llthread_copy_value(llthread_copy_state *state, int depth, int idx) { | ||
175 | const char *str; | ||
176 | size_t str_len; | ||
177 | int kv_pos; | ||
178 | |||
179 | /* Maximum recursive depth */ | ||
180 | if(++depth > MAX_COPY_DEPTH) { | ||
181 | return luaL_error(state->from_L, "Hit maximum copy depth (%d > %d).", depth, MAX_COPY_DEPTH); | ||
182 | } | ||
183 | |||
184 | /* only support string/number/boolean/nil/table/lightuserdata. */ | ||
185 | switch(lua_type(state->from_L, idx)) { | ||
186 | case LUA_TNIL: | ||
187 | lua_pushnil(state->to_L); | ||
188 | break; | ||
189 | case LUA_TNUMBER: | ||
190 | lua_pushnumber(state->to_L, lua_tonumber(state->from_L, idx)); | ||
191 | break; | ||
192 | case LUA_TBOOLEAN: | ||
193 | lua_pushboolean(state->to_L, lua_toboolean(state->from_L, idx)); | ||
194 | break; | ||
195 | case LUA_TSTRING: | ||
196 | str = lua_tolstring(state->from_L, idx, &(str_len)); | ||
197 | lua_pushlstring(state->to_L, str, str_len); | ||
198 | break; | ||
199 | case LUA_TLIGHTUSERDATA: | ||
200 | lua_pushlightuserdata(state->to_L, lua_touserdata(state->from_L, idx)); | ||
201 | break; | ||
202 | case LUA_TTABLE: | ||
203 | /* make sure there is room on the new state for 3 values (table,key,value) */ | ||
204 | if(!lua_checkstack(state->to_L, 3)) { | ||
205 | return luaL_error(state->from_L, "To stack overflow!"); | ||
206 | } | ||
207 | /* make room on from stack for key/value pairs. */ | ||
208 | luaL_checkstack(state->from_L, 2, "From stack overflow!"); | ||
209 | |||
210 | /* check cache for table. */ | ||
211 | if(llthread_copy_table_from_cache(state, idx)) { | ||
212 | /* found in cache don't need to copy table. */ | ||
213 | break; | ||
214 | } | ||
215 | lua_pushnil(state->from_L); | ||
216 | while (lua_next(state->from_L, idx) != 0) { | ||
217 | /* key is at (top - 1), value at (top), but we need to normalize these | ||
218 | * to positive indices */ | ||
219 | kv_pos = lua_gettop(state->from_L); | ||
220 | /* copy key */ | ||
221 | llthread_copy_value(state, depth, kv_pos - 1); | ||
222 | /* copy value */ | ||
223 | llthread_copy_value(state, depth, kv_pos); | ||
224 | /* Copied key and value are now at -2 and -1 in state->to_L. */ | ||
225 | lua_settable(state->to_L, -3); | ||
226 | /* Pop value for next iteration */ | ||
227 | lua_pop(state->from_L, 1); | ||
228 | } | ||
229 | break; | ||
230 | case LUA_TFUNCTION: | ||
231 | if(lua_iscfunction(state->from_L, idx)){ | ||
232 | lua_CFunction fn = lua_tocfunction(state->from_L, idx); | ||
233 | lua_pushcfunction(state->to_L, fn); | ||
234 | break; | ||
235 | } | ||
236 | case LUA_TUSERDATA: | ||
237 | case LUA_TTHREAD: | ||
238 | default: | ||
239 | if (state->is_arg) { | ||
240 | return luaL_argerror(state->from_L, idx, "function/userdata/thread types un-supported."); | ||
241 | } else { | ||
242 | /* convert un-supported types to an error string. */ | ||
243 | lua_pushfstring(state->to_L, "Un-supported value: %s: %p", | ||
244 | lua_typename(state->from_L, lua_type(state->from_L, idx)), lua_topointer(state->from_L, idx)); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | return 1; | ||
249 | } | ||
250 | |||
251 | static int llthread_copy_values(lua_State *from_L, lua_State *to_L, int idx, int top, int is_arg) { | ||
252 | llthread_copy_state state; | ||
253 | int nvalues = 0; | ||
254 | int n; | ||
255 | |||
256 | nvalues = (top - idx) + 1; | ||
257 | /* make sure there is room on the new state for the values. */ | ||
258 | if(!lua_checkstack(to_L, nvalues + 1)) { | ||
259 | return luaL_error(from_L, "To stack overflow!"); | ||
260 | } | ||
261 | |||
262 | /* setup copy state. */ | ||
263 | state.from_L = from_L; | ||
264 | state.to_L = to_L; | ||
265 | state.is_arg = is_arg; | ||
266 | state.has_cache = 0; /* don't create cache table unless it is needed. */ | ||
267 | lua_pushnil(to_L); | ||
268 | state.cache_idx = lua_gettop(to_L); | ||
269 | |||
270 | nvalues = 0; | ||
271 | for(n = idx; n <= top; n++) { | ||
272 | llthread_copy_value(&state, 0, n); | ||
273 | ++nvalues; | ||
274 | } | ||
275 | |||
276 | /* remove cache table. */ | ||
277 | lua_remove(to_L, state.cache_idx); | ||
278 | |||
279 | return nvalues; | ||
280 | } | ||
281 | 76 | ||
282 | //} | 77 | //} |
283 | 78 | ||
@@ -287,20 +82,22 @@ static int fail(lua_State *L, const char *msg){ | |||
287 | return 2; | 82 | return 2; |
288 | } | 83 | } |
289 | 84 | ||
85 | #define ERROR_LEN 1024 | ||
86 | |||
290 | #define flags_t unsigned char | 87 | #define flags_t unsigned char |
291 | 88 | ||
292 | #define TSTATE_NONE (flags_t)0 | 89 | #define FLAG_NONE (flags_t)0 |
293 | #define TSTATE_STARTED (flags_t)1<<0 | 90 | #define FLAG_STARTED (flags_t)1<<0 |
294 | #define TSTATE_DETACHED (flags_t)1<<1 | 91 | #define FLAG_DETACHED (flags_t)1<<1 |
295 | #define TSTATE_JOINED (flags_t)1<<2 | 92 | #define FLAG_JOINED (flags_t)1<<2 |
296 | #define FLAG_JOIN_LUA (flags_t)1<<3 | 93 | #define FLAG_JOINABLE (flags_t)1<<3 |
297 | 94 | ||
298 | /*At least one flag*/ | 95 | /*At least one flag*/ |
299 | #define FLAG_IS_SET(O, F) (O->flags & (flags_t)(F)) | 96 | #define FLAG_IS_SET(O, F) (O->flags & (flags_t)(F)) |
300 | /*All flags*/ | ||
301 | #define FLAGS_IS_SET(O, F) ((F) == FLAG_IS_SET(O, F)) | ||
302 | #define FLAG_SET(O, F) O->flags |= (flags_t)(F) | 97 | #define FLAG_SET(O, F) O->flags |= (flags_t)(F) |
303 | #define FLAG_UNSET(O, F) O->flags &= ~((flags_t)(F)) | 98 | #define FLAG_UNSET(O, F) O->flags &= ~((flags_t)(F)) |
99 | #define IS(O, F) FLAG_IS_SET(O, FLAG_##F) | ||
100 | #define SET(O, F) FLAG_SET(O, FLAG_##F) | ||
304 | 101 | ||
305 | #define ALLOC_STRUCT(S) (S*)calloc(1, sizeof(S)) | 102 | #define ALLOC_STRUCT(S) (S*)calloc(1, sizeof(S)) |
306 | #define FREE_STRUCT(O) free(O) | 103 | #define FREE_STRUCT(O) free(O) |
@@ -422,7 +219,7 @@ static OS_THREAD_RETURN llthread_child_thread_run(void *arg) { | |||
422 | llthread_log(L, "Error from thread: ", lua_tostring(L, -1)); | 219 | llthread_log(L, "Error from thread: ", lua_tostring(L, -1)); |
423 | } | 220 | } |
424 | 221 | ||
425 | if(FLAG_IS_SET(this, TSTATE_DETACHED) || !FLAG_IS_SET(this, FLAG_JOIN_LUA)) { | 222 | if(IS(this, DETACHED) || !IS(this, JOINABLE)) { |
426 | /* thread is detached, so it must clean-up the child state. */ | 223 | /* thread is detached, so it must clean-up the child state. */ |
427 | llthread_child_destroy(this); | 224 | llthread_child_destroy(this); |
428 | this = NULL; | 225 | this = NULL; |
@@ -450,15 +247,15 @@ static void llthread_validate(llthread_t *this){ | |||
450 | /* describe valid state of llthread_t object | 247 | /* describe valid state of llthread_t object |
451 | * from after create and before destroy | 248 | * from after create and before destroy |
452 | */ | 249 | */ |
453 | if(!FLAGS_IS_SET(this, TSTATE_STARTED)){ | 250 | if(!IS(this, STARTED)){ |
454 | assert(!FLAGS_IS_SET(this, TSTATE_DETACHED)); | 251 | assert(!IS(this, DETACHED)); |
455 | assert(!FLAGS_IS_SET(this, TSTATE_JOINED)); | 252 | assert(!IS(this, JOINED)); |
456 | assert(!FLAGS_IS_SET(this, FLAG_JOIN_LUA)); | 253 | assert(!IS(this, JOINABLE)); |
457 | return; | 254 | return; |
458 | } | 255 | } |
459 | 256 | ||
460 | if(FLAGS_IS_SET(this, TSTATE_DETACHED)){ | 257 | if(IS(this, DETACHED)){ |
461 | if(!FLAGS_IS_SET(this, FLAG_JOIN_LUA)) assert(this->child == NULL); | 258 | if(!IS(this, JOINABLE)) assert(this->child == NULL); |
462 | else assert(this->child != NULL); | 259 | else assert(this->child != NULL); |
463 | } | 260 | } |
464 | } | 261 | } |
@@ -471,7 +268,7 @@ static llthread_t *llthread_new() { | |||
471 | llthread_t *this = ALLOC_STRUCT(llthread_t); | 268 | llthread_t *this = ALLOC_STRUCT(llthread_t); |
472 | if(!this) return NULL; | 269 | if(!this) return NULL; |
473 | 270 | ||
474 | this->flags = TSTATE_NONE; | 271 | this->flags = FLAG_NONE; |
475 | #ifndef USE_PTHREAD | 272 | #ifndef USE_PTHREAD |
476 | this->thread = INVALID_THREAD; | 273 | this->thread = INVALID_THREAD; |
477 | #endif | 274 | #endif |
@@ -493,28 +290,36 @@ static void llthread_cleanup_child(llthread_t *this) { | |||
493 | 290 | ||
494 | static void llthread_destroy(llthread_t *this) { | 291 | static void llthread_destroy(llthread_t *this) { |
495 | do{ | 292 | do{ |
496 | if(!FLAG_IS_SET(this, TSTATE_STARTED)){ | 293 | /* thread not started */ |
294 | if(!IS(this, STARTED)){ | ||
497 | llthread_cleanup_child(this); | 295 | llthread_cleanup_child(this); |
498 | break; | 296 | break; |
499 | } | 297 | } |
500 | if(!FLAG_IS_SET(this, FLAG_JOIN_LUA)) break; | 298 | |
501 | if( FLAG_IS_SET(this, TSTATE_DETACHED)){ | 299 | /* DETACHED */ |
502 | llthread_detach(this); | 300 | if(IS(this, DETACHED)){ |
301 | if(IS(this, JOINABLE)){ | ||
302 | llthread_detach(this); | ||
303 | } | ||
503 | break; | 304 | break; |
504 | } | 305 | } |
505 | 306 | ||
506 | if(!FLAG_IS_SET(this, TSTATE_JOINED)){ | 307 | /* ATACHED */ |
507 | /* @todo log warning about lost thread object for debug? */ | 308 | if(!IS(this, JOINED)){ |
508 | llthread_child_t *child = this->child; | ||
509 | llthread_join(this, INFINITE_JOIN_TIMEOUT); | 309 | llthread_join(this, INFINITE_JOIN_TIMEOUT); |
510 | if(child && child->status != 0) { | 310 | if(!IS(this, JOINED)){ |
511 | /*@fixme remove redundant log*/ | 311 | /* @todo use current lua state to logging */ |
512 | llthread_log(child->L, "Error from non-joined thread: ", lua_tostring(child->L, -1)); | 312 | /* |
313 | * char buf[ERROR_LEN]; | ||
314 | * strerror_r(errno, buf, ERROR_LEN); | ||
315 | * llthread_log(L, "Error can not join thread on gc: ", buf); | ||
316 | */ | ||
513 | } | 317 | } |
514 | } | 318 | } |
319 | if(IS(this, JOINABLE)){ | ||
320 | llthread_cleanup_child(this); | ||
321 | } | ||
515 | 322 | ||
516 | assert(FLAG_IS_SET(this, TSTATE_JOINED)); | ||
517 | llthread_cleanup_child(this); | ||
518 | }while(0); | 323 | }while(0); |
519 | 324 | ||
520 | FREE_STRUCT(this); | 325 | FREE_STRUCT(this); |
@@ -531,11 +336,11 @@ static int llthread_push_results(lua_State *L, llthread_child_t *child, int idx, | |||
531 | static int llthread_detach(llthread_t *this){ | 336 | static int llthread_detach(llthread_t *this){ |
532 | int rc = 0; | 337 | int rc = 0; |
533 | 338 | ||
534 | assert(FLAGS_IS_SET(this, TSTATE_STARTED)); | 339 | assert(IS(this, STARTED)); |
535 | assert(this->child != NULL); | 340 | assert(this->child != NULL); |
536 | 341 | ||
537 | /*we can not deatach joined thread*/ | 342 | /*we can not detach joined thread*/ |
538 | if(FLAGS_IS_SET(this, TSTATE_JOINED)) | 343 | if(IS(this, JOINED)) |
539 | return 0; | 344 | return 0; |
540 | 345 | ||
541 | this->child = NULL; | 346 | this->child = NULL; |
@@ -549,24 +354,24 @@ static int llthread_detach(llthread_t *this){ | |||
549 | return rc; | 354 | return rc; |
550 | } | 355 | } |
551 | 356 | ||
552 | /* | detached | join_lua || return values | which thread | gc calls | detach on | | 357 | /* | detached | joinable || join | which thread | gc | detach | |
553 | * | | || thread:join() | closes lua state | | | | 358 | * | | || return | destroy child | calls | on | |
554 | * ------------------------------------------------------------------------------------- | 359 | * ------------------------------------------------------------------------ |
555 | * | false | falas || <NONE> | child | <NONE> | <NEVER> | | 360 | * | false | falas || <NONE> | child | join | <NEVER> | |
556 | * *| false | true || Lua values | parent | join | <NEVER> | | 361 | * *| false | true || Lua values | parent | join | <NEVER> | |
557 | * *| true | false || <ERROR> | child | <NONE> | start | | 362 | * *| true | false || <ERROR> | child | <NONE> | start | |
558 | * | true | true || <NONE> | child | detach | gc | | 363 | * | true | true || <NONE> | child | detach | gc | |
559 | * ------------------------------------------------------------------------------------- | 364 | * ------------------------------------------------------------------------ |
560 | * * llthread behavior. | 365 | * * llthread behavior. |
561 | */ | 366 | */ |
562 | static int llthread_start(llthread_t *this, int start_detached, int join_lua) { | 367 | static int llthread_start(llthread_t *this, int start_detached, int joinable) { |
563 | llthread_child_t *child = this->child; | 368 | llthread_child_t *child = this->child; |
564 | int rc = 0; | 369 | int rc = 0; |
565 | 370 | ||
566 | llthread_validate(this); | 371 | llthread_validate(this); |
567 | 372 | ||
568 | if(join_lua) FLAG_SET(child, FLAG_JOIN_LUA); | 373 | if(joinable) SET(child, JOINABLE); |
569 | if(start_detached) FLAG_SET(child, TSTATE_DETACHED); | 374 | if(start_detached) SET(child, DETACHED); |
570 | 375 | ||
571 | #ifndef USE_PTHREAD | 376 | #ifndef USE_PTHREAD |
572 | this->thread = (HANDLE)_beginthreadex(NULL, 0, llthread_child_thread_run, child, 0, NULL); | 377 | this->thread = (HANDLE)_beginthreadex(NULL, 0, llthread_child_thread_run, child, 0, NULL); |
@@ -578,10 +383,10 @@ static int llthread_start(llthread_t *this, int start_detached, int join_lua) { | |||
578 | #endif | 383 | #endif |
579 | 384 | ||
580 | if(rc == 0) { | 385 | if(rc == 0) { |
581 | FLAG_SET(this, TSTATE_STARTED); | 386 | SET(this, STARTED); |
582 | if(join_lua) FLAG_SET(this, FLAG_JOIN_LUA); | 387 | if(joinable) SET(this, JOINABLE); |
583 | if(start_detached) FLAG_SET(this, TSTATE_DETACHED); | 388 | if(start_detached) SET(this, DETACHED); |
584 | if((start_detached)&&(!join_lua)){ | 389 | if((start_detached)&&(!joinable)){ |
585 | rc = llthread_detach(this); | 390 | rc = llthread_detach(this); |
586 | } | 391 | } |
587 | } | 392 | } |
@@ -594,7 +399,7 @@ static int llthread_start(llthread_t *this, int start_detached, int join_lua) { | |||
594 | static int llthread_join(llthread_t *this, join_timeout_t timeout) { | 399 | static int llthread_join(llthread_t *this, join_timeout_t timeout) { |
595 | llthread_validate(this); | 400 | llthread_validate(this); |
596 | 401 | ||
597 | if(FLAG_IS_SET(this, TSTATE_JOINED)){ | 402 | if(IS(this, JOINED)){ |
598 | return JOIN_OK; | 403 | return JOIN_OK; |
599 | } else{ | 404 | } else{ |
600 | #ifndef USE_PTHREAD | 405 | #ifndef USE_PTHREAD |
@@ -604,7 +409,7 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) { | |||
604 | if( ret == WAIT_OBJECT_0){ /* Destroy the thread object. */ | 409 | if( ret == WAIT_OBJECT_0){ /* Destroy the thread object. */ |
605 | CloseHandle( this->thread ); | 410 | CloseHandle( this->thread ); |
606 | this->thread = INVALID_THREAD; | 411 | this->thread = INVALID_THREAD; |
607 | FLAG_SET(this, TSTATE_JOINED); | 412 | SET(this, JOINED); |
608 | 413 | ||
609 | llthread_validate(this); | 414 | llthread_validate(this); |
610 | 415 | ||
@@ -635,7 +440,7 @@ static int llthread_join(llthread_t *this, join_timeout_t timeout) { | |||
635 | /* then join the thread. */ | 440 | /* then join the thread. */ |
636 | rc = pthread_join(this->thread, NULL); | 441 | rc = pthread_join(this->thread, NULL); |
637 | if((rc == 0) || (rc == ESRCH)) { | 442 | if((rc == 0) || (rc == ESRCH)) { |
638 | FLAG_SET(this, TSTATE_JOINED); | 443 | SET(this, JOINED); |
639 | rc = JOIN_OK; | 444 | rc = JOIN_OK; |
640 | } | 445 | } |
641 | 446 | ||
@@ -700,16 +505,16 @@ static int l_llthread_delete(lua_State *L) { | |||
700 | static int l_llthread_start(lua_State *L) { | 505 | static int l_llthread_start(lua_State *L) { |
701 | llthread_t *this = l_llthread_at(L, 1); | 506 | llthread_t *this = l_llthread_at(L, 1); |
702 | int start_detached = lua_toboolean(L, 2); | 507 | int start_detached = lua_toboolean(L, 2); |
703 | int join_lua, rc; | 508 | int joinable, rc; |
704 | 509 | ||
705 | if(!lua_isnone(L, 3)) join_lua = lua_toboolean(L, 3); | 510 | if(!lua_isnone(L, 3)) joinable = lua_toboolean(L, 3); |
706 | else join_lua = start_detached ? 0 : 1; | 511 | else joinable = start_detached ? 0 : 1; |
707 | 512 | ||
708 | if(FLAG_IS_SET(this, TSTATE_STARTED)) { | 513 | if(IS(this, STARTED)) { |
709 | return fail(L, "Thread already started."); | 514 | return fail(L, "Thread already started."); |
710 | } | 515 | } |
711 | 516 | ||
712 | rc = llthread_start(this, start_detached, join_lua); | 517 | rc = llthread_start(this, start_detached, joinable); |
713 | if(rc != 0) { | 518 | if(rc != 0) { |
714 | char buf[ERROR_LEN]; | 519 | char buf[ERROR_LEN]; |
715 | strerror_r(errno, buf, ERROR_LEN); | 520 | strerror_r(errno, buf, ERROR_LEN); |
@@ -725,27 +530,28 @@ static int l_llthread_join(lua_State *L) { | |||
725 | llthread_child_t *child = this->child; | 530 | llthread_child_t *child = this->child; |
726 | int rc; | 531 | int rc; |
727 | 532 | ||
728 | if(!FLAG_IS_SET(this, TSTATE_STARTED )) { | 533 | if(!IS(this, STARTED )) { |
729 | return fail(L, "Can't join a thread that hasn't be started."); | 534 | return fail(L, "Can't join a thread that hasn't be started."); |
730 | } | 535 | } |
731 | if( FLAG_IS_SET(this, TSTATE_DETACHED) && !FLAG_IS_SET(this, FLAG_JOIN_LUA)) { | 536 | if( IS(this, DETACHED) && !IS(this, JOINABLE)) { |
732 | return fail(L, "Can't join a thread that has been detached."); | 537 | return fail(L, "Can't join a thread that has been detached."); |
733 | } | 538 | } |
734 | if( FLAG_IS_SET(this, TSTATE_JOINED )) { | 539 | if( IS(this, JOINED )) { |
735 | return fail(L, "Can't join a thread that has already been joined."); | 540 | return fail(L, "Can't join a thread that has already been joined."); |
736 | } | 541 | } |
737 | 542 | ||
738 | /* join the thread. */ | 543 | /* join the thread. */ |
739 | rc = llthread_join(this, luaL_optint(L, 2, INFINITE_JOIN_TIMEOUT)); | 544 | rc = llthread_join(this, luaL_optint(L, 2, INFINITE_JOIN_TIMEOUT)); |
740 | 545 | ||
741 | if(child && FLAG_IS_SET(this, TSTATE_JOINED)) { | 546 | if(child && IS(this, JOINED)) { |
742 | int top; | 547 | int top; |
743 | 548 | ||
744 | if(FLAG_IS_SET(this, TSTATE_DETACHED) || !FLAG_IS_SET(this, FLAG_JOIN_LUA)){ | 549 | if(IS(this, DETACHED) || !IS(this, JOINABLE)){ |
745 | /*child lua state has been destroyed by child thread*/ | 550 | /*child lua state has been destroyed by child thread*/ |
746 | /*@todo return thread exit code*/ | 551 | /*@todo return thread exit code*/ |
552 | lua_pushboolean(L, 1); | ||
747 | lua_pushnumber(L, 0); | 553 | lua_pushnumber(L, 0); |
748 | return 1; | 554 | return 2; |
749 | } | 555 | } |
750 | 556 | ||
751 | /* copy values from child lua state */ | 557 | /* copy values from child lua state */ |