diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2011-11-14 19:41:28 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2011-11-14 19:41:28 +0100 |
| commit | 87431bcc0ece1eaf9305593223bb0c5145004044 (patch) | |
| tree | e1a76ea727e8019d3c26c4829dbb95253dd7e1f6 /src | |
| parent | 1d2b45823fd2a13761bd2d19b1b5a1e8bb11f7b9 (diff) | |
| download | lanes-87431bcc0ece1eaf9305593223bb0c5145004044.tar.gz lanes-87431bcc0ece1eaf9305593223bb0c5145004044.tar.bz2 lanes-87431bcc0ece1eaf9305593223bb0c5145004044.zip | |
* removed packagepath and packagecpath options, replaced by a package table, whose fields path, cpath, loaders, preload are transfered
* code cleanup to facilitate transition between WIN32 and PTHREAD impleentations
* tentative fix for desinit crashes when free running lanes are killed at process shutdown
Diffstat (limited to 'src')
| -rw-r--r-- | src/lanes.c | 161 | ||||
| -rw-r--r-- | src/lanes.lua | 13 | ||||
| -rw-r--r-- | src/threading.c | 54 | ||||
| -rw-r--r-- | src/threading.h | 55 |
4 files changed, 141 insertions, 142 deletions
diff --git a/src/lanes.c b/src/lanes.c index aef1015..40af6c0 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -139,7 +139,7 @@ struct s_lane { | |||
| 139 | // M: sets to FALSE, flags TRUE for cancel request | 139 | // M: sets to FALSE, flags TRUE for cancel request |
| 140 | // S: reads to see if cancel is requested | 140 | // S: reads to see if cancel is requested |
| 141 | 141 | ||
| 142 | #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) | 142 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 143 | SIGNAL_T done_signal_; | 143 | SIGNAL_T done_signal_; |
| 144 | // | 144 | // |
| 145 | // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN) | 145 | // M: Waited upon at lane ending (if Posix with no PTHREAD_TIMEDJOIN) |
| @@ -149,7 +149,7 @@ struct s_lane { | |||
| 149 | // | 149 | // |
| 150 | // Lock required by 'done_signal' condition variable, protecting | 150 | // Lock required by 'done_signal' condition variable, protecting |
| 151 | // lane status changes to DONE/ERROR_ST/CANCELLED. | 151 | // lane status changes to DONE/ERROR_ST/CANCELLED. |
| 152 | #endif | 152 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 153 | 153 | ||
| 154 | volatile enum { | 154 | volatile enum { |
| 155 | NORMAL, // normal master side state | 155 | NORMAL, // normal master side state |
| @@ -1150,9 +1150,17 @@ static int selfdestruct_atexit( lua_State *L) | |||
| 1150 | { | 1150 | { |
| 1151 | struct s_lane *next_s= s->selfdestruct_next; | 1151 | struct s_lane *next_s= s->selfdestruct_next; |
| 1152 | s->selfdestruct_next= NULL; // detach from selfdestruct chain | 1152 | s->selfdestruct_next= NULL; // detach from selfdestruct chain |
| 1153 | if( s->thread) // can be NULL if previous 'soft' termination succeeded | 1153 | if( !THREAD_ISNULL( s->thread)) // can be NULL if previous 'soft' termination succeeded |
| 1154 | { | ||
| 1154 | THREAD_KILL( &s->thread); | 1155 | THREAD_KILL( &s->thread); |
| 1156 | // make sure the thread is really stopped! | ||
| 1157 | THREAD_WAIT( &s->thread, -1, &s->done_signal_, &s->done_lock_, &s->status); | ||
| 1158 | } | ||
| 1155 | // NO lua_close() in this case because we don't know where execution of the state was interrupted | 1159 | // NO lua_close() in this case because we don't know where execution of the state was interrupted |
| 1160 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
| 1161 | SIGNAL_FREE( &s->done_signal_); | ||
| 1162 | MUTEX_FREE( &s->done_lock_); | ||
| 1163 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
| 1156 | free( s); | 1164 | free( s); |
| 1157 | s = next_s; | 1165 | s = next_s; |
| 1158 | n++; | 1166 | n++; |
| @@ -1374,11 +1382,7 @@ LUAG_FUNC( set_debug_threadname) | |||
| 1374 | } | 1382 | } |
| 1375 | 1383 | ||
| 1376 | //--- | 1384 | //--- |
| 1377 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 1385 | static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs) |
| 1378 | static THREAD_RETURN_T __stdcall lane_main( void *vs ) | ||
| 1379 | #else | ||
| 1380 | static THREAD_RETURN_T lane_main( void *vs ) | ||
| 1381 | #endif | ||
| 1382 | { | 1386 | { |
| 1383 | struct s_lane *s= (struct s_lane *)vs; | 1387 | struct s_lane *s= (struct s_lane *)vs; |
| 1384 | int rc, rc2; | 1388 | int rc, rc2; |
| @@ -1475,13 +1479,15 @@ LUAG_FUNC( set_debug_threadname) | |||
| 1475 | lua_close( s->L ); | 1479 | lua_close( s->L ); |
| 1476 | s->L = L = 0; | 1480 | s->L = L = 0; |
| 1477 | 1481 | ||
| 1478 | #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) | 1482 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1479 | SIGNAL_FREE( &s->done_signal_ ); | 1483 | SIGNAL_FREE( &s->done_signal_); |
| 1480 | MUTEX_FREE( &s->done_lock_ ); | 1484 | MUTEX_FREE( &s->done_lock_); |
| 1481 | #endif | 1485 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1482 | free(s); | 1486 | free(s); |
| 1483 | 1487 | ||
| 1484 | } else { | 1488 | } |
| 1489 | else | ||
| 1490 | { | ||
| 1485 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them | 1491 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them |
| 1486 | 1492 | ||
| 1487 | enum e_status st= | 1493 | enum e_status st= |
| @@ -1492,16 +1498,16 @@ LUAG_FUNC( set_debug_threadname) | |||
| 1492 | // Posix no PTHREAD_TIMEDJOIN: | 1498 | // Posix no PTHREAD_TIMEDJOIN: |
| 1493 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change | 1499 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change |
| 1494 | // | 1500 | // |
| 1495 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | 1501 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1496 | s->status= st; | 1502 | MUTEX_LOCK( &s->done_lock_); |
| 1497 | #else | ||
| 1498 | MUTEX_LOCK( &s->done_lock_ ); | ||
| 1499 | { | 1503 | { |
| 1500 | s->status= st; | 1504 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1501 | SIGNAL_ONE( &s->done_signal_ ); // wake up master (while 's->done_lock' is on) | 1505 | s->status = st; |
| 1506 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
| 1507 | SIGNAL_ONE( &s->done_signal_); // wake up master (while 's->done_lock' is on) | ||
| 1502 | } | 1508 | } |
| 1503 | MUTEX_UNLOCK( &s->done_lock_ ); | 1509 | MUTEX_UNLOCK( &s->done_lock_); |
| 1504 | #endif | 1510 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1505 | } | 1511 | } |
| 1506 | return 0; // ignored | 1512 | return 0; // ignored |
| 1507 | } | 1513 | } |
| @@ -1512,7 +1518,7 @@ LUAG_FUNC( set_debug_threadname) | |||
| 1512 | // [cancelstep_uint=0], | 1518 | // [cancelstep_uint=0], |
| 1513 | // [prio_int=0], | 1519 | // [prio_int=0], |
| 1514 | // [globals_tbl], | 1520 | // [globals_tbl], |
| 1515 | // [packagepath], | 1521 | // [package_tbl], |
| 1516 | // [required], | 1522 | // [required], |
| 1517 | // [... args ...] ) | 1523 | // [... args ...] ) |
| 1518 | // | 1524 | // |
| @@ -1553,11 +1559,10 @@ LUAG_FUNC( thread_new ) | |||
| 1553 | uint_t cs= luaG_optunsigned( L, 3,0); | 1559 | uint_t cs= luaG_optunsigned( L, 3,0); |
| 1554 | int prio= (int)luaL_optinteger( L, 4,0); | 1560 | int prio= (int)luaL_optinteger( L, 4,0); |
| 1555 | uint_t glob= luaG_isany(L,5) ? 5:0; | 1561 | uint_t glob= luaG_isany(L,5) ? 5:0; |
| 1556 | uint_t ppath = luaG_isany(L,6) ? 6:0; | 1562 | uint_t package = luaG_isany(L,6) ? 6:0; |
| 1557 | uint_t pcpath = luaG_isany(L,7) ? 7:0; | 1563 | uint_t required = luaG_isany(L,7) ? 7:0; |
| 1558 | uint_t required = luaG_isany(L,8) ? 8:0; | ||
| 1559 | 1564 | ||
| 1560 | #define FIXED_ARGS (8) | 1565 | #define FIXED_ARGS (7) |
| 1561 | uint_t args= lua_gettop(L) - FIXED_ARGS; | 1566 | uint_t args= lua_gettop(L) - FIXED_ARGS; |
| 1562 | 1567 | ||
| 1563 | if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) | 1568 | if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) |
| @@ -1588,46 +1593,35 @@ LUAG_FUNC( thread_new ) | |||
| 1588 | ASSERT_L( lua_gettop(L2) == 0); | 1593 | ASSERT_L( lua_gettop(L2) == 0); |
| 1589 | 1594 | ||
| 1590 | // package.path | 1595 | // package.path |
| 1596 | STACK_CHECK(L) | ||
| 1591 | STACK_CHECK(L2) | 1597 | STACK_CHECK(L2) |
| 1592 | if( ppath) | 1598 | if( package) |
| 1593 | { | ||
| 1594 | if (lua_type(L,ppath) != LUA_TSTRING) | ||
| 1595 | luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath)); | ||
| 1596 | lua_getglobal( L2, "package"); | ||
| 1597 | if( lua_isnil( L2, -1)) // package library not loaded: do nothing | ||
| 1598 | { | ||
| 1599 | lua_pop( L2, 1); | ||
| 1600 | } | ||
| 1601 | else | ||
| 1602 | { | ||
| 1603 | lua_pushvalue( L, ppath); | ||
| 1604 | luaG_inter_move( L, L2, 1); // moves the new path to L2 | ||
| 1605 | lua_setfield( L2, -2, "path"); // set package.path | ||
| 1606 | lua_pop( L2, 1); | ||
| 1607 | } | ||
| 1608 | } | ||
| 1609 | STACK_END(L2,0) | ||
| 1610 | |||
| 1611 | // package.cpath | ||
| 1612 | STACK_CHECK(L2) | ||
| 1613 | if( pcpath) | ||
| 1614 | { | 1599 | { |
| 1615 | if (lua_type(L,pcpath) != LUA_TSTRING) | 1600 | if (lua_type(L,package) != LUA_TTABLE) |
| 1616 | luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath)); | 1601 | luaL_error( L, "expected package as table, got %s", luaG_typename(L,package)); |
| 1617 | lua_getglobal( L2, "package"); | 1602 | lua_getglobal( L2, "package"); |
| 1618 | if( lua_isnil( L2, -1)) // // package library not loaded: do nothing | 1603 | if( !lua_isnil( L2, -1)) // package library not loaded: do nothing |
| 1619 | { | 1604 | { |
| 1620 | lua_pop( L2, 1); | 1605 | int i; |
| 1621 | } | 1606 | char const *entries[] = { "path", "cpath", "preload", "loaders", NULL}; |
| 1622 | else | 1607 | for( i = 0; entries[i]; ++ i) |
| 1623 | { | 1608 | { |
| 1624 | lua_pushvalue( L, pcpath); | 1609 | lua_getfield( L, package, entries[i]); |
| 1625 | luaG_inter_move( L, L2, 1); // moves the new cpath to L2 | 1610 | if( lua_isnil( L, -1)) |
| 1626 | lua_setfield( L2, -2, "cpath"); // set package.cpath | 1611 | { |
| 1627 | lua_pop( L2, 1); | 1612 | lua_pop( L, 1); |
| 1613 | } | ||
| 1614 | else | ||
| 1615 | { | ||
| 1616 | luaG_inter_move( L, L2, 1); // moves the entry to L2 | ||
| 1617 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] | ||
| 1618 | } | ||
| 1619 | } | ||
| 1628 | } | 1620 | } |
| 1621 | lua_pop( L2, 1); | ||
| 1629 | } | 1622 | } |
| 1630 | STACK_END(L2,0) | 1623 | STACK_END(L2,0) |
| 1624 | STACK_END(L,0) | ||
| 1631 | 1625 | ||
| 1632 | // modules to require in the target lane *before* the function is transfered! | 1626 | // modules to require in the target lane *before* the function is transfered! |
| 1633 | 1627 | ||
| @@ -1738,10 +1732,10 @@ LUAG_FUNC( thread_new ) | |||
| 1738 | s->waiting_on = NULL; | 1732 | s->waiting_on = NULL; |
| 1739 | s->cancel_request= FALSE; | 1733 | s->cancel_request= FALSE; |
| 1740 | 1734 | ||
| 1741 | #if !( (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) ) | 1735 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1742 | MUTEX_INIT( &s->done_lock_ ); | 1736 | MUTEX_INIT( &s->done_lock_); |
| 1743 | SIGNAL_INIT( &s->done_signal_ ); | 1737 | SIGNAL_INIT( &s->done_signal_); |
| 1744 | #endif | 1738 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1745 | s->mstatus= NORMAL; | 1739 | s->mstatus= NORMAL; |
| 1746 | s->selfdestruct_next= NULL; | 1740 | s->selfdestruct_next= NULL; |
| 1747 | 1741 | ||
| @@ -1813,6 +1807,7 @@ LUAG_FUNC( thread_gc ) | |||
| 1813 | { | 1807 | { |
| 1814 | // Make sure a kill has proceeded, before cleaning up the data structure. | 1808 | // Make sure a kill has proceeded, before cleaning up the data structure. |
| 1815 | // | 1809 | // |
| 1810 | // NO lua_close() in this case because we don't know where execution of the state was interrupted | ||
| 1816 | // If not doing 'THREAD_WAIT()' we should close the Lua state here | 1811 | // If not doing 'THREAD_WAIT()' we should close the Lua state here |
| 1817 | // (can it be out of order, since we killed the lane abruptly?) | 1812 | // (can it be out of order, since we killed the lane abruptly?) |
| 1818 | // | 1813 | // |
| @@ -1821,11 +1816,7 @@ LUAG_FUNC( thread_gc ) | |||
| 1821 | s->L = 0; | 1816 | s->L = 0; |
| 1822 | #else // 0 | 1817 | #else // 0 |
| 1823 | DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" )); | 1818 | DEBUGEXEC(fprintf( stderr, "** Joining with a killed thread (needs testing) **" )); |
| 1824 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | 1819 | THREAD_WAIT( &s->thread, -1, &s->done_signal_, &s->done_lock_, &s->status); |
| 1825 | THREAD_WAIT( &s->thread, -1 ); | ||
| 1826 | #else | ||
| 1827 | THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, -1 ); | ||
| 1828 | #endif | ||
| 1829 | DEBUGEXEC(fprintf( stderr, "** Joined ok **" )); | 1820 | DEBUGEXEC(fprintf( stderr, "** Joined ok **" )); |
| 1830 | #endif // 0 | 1821 | #endif // 0 |
| 1831 | } | 1822 | } |
| @@ -1837,12 +1828,12 @@ LUAG_FUNC( thread_gc ) | |||
| 1837 | 1828 | ||
| 1838 | // Clean up after a (finished) thread | 1829 | // Clean up after a (finished) thread |
| 1839 | // | 1830 | // |
| 1840 | #if (! ((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN))) | 1831 | #if THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1841 | SIGNAL_FREE( &s->done_signal_ ); | 1832 | SIGNAL_FREE( &s->done_signal_); |
| 1842 | MUTEX_FREE( &s->done_lock_ ); | 1833 | MUTEX_FREE( &s->done_lock_); |
| 1843 | #endif | 1834 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 1844 | 1835 | ||
| 1845 | free(s); | 1836 | free( s); |
| 1846 | 1837 | ||
| 1847 | return 0; | 1838 | return 0; |
| 1848 | } | 1839 | } |
| @@ -1871,6 +1862,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force) | |||
| 1871 | // | 1862 | // |
| 1872 | if( s->status < DONE) | 1863 | if( s->status < DONE) |
| 1873 | { | 1864 | { |
| 1865 | s->cancel_request = TRUE; // it's now signaled to stop | ||
| 1874 | // signal the linda the wake up the thread so that it can react to the cancel query | 1866 | // signal the linda the wake up the thread so that it can react to the cancel query |
| 1875 | // let us hope we never land here with a pointer on a linda that has been destroyed... | 1867 | // let us hope we never land here with a pointer on a linda that has been destroyed... |
| 1876 | //MUTEX_LOCK( &selfdestruct_cs ); | 1868 | //MUTEX_LOCK( &selfdestruct_cs ); |
| @@ -1882,13 +1874,7 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force) | |||
| 1882 | } | 1874 | } |
| 1883 | } | 1875 | } |
| 1884 | //MUTEX_UNLOCK( &selfdestruct_cs ); | 1876 | //MUTEX_UNLOCK( &selfdestruct_cs ); |
| 1885 | s->cancel_request = TRUE; // it's now signalled to stop | 1877 | done = THREAD_WAIT( &s->thread, secs, &s->done_signal_, &s->done_lock_, &s->status); |
| 1886 | done= | ||
| 1887 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | ||
| 1888 | THREAD_WAIT( &s->thread, secs); | ||
| 1889 | #else | ||
| 1890 | THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, secs); | ||
| 1891 | #endif | ||
| 1892 | 1878 | ||
| 1893 | if ((!done) && force) | 1879 | if ((!done) && force) |
| 1894 | { | 1880 | { |
| @@ -1986,12 +1972,7 @@ LUAG_FUNC( thread_join ) | |||
| 1986 | int ret; | 1972 | int ret; |
| 1987 | bool_t done; | 1973 | bool_t done; |
| 1988 | 1974 | ||
| 1989 | done = (s->thread == 0) || | 1975 | done = THREAD_ISNULL( s->thread) || THREAD_WAIT( &s->thread, wait_secs, &s->done_signal_, &s->done_lock_, &s->status); |
| 1990 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | ||
| 1991 | THREAD_WAIT( &s->thread, wait_secs ); | ||
| 1992 | #else | ||
| 1993 | THREAD_WAIT( &s->thread, &s->done_signal_, &s->done_lock_, &s->status, wait_secs); | ||
| 1994 | #endif | ||
| 1995 | if (!done || !L2) | 1976 | if (!done || !L2) |
| 1996 | return 0; // timeout: pushes none, leaves 'L2' alive | 1977 | return 0; // timeout: pushes none, leaves 'L2' alive |
| 1997 | 1978 | ||
| @@ -2365,7 +2346,7 @@ LUAG_FUNC( configure ) | |||
| 2365 | * there is no problem. But if the host is multithreaded, we need to lock around the | 2346 | * there is no problem. But if the host is multithreaded, we need to lock around the |
| 2366 | * initializations. | 2347 | * initializations. |
| 2367 | */ | 2348 | */ |
| 2368 | #ifdef PLATFORM_WIN32 | 2349 | #if THREADAPI == THREADAPI_WINDOWS |
| 2369 | { | 2350 | { |
| 2370 | static volatile int /*bool*/ go_ahead; // = 0 | 2351 | static volatile int /*bool*/ go_ahead; // = 0 |
| 2371 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) | 2352 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) |
| @@ -2378,7 +2359,7 @@ LUAG_FUNC( configure ) | |||
| 2378 | while( !go_ahead ) { Sleep(1); } // changes threads | 2359 | while( !go_ahead ) { Sleep(1); } // changes threads |
| 2379 | } | 2360 | } |
| 2380 | } | 2361 | } |
| 2381 | #else | 2362 | #else // THREADAPI == THREADAPI_PTHREAD |
| 2382 | if( s_initCount == 0) | 2363 | if( s_initCount == 0) |
| 2383 | { | 2364 | { |
| 2384 | static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; | 2365 | static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; |
| @@ -2394,7 +2375,7 @@ LUAG_FUNC( configure ) | |||
| 2394 | } | 2375 | } |
| 2395 | pthread_mutex_unlock(&my_lock); | 2376 | pthread_mutex_unlock(&my_lock); |
| 2396 | } | 2377 | } |
| 2397 | #endif | 2378 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 2398 | assert( timer_deep != 0 ); | 2379 | assert( timer_deep != 0 ); |
| 2399 | 2380 | ||
| 2400 | // Create main module interface table | 2381 | // Create main module interface table |
| @@ -2453,7 +2434,7 @@ LUAG_FUNC( configure ) | |||
| 2453 | int | 2434 | int |
| 2454 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 2435 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
| 2455 | __declspec(dllexport) | 2436 | __declspec(dllexport) |
| 2456 | #endif | 2437 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) |
| 2457 | luaopen_lanes( lua_State *L ) | 2438 | luaopen_lanes( lua_State *L ) |
| 2458 | { | 2439 | { |
| 2459 | // Create main module interface table | 2440 | // Create main module interface table |
diff --git a/src/lanes.lua b/src/lanes.lua index 005ce28..6ba0ef3 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
| @@ -214,7 +214,7 @@ local function gen( ... ) | |||
| 214 | end | 214 | end |
| 215 | end | 215 | end |
| 216 | 216 | ||
| 217 | local prio, cs, g_tbl, packagepath, packagecpath, required | 217 | local prio, cs, g_tbl, package_tbl, required |
| 218 | 218 | ||
| 219 | for k,v in pairs(opt) do | 219 | for k,v in pairs(opt) do |
| 220 | if k=="priority" then prio= v | 220 | if k=="priority" then prio= v |
| @@ -224,10 +224,8 @@ local function gen( ... ) | |||
| 224 | type(v)=="number" and v or | 224 | type(v)=="number" and v or |
| 225 | error( "Bad cancelstep: "..tostring(v), lev ) | 225 | error( "Bad cancelstep: "..tostring(v), lev ) |
| 226 | elseif k=="globals" then g_tbl= v | 226 | elseif k=="globals" then g_tbl= v |
| 227 | elseif k=="packagepath" then | 227 | elseif k=="package" then |
| 228 | packagepath = (type( v) == "string") and v or error( "Bad packagepath: " .. tostring( v), lev) | 228 | package_tbl = (type( v) == "table") and v or error( "Bad package: " .. tostring( v), lev) |
| 229 | elseif k=="packagecpath" then | ||
| 230 | packagecpath = (type( v) == "string") and v or error( "Bad packagecpath: " .. tostring( v), lev) | ||
| 231 | elseif k=="required" then | 229 | elseif k=="required" then |
| 232 | required= (type( v) == "table") and v or error( "Bad required: " .. tostring( v), lev) | 230 | required= (type( v) == "table") and v or error( "Bad required: " .. tostring( v), lev) |
| 233 | --.. | 231 | --.. |
| @@ -236,12 +234,11 @@ local function gen( ... ) | |||
| 236 | end | 234 | end |
| 237 | end | 235 | end |
| 238 | 236 | ||
| 239 | if not packagepath then packagepath = package.path end | 237 | if not package_tbl then package_tbl = package end |
| 240 | if not packagecpath then packagecpath = package.cpath end | ||
| 241 | -- Lane generator | 238 | -- Lane generator |
| 242 | -- | 239 | -- |
| 243 | return function(...) | 240 | return function(...) |
| 244 | return thread_new( func, libs, cs, prio, g_tbl, packagepath, packagecpath, required, ...) -- args | 241 | return thread_new( func, libs, cs, prio, g_tbl, package_tbl, required, ...) -- args |
| 245 | end | 242 | end |
| 246 | end | 243 | end |
| 247 | 244 | ||
diff --git a/src/threading.c b/src/threading.c index 22d18d4..8966dc6 100644 --- a/src/threading.c +++ b/src/threading.c | |||
| @@ -41,9 +41,9 @@ THE SOFTWARE. | |||
| 41 | #include "threading.h" | 41 | #include "threading.h" |
| 42 | #include "lua.h" | 42 | #include "lua.h" |
| 43 | 43 | ||
| 44 | #if !((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)) | 44 | #if THREADAPI == THREADAPI_PTHREAD |
| 45 | # include <sys/time.h> | 45 | # include <sys/time.h> |
| 46 | #endif | 46 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | #if defined(PLATFORM_LINUX) || defined(PLATFORM_CYGWIN) | 49 | #if defined(PLATFORM_LINUX) || defined(PLATFORM_CYGWIN) |
| @@ -71,7 +71,7 @@ THE SOFTWARE. | |||
| 71 | * FAIL is for unexpected API return values - essentially programming | 71 | * FAIL is for unexpected API return values - essentially programming |
| 72 | * error in _this_ code. | 72 | * error in _this_ code. |
| 73 | */ | 73 | */ |
| 74 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 74 | #if THREADAPI == THREADAPI_WINDOWS |
| 75 | static void FAIL( const char *funcname, int rc ) { | 75 | static void FAIL( const char *funcname, int rc ) { |
| 76 | fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); | 76 | fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); |
| 77 | #ifdef _MSC_VER | 77 | #ifdef _MSC_VER |
| @@ -79,7 +79,7 @@ static void FAIL( const char *funcname, int rc ) { | |||
| 79 | #endif // _MSC_VER | 79 | #endif // _MSC_VER |
| 80 | abort(); | 80 | abort(); |
| 81 | } | 81 | } |
| 82 | #endif | 82 | #endif // THREADAPI == THREADAPI_WINDOWS |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | /* | 85 | /* |
| @@ -90,7 +90,7 @@ static void FAIL( const char *funcname, int rc ) { | |||
| 90 | */ | 90 | */ |
| 91 | time_d now_secs(void) { | 91 | time_d now_secs(void) { |
| 92 | 92 | ||
| 93 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 93 | #if THREADAPI == THREADAPI_WINDOWS |
| 94 | /* | 94 | /* |
| 95 | * Windows FILETIME values are "100-nanosecond intervals since | 95 | * Windows FILETIME values are "100-nanosecond intervals since |
| 96 | * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as | 96 | * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as |
| @@ -145,7 +145,7 @@ time_d now_secs(void) { | |||
| 145 | // <= 2.0.2 code | 145 | // <= 2.0.2 code |
| 146 | return (double)(uli.QuadPart - uli_epoch.QuadPart) / 10000000.0; | 146 | return (double)(uli.QuadPart - uli_epoch.QuadPart) / 10000000.0; |
| 147 | # endif | 147 | # endif |
| 148 | #else | 148 | #else // THREADAPI == THREADAPI_PTHREAD |
| 149 | struct timeval tv; | 149 | struct timeval tv; |
| 150 | // { | 150 | // { |
| 151 | // time_t tv_sec; /* seconds since Jan. 1, 1970 */ | 151 | // time_t tv_sec; /* seconds since Jan. 1, 1970 */ |
| @@ -156,7 +156,7 @@ time_d now_secs(void) { | |||
| 156 | assert( rc==0 ); | 156 | assert( rc==0 ); |
| 157 | 157 | ||
| 158 | return ((double)tv.tv_sec) + ((tv.tv_usec)/1000) / 1000.0; | 158 | return ((double)tv.tv_sec) + ((tv.tv_usec)/1000) / 1000.0; |
| 159 | #endif | 159 | #endif // THREADAPI THREADAPI_PTHREAD |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | 162 | ||
| @@ -168,7 +168,7 @@ time_d SIGNAL_TIMEOUT_PREPARE( double secs ) { | |||
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | 170 | ||
| 171 | #if !((defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)) | 171 | #if THREADAPI == THREADAPI_PTHREAD |
| 172 | /* | 172 | /* |
| 173 | * Prepare 'abs_secs' kind of timeout to 'timespec' format | 173 | * Prepare 'abs_secs' kind of timeout to 'timespec' format |
| 174 | */ | 174 | */ |
| @@ -187,7 +187,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 187 | ts->tv_sec = ts->tv_sec + 1; | 187 | ts->tv_sec = ts->tv_sec + 1; |
| 188 | } | 188 | } |
| 189 | } | 189 | } |
| 190 | #endif | 190 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 191 | 191 | ||
| 192 | 192 | ||
| 193 | /*---=== Threading ===---*/ | 193 | /*---=== Threading ===---*/ |
| @@ -230,7 +230,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 230 | # endif | 230 | # endif |
| 231 | #endif | 231 | #endif |
| 232 | 232 | ||
| 233 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 233 | #if THREADAPI == THREADAPI_WINDOWS |
| 234 | // | 234 | // |
| 235 | void MUTEX_INIT( MUTEX_T *ref ) { | 235 | void MUTEX_INIT( MUTEX_T *ref ) { |
| 236 | *ref= CreateMutex( NULL /*security attr*/, FALSE /*not locked*/, NULL ); | 236 | *ref= CreateMutex( NULL /*security attr*/, FALSE /*not locked*/, NULL ); |
| @@ -282,7 +282,8 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 282 | *ref= h; | 282 | *ref= h; |
| 283 | } | 283 | } |
| 284 | // | 284 | // |
| 285 | bool_t THREAD_WAIT( THREAD_T *ref, double secs ) { | 285 | bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs) |
| 286 | { | ||
| 286 | DWORD ms = (secs<0.0) ? INFINITE : (DWORD)((secs*1000.0)+0.5); | 287 | DWORD ms = (secs<0.0) ? INFINITE : (DWORD)((secs*1000.0)+0.5); |
| 287 | 288 | ||
| 288 | DWORD rc= WaitForSingleObject( *ref, ms /*timeout*/ ); | 289 | DWORD rc= WaitForSingleObject( *ref, ms /*timeout*/ ); |
| @@ -373,7 +374,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 373 | if (!PulseEvent( *ref )) | 374 | if (!PulseEvent( *ref )) |
| 374 | FAIL( "PulseEvent", GetLastError() ); | 375 | FAIL( "PulseEvent", GetLastError() ); |
| 375 | } | 376 | } |
| 376 | #else | 377 | #else // THREADAPI == THREADAPI_PTHREAD |
| 377 | // PThread (Linux, OS X, ...) | 378 | // PThread (Linux, OS X, ...) |
| 378 | // | 379 | // |
| 379 | // On OS X, user processes seem to be able to change priorities. | 380 | // On OS X, user processes seem to be able to change priorities. |
| @@ -652,7 +653,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 652 | } | 653 | } |
| 653 | } | 654 | } |
| 654 | // | 655 | // |
| 655 | /* | 656 | /* |
| 656 | * Wait for a thread to finish. | 657 | * Wait for a thread to finish. |
| 657 | * | 658 | * |
| 658 | * 'mu_ref' is a lock we should use for the waiting; initially unlocked. | 659 | * 'mu_ref' is a lock we should use for the waiting; initially unlocked. |
| @@ -660,11 +661,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 660 | * | 661 | * |
| 661 | * Returns TRUE for succesful wait, FALSE for timed out | 662 | * Returns TRUE for succesful wait, FALSE for timed out |
| 662 | */ | 663 | */ |
| 663 | #ifdef PTHREAD_TIMEDJOIN | 664 | bool_t THREAD_WAIT( THREAD_T *ref, double secs , SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref) |
| 664 | bool_t THREAD_WAIT( THREAD_T *ref, double secs ) | ||
| 665 | #else | ||
| 666 | bool_t THREAD_WAIT( THREAD_T *ref, SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref, double secs ) | ||
| 667 | #endif | ||
| 668 | { | 665 | { |
| 669 | struct timespec ts_store; | 666 | struct timespec ts_store; |
| 670 | const struct timespec *timeout= NULL; | 667 | const struct timespec *timeout= NULL; |
| @@ -672,16 +669,17 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 672 | 669 | ||
| 673 | // Do timeout counting before the locks | 670 | // Do timeout counting before the locks |
| 674 | // | 671 | // |
| 675 | #ifdef PTHREAD_TIMEDJOIN | 672 | #if THREADWAIT_METHOD == THREADWAIT_TIMEOUT |
| 676 | if (secs>=0.0) { | 673 | if (secs>=0.0) |
| 677 | #else | 674 | #else // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 678 | if (secs>0.0) { | 675 | if (secs>0.0) |
| 679 | #endif | 676 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 677 | { | ||
| 680 | prepare_timeout( &ts_store, now_secs()+secs ); | 678 | prepare_timeout( &ts_store, now_secs()+secs ); |
| 681 | timeout= &ts_store; | 679 | timeout= &ts_store; |
| 682 | } | 680 | } |
| 683 | 681 | ||
| 684 | #ifdef PTHREAD_TIMEDJOIN | 682 | #if THREADWAIT_METHOD == THREADWAIT_TIMEOUT |
| 685 | /* Thread is joinable | 683 | /* Thread is joinable |
| 686 | */ | 684 | */ |
| 687 | if (!timeout) { | 685 | if (!timeout) { |
| @@ -694,7 +692,7 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 694 | } | 692 | } |
| 695 | done= rc==0; | 693 | done= rc==0; |
| 696 | } | 694 | } |
| 697 | #else | 695 | #else // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 698 | /* Since we've set the thread up as PTHREAD_CREATE_DETACHED, we cannot | 696 | /* Since we've set the thread up as PTHREAD_CREATE_DETACHED, we cannot |
| 699 | * join with it. Use the cond.var. | 697 | * join with it. Use the cond.var. |
| 700 | */ | 698 | */ |
| @@ -718,13 +716,13 @@ static void prepare_timeout( struct timespec *ts, time_d abs_secs ) { | |||
| 718 | done= *st_ref >= DONE; // DONE|ERROR_ST|CANCELLED | 716 | done= *st_ref >= DONE; // DONE|ERROR_ST|CANCELLED |
| 719 | 717 | ||
| 720 | MUTEX_UNLOCK( mu_ref ); | 718 | MUTEX_UNLOCK( mu_ref ); |
| 721 | #endif | 719 | #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR |
| 722 | return done; | 720 | return done; |
| 723 | } | 721 | } |
| 724 | // | 722 | // |
| 725 | void THREAD_KILL( THREAD_T *ref ) { | 723 | void THREAD_KILL( THREAD_T *ref ) { |
| 726 | pthread_cancel( *ref ); | 724 | pthread_cancel( *ref ); |
| 727 | } | 725 | } |
| 728 | #endif | 726 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 729 | 727 | ||
| 730 | static const lua_Alloc alloc_f= 0; | 728 | static const lua_Alloc alloc_f= 0; |
diff --git a/src/threading.h b/src/threading.h index 4a83229..7387764 100644 --- a/src/threading.h +++ b/src/threading.h | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * THREADING.H | 2 | * THREADING.H |
| 3 | */ | 3 | */ |
| 4 | #ifndef THREADING_H | 4 | #ifndef __threading_h__ |
| 5 | #define THREADING_H | 5 | #define __threading_h__ 1 |
| 6 | 6 | ||
| 7 | /* Platform detection | 7 | /* Platform detection |
| 8 | */ | 8 | */ |
| @@ -45,11 +45,19 @@ typedef unsigned int uint_t; | |||
| 45 | */ | 45 | */ |
| 46 | enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | 46 | enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; |
| 47 | 47 | ||
| 48 | #define THREADAPI_WINDOWS 1 | ||
| 49 | #define THREADAPI_PTHREAD 2 | ||
| 50 | |||
| 51 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | ||
| 52 | #define THREADAPI THREADAPI_WINDOWS | ||
| 53 | #else // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | ||
| 54 | #define THREADAPI THREADAPI_PTHREAD | ||
| 55 | #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | ||
| 48 | 56 | ||
| 49 | /*---=== Locks & Signals ===--- | 57 | /*---=== Locks & Signals ===--- |
| 50 | */ | 58 | */ |
| 51 | 59 | ||
| 52 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 60 | #if THREADAPI == THREADAPI_WINDOWS |
| 53 | #define WIN32_LEAN_AND_MEAN | 61 | #define WIN32_LEAN_AND_MEAN |
| 54 | // 'SignalObjectAndWait' needs this (targets Windows 2000 and above) | 62 | // 'SignalObjectAndWait' needs this (targets Windows 2000 and above) |
| 55 | #define _WIN32_WINNT 0x0400 | 63 | #define _WIN32_WINNT 0x0400 |
| @@ -68,12 +76,13 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | |||
| 68 | void MUTEX_LOCK( MUTEX_T *ref ); | 76 | void MUTEX_LOCK( MUTEX_T *ref ); |
| 69 | void MUTEX_UNLOCK( MUTEX_T *ref ); | 77 | void MUTEX_UNLOCK( MUTEX_T *ref ); |
| 70 | 78 | ||
| 71 | typedef unsigned THREAD_RETURN_T; | 79 | typedef unsigned int THREAD_RETURN_T; |
| 72 | 80 | ||
| 73 | #define SIGNAL_T HANDLE | 81 | #define SIGNAL_T HANDLE |
| 74 | 82 | ||
| 75 | #define YIELD() Sleep(0) | 83 | #define YIELD() Sleep(0) |
| 76 | #else | 84 | #define THREAD_CALLCONV __stdcall |
| 85 | #else // THREADAPI == THREADAPI_PTHREAD | ||
| 77 | // PThread (Linux, OS X, ...) | 86 | // PThread (Linux, OS X, ...) |
| 78 | // | 87 | // |
| 79 | #include <pthread.h> | 88 | #include <pthread.h> |
| @@ -114,7 +123,8 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED }; | |||
| 114 | #else | 123 | #else |
| 115 | #define YIELD() pthread_yield() | 124 | #define YIELD() pthread_yield() |
| 116 | #endif | 125 | #endif |
| 117 | #endif | 126 | #define THREAD_CALLCONV |
| 127 | #endif //THREADAPI == THREADAPI_PTHREAD | ||
| 118 | 128 | ||
| 119 | void SIGNAL_INIT( SIGNAL_T *ref ); | 129 | void SIGNAL_INIT( SIGNAL_T *ref ); |
| 120 | void SIGNAL_FREE( SIGNAL_T *ref ); | 130 | void SIGNAL_FREE( SIGNAL_T *ref ); |
| @@ -136,9 +146,10 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
| 136 | /*---=== Threading ===--- | 146 | /*---=== Threading ===--- |
| 137 | */ | 147 | */ |
| 138 | 148 | ||
| 139 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) | 149 | #if THREADAPI == THREADAPI_WINDOWS |
| 140 | 150 | ||
| 141 | typedef HANDLE THREAD_T; | 151 | typedef HANDLE THREAD_T; |
| 152 | # define THREAD_ISNULL( _h) (_h == 0) | ||
| 142 | // | 153 | // |
| 143 | void THREAD_CREATE( THREAD_T *ref, | 154 | void THREAD_CREATE( THREAD_T *ref, |
| 144 | THREAD_RETURN_T (__stdcall *func)( void * ), | 155 | THREAD_RETURN_T (__stdcall *func)( void * ), |
| @@ -147,7 +158,7 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
| 147 | # define THREAD_PRIO_MIN (-3) | 158 | # define THREAD_PRIO_MIN (-3) |
| 148 | # define THREAD_PRIO_MAX (+3) | 159 | # define THREAD_PRIO_MAX (+3) |
| 149 | 160 | ||
| 150 | #else | 161 | #else // THREADAPI == THREADAPI_PTHREAD |
| 151 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler | 162 | /* Platforms that have a timed 'pthread_join()' can get away with a simpler |
| 152 | * implementation. Others will use a condition variable. | 163 | * implementation. Others will use a condition variable. |
| 153 | */ | 164 | */ |
| @@ -161,6 +172,7 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
| 161 | # endif | 172 | # endif |
| 162 | 173 | ||
| 163 | typedef pthread_t THREAD_T; | 174 | typedef pthread_t THREAD_T; |
| 175 | # define THREAD_ISNULL( _h) 0 // pthread_t may be a structure: never 'null' by itself | ||
| 164 | 176 | ||
| 165 | void THREAD_CREATE( THREAD_T *ref, | 177 | void THREAD_CREATE( THREAD_T *ref, |
| 166 | THREAD_RETURN_T (*func)( void * ), | 178 | THREAD_RETURN_T (*func)( void * ), |
| @@ -178,19 +190,30 @@ bool_t SIGNAL_WAIT( SIGNAL_T *ref, MUTEX_T *mu, time_d timeout ); | |||
| 178 | # define THREAD_PRIO_MIN (-2) | 190 | # define THREAD_PRIO_MIN (-2) |
| 179 | # define THREAD_PRIO_MAX (+2) | 191 | # define THREAD_PRIO_MAX (+2) |
| 180 | # endif | 192 | # endif |
| 181 | #endif | 193 | #endif // THREADAPI == THREADAPI_WINDOWS |
| 182 | 194 | ||
| 183 | /* | 195 | /* |
| 184 | * Win32 and PTHREAD_TIMEDJOIN allow waiting for a thread with a timeout. | 196 | * Win32 and PTHREAD_TIMEDJOIN allow waiting for a thread with a timeout. |
| 185 | * Posix without PTHREAD_TIMEDJOIN needs to use a condition variable approach. | 197 | * Posix without PTHREAD_TIMEDJOIN needs to use a condition variable approach. |
| 186 | */ | 198 | */ |
| 187 | #if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) | 199 | #define THREADWAIT_TIMEOUT 1 |
| 188 | bool_t THREAD_WAIT( THREAD_T *ref, double secs ); | 200 | #define THREADWAIT_CONDVAR 2 |
| 189 | #else | 201 | |
| 190 | bool_t THREAD_WAIT( THREAD_T *ref, SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref, double secs ); | 202 | #if THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) |
| 191 | #endif | 203 | #define THREADWAIT_METHOD THREADWAIT_TIMEOUT |
| 204 | #else // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) | ||
| 205 | #define THREADWAIT_METHOD THREADWAIT_CONDVAR | ||
| 206 | #endif // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) | ||
| 207 | |||
| 208 | |||
| 209 | #if THREADWAIT_METHOD == THREADWAIT_TIMEOUT | ||
| 210 | bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs); | ||
| 211 | #define THREAD_WAIT( a, b, c, d, e) THREAD_WAIT_IMPL( a, b) | ||
| 212 | #else // THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
| 213 | bool_t THREAD_WAIT_IMPL( THREAD_T *ref, double secs, SIGNAL_T *signal_ref, MUTEX_T *mu_ref, volatile enum e_status *st_ref); | ||
| 214 | #define THREAD_WAIT THREAD_WAIT_IMPL | ||
| 215 | #endif // // THREADWAIT_METHOD == THREADWAIT_CONDVAR | ||
| 192 | 216 | ||
| 193 | void THREAD_KILL( THREAD_T *ref ); | 217 | void THREAD_KILL( THREAD_T *ref ); |
| 194 | 218 | ||
| 195 | #endif | 219 | #endif // __threading_h__ |
| 196 | // THREADING_H | ||
