diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | docs/index.html | 18 | ||||
-rw-r--r-- | src/keeper.c | 9 | ||||
-rw-r--r-- | src/lanes.c | 68 | ||||
-rw-r--r-- | src/threading.c | 12 | ||||
-rw-r--r-- | src/threading.h | 12 | ||||
-rw-r--r-- | src/tools.c | 9 | ||||
-rw-r--r-- | src/tools.h | 11 |
8 files changed, 105 insertions, 40 deletions
@@ -1,5 +1,11 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 85: BGe 28-Nov-13 | ||
4 | * version 3.7.3 | ||
5 | * set pthread thread cancel type to PTHREAD_CANCEL_ASYNCHRONOUS | ||
6 | * lane_h:cancel() accepts a 3rd timeout argument used when waiting for actual thread termination (hitting the timeout raises an error) | ||
7 | * added PROPAGATE_ALLOCF macro to select state creation mode (lua_newstate or luaL_newstate) | ||
8 | |||
3 | CHANGE 84: BGe 18-Nov-13 | 9 | CHANGE 84: BGe 18-Nov-13 |
4 | * Fix a deadlock when GCing during a linda operation. | 10 | * Fix a deadlock when GCing during a linda operation. |
5 | * Fix a compilation warning about an unused variable | 11 | * Fix a compilation warning about an unused variable |
diff --git a/docs/index.html b/docs/index.html index 40930d8..25f9e22 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -70,7 +70,7 @@ | |||
70 | </p> | 70 | </p> |
71 | 71 | ||
72 | <p> | 72 | <p> |
73 | This document was revised on 16-Nov-13, and applies to version <tt>3.7.2</tt>. | 73 | This document was revised on 28-Nov-13, and applies to version <tt>3.7.3</tt>. |
74 | </p> | 74 | </p> |
75 | </font> | 75 | </font> |
76 | </center> | 76 | </center> |
@@ -102,7 +102,7 @@ | |||
102 | <li>Data passing uses fast inter-state copies (no serialization required).</li> | 102 | <li>Data passing uses fast inter-state copies (no serialization required).</li> |
103 | <li>"Deep userdata" concept, for sharing userdata over multiple lanes.</li> | 103 | <li>"Deep userdata" concept, for sharing userdata over multiple lanes.</li> |
104 | <li>Millisecond level timers, integrated with the Linda system.</li> | 104 | <li>Millisecond level timers, integrated with the Linda system.</li> |
105 | <li>Threads can be given priorities -2..+2 (default is 0).</li> | 105 | <li>Threads can be given priorities.</li> |
106 | <li>Lanes are cancellable, with proper cleanup.</li> | 106 | <li>Lanes are cancellable, with proper cleanup.</li> |
107 | <li>No Lua-side application level locking - ever!</li> | 107 | <li>No Lua-side application level locking - ever!</li> |
108 | </ul> | 108 | </ul> |
@@ -587,9 +587,10 @@ | |||
587 | <td> | 587 | <td> |
588 | <code>.priority</code> | 588 | <code>.priority</code> |
589 | </td> | 589 | </td> |
590 | <td> integer -2..+2</td> | 590 | <td>integer</td> |
591 | <td> | 591 | <td> |
592 | The priority of lanes generated. -2 is lowest, +2 is highest. | 592 | The priority of lanes generated in the range -3..+3 (MinGW pthread and Windows thread API), or -2..+2 otherwise (default is 0). |
593 | These values are a mapping over the actual priority range of the underlying implementation. | ||
593 | <br> | 594 | <br> |
594 | Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode. | 595 | Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode. |
595 | </td> | 596 | </td> |
@@ -842,14 +843,15 @@ | |||
842 | <h2 id="cancelling">Cancelling</h2> | 843 | <h2 id="cancelling">Cancelling</h2> |
843 | 844 | ||
844 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 845 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
845 | bool[,reason] = lane_h:cancel( [timeout_secs=0.0,] [force_kill_bool = false] ) | 846 | bool[,reason] = lane_h:cancel( [timeout_secs=0.0,] [force_kill_bool = false] [, forcekill_timeout=0.0]) |
846 | </pre></td></tr></table> | 847 | </pre></td></tr></table> |
847 | 848 | ||
848 | <p> | 849 | <p> |
849 | <tt>cancel()</tt>sends a cancellation request to the lane.<br/> | 850 | <tt>cancel()</tt> sends a cancellation request to the lane.<br/> |
851 | If <tt>timeout_secs</tt> is negative (aka "soft cancel"), starting with version 3.6.3, will only cause <tt>cancel_test()</tt> to return <tt>true</tt>, so that the lane can cleanup manually (the actual value is irrelevant). You can't provide the additional arguments in that case.<br/> | ||
850 | If <tt>timeout_secs</tt> is positive (aka "hard cancel"), waits for the request to be processed, or a timeout to occur.<br/> | 852 | If <tt>timeout_secs</tt> is positive (aka "hard cancel"), waits for the request to be processed, or a timeout to occur.<br/> |
851 | If <tt>timeout_secs</tt> is negative (aka "soft cancel"), starting with version 3.6.3, will only cause <tt>cancel_test()</tt> to return true, so that the lane can cleanup manually. You can't provide a second argument in that case.<br/> | 853 | If <tt>force_kill_bool</tt> is <tt>true</tt>, <tt>forcekill_timeout</tt> can be set to tell how long lanes will wait for the OS thread to terminate before raising an error. Windows threads always terminate immediately, but it might not always be the case with some pthread implementations. |
852 | Returns <tt>true</tt> if soft cancelling, or the lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within timeout period. | 854 | Returns <tt>true</tt> if soft cancelling, or the lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within <tt>timeout_secs</tt> timeout period. |
853 | </p> | 855 | </p> |
854 | 856 | ||
855 | <p> | 857 | <p> |
diff --git a/src/keeper.c b/src/keeper.c index 8da3c08..99f510b 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
@@ -567,8 +567,7 @@ void close_keepers( void) | |||
567 | char const* init_keepers( lua_State* L) | 567 | char const* init_keepers( lua_State* L) |
568 | { | 568 | { |
569 | int i; | 569 | int i; |
570 | void* allocUD; | 570 | PROPAGATE_ALLOCF_PREP( L); |
571 | lua_Alloc allocF = lua_getallocf( L, &allocUD); | ||
572 | 571 | ||
573 | STACK_CHECK( L); | 572 | STACK_CHECK( L); |
574 | lua_getfield( L, 1, "nb_keepers"); | 573 | lua_getfield( L, 1, "nb_keepers"); |
@@ -580,10 +579,10 @@ char const* init_keepers( lua_State* L) | |||
580 | GKeepers = malloc( GNbKeepers * sizeof( struct s_Keeper)); | 579 | GKeepers = malloc( GNbKeepers * sizeof( struct s_Keeper)); |
581 | for( i = 0; i < GNbKeepers; ++ i) | 580 | for( i = 0; i < GNbKeepers; ++ i) |
582 | { | 581 | { |
583 | lua_State* K = lua_newstate( allocF, allocUD); | 582 | lua_State* K = PROPAGATE_ALLOCF_ALLOC(); |
584 | if( K == NULL) | 583 | if( K == NULL) |
585 | { | 584 | { |
586 | (void) luaL_error( L, "'lua_newstate()' failed while creating keeper state; out of memory"); | 585 | (void) luaL_error( L, "init_keepers() failed while creating keeper state; out of memory"); |
587 | } | 586 | } |
588 | STACK_CHECK( K); | 587 | STACK_CHECK( K); |
589 | 588 | ||
@@ -627,7 +626,7 @@ struct s_Keeper* keeper_acquire( void const* ptr) | |||
627 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer | 626 | * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer |
628 | */ | 627 | */ |
629 | unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers); | 628 | unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers); |
630 | struct s_Keeper* K = &GKeepers[i]; | 629 | struct s_Keeper *K= &GKeepers[i]; |
631 | 630 | ||
632 | MUTEX_LOCK( &K->lock_); | 631 | MUTEX_LOCK( &K->lock_); |
633 | //++ K->count; | 632 | //++ K->count; |
diff --git a/src/lanes.c b/src/lanes.c index 53ed5e4..9e32f9a 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -52,7 +52,7 @@ | |||
52 | * ... | 52 | * ... |
53 | */ | 53 | */ |
54 | 54 | ||
55 | char const* VERSION = "3.7.2"; | 55 | char const* VERSION = "3.7.3"; |
56 | 56 | ||
57 | /* | 57 | /* |
58 | =============================================================================== | 58 | =============================================================================== |
@@ -1197,7 +1197,7 @@ typedef enum | |||
1197 | CR_Killed | 1197 | CR_Killed |
1198 | } cancel_result; | 1198 | } cancel_result; |
1199 | 1199 | ||
1200 | static cancel_result thread_cancel( struct s_lane *s, double secs, bool_t force) | 1200 | static cancel_result thread_cancel( lua_State* L, struct s_lane* s, double secs, bool_t force, double waitkill_timeout_) |
1201 | { | 1201 | { |
1202 | cancel_result result; | 1202 | cancel_result result; |
1203 | 1203 | ||
@@ -1239,6 +1239,15 @@ static cancel_result thread_cancel( struct s_lane *s, double secs, bool_t force) | |||
1239 | // PThread seems to have). | 1239 | // PThread seems to have). |
1240 | // | 1240 | // |
1241 | THREAD_KILL( &s->thread); | 1241 | THREAD_KILL( &s->thread); |
1242 | #if THREADAPI == THREADAPI_PTHREAD | ||
1243 | // pthread: make sure the thread is really stopped! | ||
1244 | // note that this may block forever if the lane doesn't call a cancellation point and pthread doesn't honor PTHREAD_CANCEL_ASYNCHRONOUS | ||
1245 | result = THREAD_WAIT( &s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status); | ||
1246 | if( result == CR_Timeout) | ||
1247 | { | ||
1248 | return luaL_error( L, "force-killed lane failed to terminate within %f second%s", waitkill_timeout_, waitkill_timeout_ > 1 ? "s" : ""); | ||
1249 | } | ||
1250 | #endif // THREADAPI == THREADAPI_PTHREAD | ||
1242 | s->mstatus = KILLED; // mark 'gc' to wait for it | 1251 | s->mstatus = KILLED; // mark 'gc' to wait for it |
1243 | // note that s->status value must remain to whatever it was at the time of the kill | 1252 | // note that s->status value must remain to whatever it was at the time of the kill |
1244 | // because we need to know if we can lua_close() the Lua State or not. | 1253 | // because we need to know if we can lua_close() the Lua State or not. |
@@ -1357,7 +1366,7 @@ static int selfdestruct_gc( lua_State* L) | |||
1357 | while( s != SELFDESTRUCT_END) | 1366 | while( s != SELFDESTRUCT_END) |
1358 | { | 1367 | { |
1359 | // attempt a regular unforced hard cancel with a small timeout | 1368 | // attempt a regular unforced hard cancel with a small timeout |
1360 | bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( s, 0.0001, FALSE); | 1369 | bool_t cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, 0.0001, FALSE, 0.0); |
1361 | // if we failed, and we know the thread is waiting on a linda | 1370 | // if we failed, and we know the thread is waiting on a linda |
1362 | if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL) | 1371 | if( cancelled == FALSE && s->status == WAITING && s->waiting_on != NULL) |
1363 | { | 1372 | { |
@@ -1758,6 +1767,17 @@ static char const* get_errcode_name( int _code) | |||
1758 | } | 1767 | } |
1759 | #endif // USE_DEBUG_SPEW | 1768 | #endif // USE_DEBUG_SPEW |
1760 | 1769 | ||
1770 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR // implies THREADAPI == THREADAPI_PTHREAD | ||
1771 | static void thread_cleanup_handler( void* opaque) | ||
1772 | { | ||
1773 | struct s_lane* s= (struct s_lane*) opaque; | ||
1774 | MUTEX_LOCK( &s->done_lock); | ||
1775 | s->status = CANCELLED; | ||
1776 | SIGNAL_ONE( &s->done_signal); // wake up master (while 's->done_lock' is on) | ||
1777 | MUTEX_UNLOCK( &s->done_lock); | ||
1778 | } | ||
1779 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
1780 | |||
1761 | //--- | 1781 | //--- |
1762 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | 1782 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) |
1763 | { | 1783 | { |
@@ -1770,7 +1790,8 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
1770 | tracking_add( s); | 1790 | tracking_add( s); |
1771 | } | 1791 | } |
1772 | #endif // HAVE_LANE_TRACKING | 1792 | #endif // HAVE_LANE_TRACKING |
1773 | 1793 | THREAD_MAKE_ASYNCH_CANCELLABLE(); | |
1794 | THREAD_CLEANUP_PUSH( thread_cleanup_handler, s); | ||
1774 | s->status= RUNNING; // PENDING -> RUNNING | 1795 | s->status= RUNNING; // PENDING -> RUNNING |
1775 | 1796 | ||
1776 | // Tie "set_finalizer()" to the state | 1797 | // Tie "set_finalizer()" to the state |
@@ -1888,7 +1909,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
1888 | : ERROR_ST; | 1909 | : ERROR_ST; |
1889 | 1910 | ||
1890 | // Posix no PTHREAD_TIMEDJOIN: | 1911 | // Posix no PTHREAD_TIMEDJOIN: |
1891 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change | 1912 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change |
1892 | // | 1913 | // |
1893 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR | 1914 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
1894 | MUTEX_LOCK( &s->done_lock); | 1915 | MUTEX_LOCK( &s->done_lock); |
@@ -1901,6 +1922,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) | |||
1901 | MUTEX_UNLOCK( &s->done_lock); | 1922 | MUTEX_UNLOCK( &s->done_lock); |
1902 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR | 1923 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
1903 | } | 1924 | } |
1925 | THREAD_CLEANUP_POP( FALSE); | ||
1904 | return 0; // ignored | 1926 | return 0; // ignored |
1905 | } | 1927 | } |
1906 | 1928 | ||
@@ -2248,6 +2270,7 @@ LUAG_FUNC( thread_gc) | |||
2248 | return 0; | 2270 | return 0; |
2249 | } | 2271 | } |
2250 | 2272 | ||
2273 | // lane_h:cancel( [timeout,] force[, forcekill_timeout]) | ||
2251 | LUAG_FUNC( thread_cancel) | 2274 | LUAG_FUNC( thread_cancel) |
2252 | { | 2275 | { |
2253 | if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA) | 2276 | if( lua_gettop( L) < 1 || lua_type( L, 1) != LUA_TUSERDATA) |
@@ -2258,9 +2281,8 @@ LUAG_FUNC( thread_cancel) | |||
2258 | { | 2281 | { |
2259 | struct s_lane* s = lua_toLane( L, 1); | 2282 | struct s_lane* s = lua_toLane( L, 1); |
2260 | double secs = 0.0; | 2283 | double secs = 0.0; |
2261 | uint_t force_i = 2; | 2284 | int force_i = 2; |
2262 | cancel_result result; | 2285 | int forcekill_timeout_i = 3; |
2263 | bool_t force; | ||
2264 | 2286 | ||
2265 | if( lua_isnumber( L, 2)) | 2287 | if( lua_isnumber( L, 2)) |
2266 | { | 2288 | { |
@@ -2270,30 +2292,34 @@ LUAG_FUNC( thread_cancel) | |||
2270 | return luaL_error( L, "can't force a soft cancel"); | 2292 | return luaL_error( L, "can't force a soft cancel"); |
2271 | } | 2293 | } |
2272 | ++ force_i; | 2294 | ++ force_i; |
2295 | ++ forcekill_timeout_i; | ||
2273 | } | 2296 | } |
2274 | else if( lua_isnil( L, 2)) | 2297 | else if( lua_isnil( L, 2)) |
2275 | { | 2298 | { |
2276 | ++ force_i; | 2299 | ++ force_i; |
2300 | ++ forcekill_timeout_i; | ||
2277 | } | 2301 | } |
2278 | 2302 | ||
2279 | force = lua_toboolean( L, force_i); // FALSE if nothing there | ||
2280 | |||
2281 | result = thread_cancel( s, secs, force); | ||
2282 | switch( result) | ||
2283 | { | 2303 | { |
2304 | bool_t force = lua_toboolean( L, force_i); // FALSE if nothing there | ||
2305 | double forcekill_timeout = luaL_optnumber( L, forcekill_timeout_i, 0.0); | ||
2306 | |||
2307 | switch( thread_cancel( L, s, secs, force, forcekill_timeout)) | ||
2308 | { | ||
2284 | case CR_Timeout: | 2309 | case CR_Timeout: |
2285 | lua_pushboolean( L, 0); | 2310 | lua_pushboolean( L, 0); |
2286 | lua_pushstring( L, "timeout"); | 2311 | lua_pushstring( L, "timeout"); |
2287 | return 2; | 2312 | return 2; |
2288 | 2313 | ||
2289 | case CR_Cancelled: | 2314 | case CR_Cancelled: |
2290 | lua_pushboolean( L, 1); | 2315 | lua_pushboolean( L, 1); |
2291 | return 1; | 2316 | return 1; |
2292 | 2317 | ||
2293 | case CR_Killed: | 2318 | case CR_Killed: |
2294 | lua_pushboolean( L, 0); | 2319 | lua_pushboolean( L, 0); |
2295 | lua_pushstring( L, "killed"); | 2320 | lua_pushstring( L, "killed"); |
2296 | return 2; | 2321 | return 2; |
2322 | } | ||
2297 | } | 2323 | } |
2298 | } | 2324 | } |
2299 | // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value" | 2325 | // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value" |
diff --git a/src/threading.c b/src/threading.c index 63c39ae..ad5b473 100644 --- a/src/threading.c +++ b/src/threading.c | |||
@@ -330,6 +330,8 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) | |||
330 | *ref= NULL; | 330 | *ref= NULL; |
331 | } | 331 | } |
332 | 332 | ||
333 | void THREAD_MAKE_ASYNCH_CANCELLABLE() {} // nothing to do for windows threads, we can cancel them anytime we want | ||
334 | |||
333 | #if !defined __GNUC__ | 335 | #if !defined __GNUC__ |
334 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx | 336 | //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx |
335 | #define MS_VC_EXCEPTION 0x406D1388 | 337 | #define MS_VC_EXCEPTION 0x406D1388 |
@@ -896,11 +898,19 @@ bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T * | |||
896 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR | 898 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
897 | return done; | 899 | return done; |
898 | } | 900 | } |
899 | // | 901 | // |
900 | void THREAD_KILL( THREAD_T *ref ) { | 902 | void THREAD_KILL( THREAD_T *ref ) { |
901 | pthread_cancel( *ref ); | 903 | pthread_cancel( *ref ); |
902 | } | 904 | } |
903 | 905 | ||
906 | void THREAD_MAKE_ASYNCH_CANCELLABLE() | ||
907 | { | ||
908 | // that's the default, but just in case... | ||
909 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); | ||
910 | // we want cancellation to take effect immediately if possible, instead of waiting for a cancellation point (which is the default) | ||
911 | pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL); | ||
912 | } | ||
913 | |||
904 | void THREAD_SETNAME( char const* _name) | 914 | void THREAD_SETNAME( char const* _name) |
905 | { | 915 | { |
906 | // exact API to set the thread name is platform-dependant | 916 | // exact API to set the thread name is platform-dependant |
diff --git a/src/threading.h b/src/threading.h index aa34248..4b28ce8 100644 --- a/src/threading.h +++ b/src/threading.h | |||
@@ -194,10 +194,16 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
194 | # define THREAD_PRIO_MIN (-3) | 194 | # define THREAD_PRIO_MIN (-3) |
195 | # define THREAD_PRIO_MAX (+3) | 195 | # define THREAD_PRIO_MAX (+3) |
196 | 196 | ||
197 | #define THREAD_CLEANUP_PUSH( cb_, val_) | ||
198 | #define THREAD_CLEANUP_POP( execute_) | ||
199 | |||
197 | #else // THREADAPI == THREADAPI_PTHREAD | 200 | #else // THREADAPI == THREADAPI_PTHREAD |
198 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler | 201 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler |
199 | * implementation. Others will use a condition variable. | 202 | * implementation. Others will use a condition variable. |
200 | */ | 203 | */ |
204 | #if defined __WINPTHREADS_VERSION | ||
205 | #define USE_PTHREAD_TIMEDJOIN | ||
206 | #endif // __WINPTHREADS_VERSION | ||
201 | # ifdef USE_PTHREAD_TIMEDJOIN | 207 | # ifdef USE_PTHREAD_TIMEDJOIN |
202 | # ifdef PLATFORM_OSX | 208 | # ifdef PLATFORM_OSX |
203 | # error "No 'pthread_timedjoin()' on this system" | 209 | # error "No 'pthread_timedjoin()' on this system" |
@@ -229,6 +235,9 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
229 | # define THREAD_PRIO_MIN (-2) | 235 | # define THREAD_PRIO_MIN (-2) |
230 | # define THREAD_PRIO_MAX (+2) | 236 | # define THREAD_PRIO_MAX (+2) |
231 | # endif | 237 | # endif |
238 | |||
239 | #define THREAD_CLEANUP_PUSH( cb_, val_) pthread_cleanup_push( cb_, val_) | ||
240 | #define THREAD_CLEANUP_POP( execute_) pthread_cleanup_pop( execute_) | ||
232 | #endif // THREADAPI == THREADAPI_WINDOWS | 241 | #endif // THREADAPI == THREADAPI_WINDOWS |
233 | 242 | ||
234 | /* | 243 | /* |
@@ -253,7 +262,8 @@ bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs, SIGNAL_T *signal_ref, MUTEX | |||
253 | #define THREAD_WAIT THREAD_WAIT_IMPL | 262 | #define THREAD_WAIT THREAD_WAIT_IMPL |
254 | #endif // // THREADWAIT_METHOD == THREADWAIT_CONDVAR | 263 | #endif // // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
255 | 264 | ||
256 | void THREAD_KILL( THREAD_T *ref ); | 265 | void THREAD_KILL( THREAD_T* ref); |
257 | void THREAD_SETNAME( char const* _name); | 266 | void THREAD_SETNAME( char const* _name); |
267 | void THREAD_MAKE_ASYNCH_CANCELLABLE(); | ||
258 | 268 | ||
259 | #endif // __threading_h__ | 269 | #endif // __threading_h__ |
diff --git a/src/tools.c b/src/tools.c index 754605b..b5f2f4b 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -570,13 +570,14 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
570 | lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) | 570 | lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) |
571 | { | 571 | { |
572 | // reuse alloc function from the originating state | 572 | // reuse alloc function from the originating state |
573 | void* allocUD; | 573 | #if PROPAGATE_ALLOCF |
574 | lua_Alloc allocF = lua_getallocf( _from, &allocUD); | 574 | PROPAGATE_ALLOCF_PREP( _from); |
575 | lua_State* L = lua_newstate( allocF, allocUD); | 575 | #endif // PROPAGATE_ALLOCF |
576 | lua_State* L = PROPAGATE_ALLOCF_ALLOC(); | ||
576 | 577 | ||
577 | if( L == NULL) | 578 | if( L == NULL) |
578 | { | 579 | { |
579 | (void) luaL_error( _from, "'lua_newstate()' failed; out of memory"); | 580 | (void) luaL_error( _from, "luaG_newstate() failed while creating state; out of memory"); |
580 | } | 581 | } |
581 | 582 | ||
582 | // we'll need this everytime we transfer some C function from/to this state | 583 | // we'll need this everytime we transfer some C function from/to this state |
diff --git a/src/tools.h b/src/tools.h index e984ec2..19dca70 100644 --- a/src/tools.h +++ b/src/tools.h | |||
@@ -41,6 +41,17 @@ void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int | |||
41 | #define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0) | 41 | #define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0) |
42 | #endif // LUA_VERSION_NUM == 502 | 42 | #endif // LUA_VERSION_NUM == 502 |
43 | 43 | ||
44 | // For some reason, LuaJIT 64bits doesn't support lua_newstate() | ||
45 | // If you build specifically for this situation, change value to 0 | ||
46 | #define PROPAGATE_ALLOCF 1 | ||
47 | #if PROPAGATE_ALLOCF | ||
48 | #define PROPAGATE_ALLOCF_PREP( L) void* allocUD; lua_Alloc allocF = lua_getallocf( L, &allocUD) | ||
49 | #define PROPAGATE_ALLOCF_ALLOC() lua_newstate( allocF, allocUD) | ||
50 | #else // PROPAGATE_ALLOCF | ||
51 | #define PROPAGATE_ALLOCF_PREP( L) | ||
52 | #define PROPAGATE_ALLOCF_ALLOC() luaL_newstate() | ||
53 | #endif // PROPAGATE_ALLOCF | ||
54 | |||
44 | #define USE_DEBUG_SPEW 0 | 55 | #define USE_DEBUG_SPEW 0 |
45 | #if USE_DEBUG_SPEW | 56 | #if USE_DEBUG_SPEW |
46 | extern char const* debugspew_indent; | 57 | extern char const* debugspew_indent; |