aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-11-05 17:31:02 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-11-05 17:31:02 +0100
commit053f7cff3c95acb915e6babfd306971f11bb7986 (patch)
treeee38c60b1119d34eb96aea1105ef033e851d266e /src/lanes.c
parent717eadee9c3644fabb32c7ee59949f2846143690 (diff)
downloadlanes-053f7cff3c95acb915e6babfd306971f11bb7986.tar.gz
lanes-053f7cff3c95acb915e6babfd306971f11bb7986.tar.bz2
lanes-053f7cff3c95acb915e6babfd306971f11bb7986.zip
* process exit change: close everything at GC when main state closes, not when atexit() handlers are processed
* Lua 5.2-style module: * module() is no longer used to implement lanes.lua * a global "lanes" variable is no longer created when the module is required * the Lanes module table is returned instead * Lanes must be initialized before used: * the first occurence of 'require "lanes"' produces a minimal interface that only contains a configure() function * the remainder of the interface is made available once this function is called * subsequent calls to configure() do nothing * configure() controls the number of keeper states and the startup of timers * LuaJIT 2 compatibility * non-Lua functions are no longer copied by creating a C closure from a C pointer, but through 2-way lookup tables * this means that if a lane function body pulls non-Lua functions, the lane generator description must contain the list of libraries and modules that exports them * introduces a change in configuration .globals management: contents are copied *after* std libs are loaded * new .required configuration entry to list modules that must be require()'ed before lane body is transferred * lane:cancel() wakes up waiting lindas like what is done at lane shutdown
Diffstat (limited to 'src/lanes.c')
-rw-r--r--src/lanes.c311
1 files changed, 225 insertions, 86 deletions
diff --git a/src/lanes.c b/src/lanes.c
index ed54b0f..44db625 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -51,7 +51,7 @@
51 * ... 51 * ...
52 */ 52 */
53 53
54const char *VERSION= "2.2.0"; 54const char *VERSION= "3.0-beta";
55 55
56/* 56/*
57=============================================================================== 57===============================================================================
@@ -787,10 +787,11 @@ static void linda_id( lua_State *L, char const * const which)
787 /* Clean associated structures in the keeper state. 787 /* Clean associated structures in the keeper state.
788 */ 788 */
789 K= keeper_acquire(s); 789 K= keeper_acquire(s);
790 if( K) // can be NULL if this happens during main state shutdown (lanes is GC'ed -> no keepers -> no need to cleanup)
790 { 791 {
791 keeper_call( K->L, "clear", L, s, 0 ); 792 keeper_call( K->L, "clear", L, s, 0 );
793 keeper_release(K);
792 } 794 }
793 keeper_release(K);
794 795
795 /* There aren't any lanes waiting on these lindas, since all proxies 796 /* There aren't any lanes waiting on these lindas, since all proxies
796 * have been gc'ed. Right? 797 * have been gc'ed. Right?
@@ -1028,9 +1029,9 @@ volatile DEEP_PRELUDE *timer_deep; // = NULL
1028/* 1029/*
1029* Process end; cancel any still free-running threads 1030* Process end; cancel any still free-running threads
1030*/ 1031*/
1031static void selfdestruct_atexit( void ) 1032static int selfdestruct_atexit( lua_State *L)
1032{ 1033{
1033 if (selfdestruct_first == SELFDESTRUCT_END) return; // no free-running threads 1034 if (selfdestruct_first == SELFDESTRUCT_END) return 0; // no free-running threads
1034 1035
1035 // Signal _all_ still running threads to exit (including the timer thread) 1036 // Signal _all_ still running threads to exit (including the timer thread)
1036 // 1037 //
@@ -1047,7 +1048,7 @@ static void selfdestruct_atexit( void )
1047 // signal the linda the wake up the thread so that it can react to the cancel query 1048 // signal the linda the wake up the thread so that it can react to the cancel query
1048 // let us hope we never land here with a pointer on a linda that has been destroyed... 1049 // let us hope we never land here with a pointer on a linda that has been destroyed...
1049 SIGNAL_T *waiting_on = s->waiting_on; 1050 SIGNAL_T *waiting_on = s->waiting_on;
1050 s->waiting_on = NULL; 1051 //s->waiting_on = NULL; // useful, or not?
1051 SIGNAL_ALL( waiting_on); 1052 SIGNAL_ALL( waiting_on);
1052 } 1053 }
1053 s = s->selfdestruct_next; 1054 s = s->selfdestruct_next;
@@ -1117,6 +1118,7 @@ static void selfdestruct_atexit( void )
1117 // 1118 //
1118 if ( selfdestruct_first != SELFDESTRUCT_END ) { 1119 if ( selfdestruct_first != SELFDESTRUCT_END ) {
1119 unsigned n=0; 1120 unsigned n=0;
1121#if 0
1120 MUTEX_LOCK( &selfdestruct_cs ); 1122 MUTEX_LOCK( &selfdestruct_cs );
1121 { 1123 {
1122 struct s_lane *s= selfdestruct_first; 1124 struct s_lane *s= selfdestruct_first;
@@ -1131,15 +1133,14 @@ static void selfdestruct_atexit( void )
1131 // and works without the block (so let's leave those lanes running) 1133 // and works without the block (so let's leave those lanes running)
1132 // 1134 //
1133//we want to free memory and such when we exit. 1135//we want to free memory and such when we exit.
1134#if 0
1135 // 2.0.2: at least timer lane is still here 1136 // 2.0.2: at least timer lane is still here
1136 // 1137 //
1137 DEBUGEXEC(fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n )); 1138 DEBUGEXEC(fprintf( stderr, "Left %d lane(s) with cancel request at process end.\n", n ));
1139 n=0;
1138#else 1140#else
1139 // first thing we did was to raise the linda signals the threads were waiting on (if any) 1141 // first thing we did was to raise the linda signals the threads were waiting on (if any)
1140 // therefore, any well-behaved thread should be in CANCELLED state 1142 // therefore, any well-behaved thread should be in CANCELLED state
1141 // these are not running, and the state can be closed 1143 // these are not running, and the state can be closed
1142 n=0;
1143 MUTEX_LOCK( &selfdestruct_cs ); 1144 MUTEX_LOCK( &selfdestruct_cs );
1144 { 1145 {
1145 struct s_lane *s= selfdestruct_first; 1146 struct s_lane *s= selfdestruct_first;
@@ -1147,7 +1148,8 @@ static void selfdestruct_atexit( void )
1147 { 1148 {
1148 struct s_lane *next_s= s->selfdestruct_next; 1149 struct s_lane *next_s= s->selfdestruct_next;
1149 s->selfdestruct_next= NULL; // detach from selfdestruct chain 1150 s->selfdestruct_next= NULL; // detach from selfdestruct chain
1150 THREAD_KILL( &s->thread); 1151 if( s->thread) // can be NULL if previous 'soft' termination succeeded
1152 THREAD_KILL( &s->thread);
1151 // NO lua_close() in this case because we don't know where execution of the state was interrupted 1153 // NO lua_close() in this case because we don't know where execution of the state was interrupted
1152 free( s); 1154 free( s);
1153 s = next_s; 1155 s = next_s;
@@ -1161,6 +1163,7 @@ static void selfdestruct_atexit( void )
1161#endif 1163#endif
1162 } 1164 }
1163 close_keepers(); 1165 close_keepers();
1166 return 0;
1164} 1167}
1165 1168
1166 1169
@@ -1508,10 +1511,36 @@ LUAG_FUNC( set_debug_threadname)
1508// [prio_int=0], 1511// [prio_int=0],
1509// [globals_tbl], 1512// [globals_tbl],
1510// [packagepath], 1513// [packagepath],
1514// [required],
1511// [... args ...] ) 1515// [... args ...] )
1512// 1516//
1513// Upvalues: metatable to use for 'lane_ud' 1517// Upvalues: metatable to use for 'lane_ud'
1514// 1518//
1519
1520// helper function to require a module in the keeper states and in the target state
1521// source state contains module name at the top of the stack
1522static void require_one_module( lua_State *L, lua_State *L2, bool_t _fatal)
1523{
1524 size_t len;
1525 char const *name = lua_tolstring( L, -1, &len);
1526 // require the module in the target lane
1527 STACK_GROW( L2, 2);
1528 lua_getglobal( L2, "require");
1529 if( lua_isnil( L2, -1))
1530 {
1531 lua_pop( L2, 1);
1532 if( _fatal)
1533 luaL_error( L, "cannot pre-require modules without loading package library first");
1534 }
1535 else
1536 {
1537 lua_pushlstring( L2, name, len);
1538 lua_pcall( L2, 1, 0, 0);
1539 // we need to require this module in the keeper states as well
1540 populate_keepers( L);
1541 }
1542}
1543
1515LUAG_FUNC( thread_new ) 1544LUAG_FUNC( thread_new )
1516{ 1545{
1517 lua_State *L2; 1546 lua_State *L2;
@@ -1524,8 +1553,9 @@ LUAG_FUNC( thread_new )
1524 uint_t glob= luaG_isany(L,5) ? 5:0; 1553 uint_t glob= luaG_isany(L,5) ? 5:0;
1525 uint_t ppath = luaG_isany(L,6) ? 6:0; 1554 uint_t ppath = luaG_isany(L,6) ? 6:0;
1526 uint_t pcpath = luaG_isany(L,7) ? 7:0; 1555 uint_t pcpath = luaG_isany(L,7) ? 7:0;
1556 uint_t required = luaG_isany(L,8) ? 8:0;
1527 1557
1528#define FIXED_ARGS (7) 1558#define FIXED_ARGS (8)
1529 uint_t args= lua_gettop(L) - FIXED_ARGS; 1559 uint_t args= lua_gettop(L) - FIXED_ARGS;
1530 1560
1531 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) 1561 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
@@ -1541,40 +1571,20 @@ LUAG_FUNC( thread_new )
1541 1571
1542 if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" ); 1572 if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" );
1543 1573
1544 STACK_GROW( L,2 ); 1574 STACK_GROW( L, 2);
1545
1546 // Setting the globals table (needs to be done before loading stdlibs,
1547 // and the lane function)
1548 //
1549 if (glob!=0)
1550 {
1551 STACK_CHECK(L)
1552 if (!lua_istable(L,glob))
1553 luaL_error( L, "Expected table, got %s", luaG_typename(L,glob) );
1554
1555 lua_pushvalue( L, glob );
1556
1557 luaG_inter_move( L, L2, 1); // moves the table to L2
1558
1559 // L2 [-1]: table of globals
1560
1561 // "You can change the global environment of a Lua thread using lua_replace"
1562 // (refman-5.0.pdf p. 30)
1563 //
1564 lua_replace( L2, LUA_GLOBALSINDEX );
1565 STACK_END(L,0)
1566 }
1567 1575
1568 // Selected libraries 1576 // Selected libraries
1569 // 1577 //
1570 if (libs) 1578 if (libs)
1571 { 1579 {
1572 const char *err= luaG_openlibs( L2, libs ); 1580 const char *err= luaG_openlibs( L2, libs);
1573 ASSERT_L( !err ); // bad libs should have been noticed by 'lanes.lua' 1581 ASSERT_L( !err ); // bad libs should have been noticed by 'lanes.lua'
1574 1582
1575 serialize_require( L2 ); 1583 serialize_require( L2);
1576 } 1584 }
1577 1585
1586 ASSERT_L( lua_gettop(L2) == 0);
1587
1578 // package.path 1588 // package.path
1579 STACK_CHECK(L2) 1589 STACK_CHECK(L2)
1580 if( ppath) 1590 if( ppath)
@@ -1582,15 +1592,17 @@ LUAG_FUNC( thread_new )
1582 if (lua_type(L,ppath) != LUA_TSTRING) 1592 if (lua_type(L,ppath) != LUA_TSTRING)
1583 luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath)); 1593 luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath));
1584 lua_getglobal( L2, "package"); 1594 lua_getglobal( L2, "package");
1585 if( lua_isnil( L2, -1)) 1595 if( lua_isnil( L2, -1)) // package library not loaded: do nothing
1586 { 1596 {
1587 lua_pop( L2, 1); 1597 lua_pop( L2, 1);
1588 luaL_error( L, "specifying a new path for packages, but lane doesn't load package library");
1589 } 1598 }
1590 lua_pushvalue( L, ppath); 1599 else
1591 luaG_inter_move( L, L2, 1); // moves the new path to L2 1600 {
1592 lua_setfield( L2, -2, "path"); // set package.path 1601 lua_pushvalue( L, ppath);
1593 lua_pop( L2, 1); 1602 luaG_inter_move( L, L2, 1); // moves the new path to L2
1603 lua_setfield( L2, -2, "path"); // set package.path
1604 lua_pop( L2, 1);
1605 }
1594 } 1606 }
1595 STACK_END(L2,0) 1607 STACK_END(L2,0)
1596 1608
@@ -1601,18 +1613,83 @@ LUAG_FUNC( thread_new )
1601 if (lua_type(L,pcpath) != LUA_TSTRING) 1613 if (lua_type(L,pcpath) != LUA_TSTRING)
1602 luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath)); 1614 luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath));
1603 lua_getglobal( L2, "package"); 1615 lua_getglobal( L2, "package");
1604 if( lua_isnil( L2, -1)) 1616 if( lua_isnil( L2, -1)) // // package library not loaded: do nothing
1605 { 1617 {
1606 lua_pop( L2, 1); 1618 lua_pop( L2, 1);
1607 luaL_error( L, "specifying a new cpath for packages, but lane doesn't load package library");
1608 } 1619 }
1609 lua_pushvalue( L, pcpath); 1620 else
1610 luaG_inter_move( L, L2, 1); // moves the new cpath to L2 1621 {
1611 lua_setfield( L2, -2, "cpath"); // set package.cpath 1622 lua_pushvalue( L, pcpath);
1612 lua_pop( L2, 1); 1623 luaG_inter_move( L, L2, 1); // moves the new cpath to L2
1624 lua_setfield( L2, -2, "cpath"); // set package.cpath
1625 lua_pop( L2, 1);
1626 }
1613 } 1627 }
1614 STACK_END(L2,0) 1628 STACK_END(L2,0)
1615 1629
1630 // modules to require in the target lane *before* the function is transfered!
1631
1632 //start by requiring lua51-lanes, since it is a bit special
1633 // it not fatal if 'require' isn't loaded, just ignore (may cause function transfer errors later on if the lane pulls the lanes module itself)
1634 STACK_CHECK(L)
1635 STACK_CHECK(L2)
1636 lua_pushliteral( L, "lua51-lanes");
1637 require_one_module( L, L2, FALSE);
1638 lua_pop( L, 1);
1639 STACK_END(L2,0)
1640 STACK_END(L,0)
1641
1642 STACK_CHECK(L)
1643 STACK_CHECK(L2)
1644 if( required)
1645 {
1646 int nbRequired = 1;
1647 // should not happen, was checked in lanes.lua before calling thread_new()
1648 if (lua_type(L, required) != LUA_TTABLE)
1649 luaL_error( L, "expected required module list as a table, got %s", luaG_typename( L, required));
1650 lua_pushnil( L);
1651 while( lua_next( L, required) != 0)
1652 {
1653 if (lua_type(L,-1) != LUA_TSTRING || lua_type(L,-2) != LUA_TNUMBER || lua_tonumber( L, -2) != nbRequired)
1654 {
1655 luaL_error( L, "required module list should be a list of strings.");
1656 }
1657 else
1658 {
1659 require_one_module( L, L2, TRUE);
1660 }
1661 lua_pop( L, 1);
1662 ++ nbRequired;
1663 }
1664 }
1665 STACK_END(L2,0)
1666 STACK_END(L,0)
1667
1668 // Appending the specified globals to the global environment
1669 // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed...
1670 //
1671 if (glob!=0)
1672 {
1673 STACK_CHECK(L)
1674 STACK_CHECK(L2)
1675 if (!lua_istable(L,glob))
1676 luaL_error( L, "Expected table, got %s", luaG_typename(L,glob));
1677
1678 lua_pushnil( L);
1679 while( lua_next( L, glob))
1680 {
1681 luaG_inter_copy( L, L2, 2); // moves the key/value pair to the L2 stack
1682 // assign it in the globals table
1683 lua_rawset( L2, LUA_GLOBALSINDEX);
1684 lua_pop( L, 1);
1685 }
1686
1687 STACK_END(L2, 0)
1688 STACK_END(L, 0)
1689 }
1690
1691 ASSERT_L( lua_gettop(L2) == 0);
1692
1616 // Lane main function 1693 // Lane main function
1617 // 1694 //
1618 STACK_CHECK(L) 1695 STACK_CHECK(L)
@@ -1677,7 +1754,7 @@ LUAG_FUNC( thread_new )
1677 lua_newtable( L); 1754 lua_newtable( L);
1678 lua_setfenv( L, -2); 1755 lua_setfenv( L, -2);
1679 1756
1680 // Place 's' to registry, for 'cancel_test()' (even if 'cs'==0 we still 1757 // Place 's' in registry, for 'cancel_test()' (even if 'cs'==0 we still
1681 // do cancel tests at pending send/receive). 1758 // do cancel tests at pending send/receive).
1682 // 1759 //
1683 lua_pushlightuserdata( L2, CANCEL_TEST_KEY ); 1760 lua_pushlightuserdata( L2, CANCEL_TEST_KEY );
@@ -1792,6 +1869,17 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force)
1792 // 1869 //
1793 if( s->status < DONE) 1870 if( s->status < DONE)
1794 { 1871 {
1872 // signal the linda the wake up the thread so that it can react to the cancel query
1873 // let us hope we never land here with a pointer on a linda that has been destroyed...
1874 //MUTEX_LOCK( &selfdestruct_cs );
1875 {
1876 SIGNAL_T *waiting_on = s->waiting_on;
1877 if( s->status == WAITING && waiting_on != NULL)
1878 {
1879 SIGNAL_ALL( waiting_on);
1880 }
1881 }
1882 //MUTEX_UNLOCK( &selfdestruct_cs );
1795 s->cancel_request = TRUE; // it's now signalled to stop 1883 s->cancel_request = TRUE; // it's now signalled to stop
1796 done= 1884 done=
1797#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN) 1885#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) || (defined PTHREAD_TIMEDJOIN)
@@ -1816,23 +1904,32 @@ static bool_t thread_cancel( struct s_lane *s, double secs, bool_t force)
1816 1904
1817LUAG_FUNC( thread_cancel) 1905LUAG_FUNC( thread_cancel)
1818{ 1906{
1819 struct s_lane *s= lua_toLane(L,1); 1907 if( lua_gettop( L) != 1 || lua_type( L, 1) != LUA_TUSERDATA)
1820 double secs= 0.0; 1908 {
1821 uint_t force_i=2; 1909 return luaL_error( L, "invalid argument #1, did you use ':' as you should?");
1822 bool_t force, done= TRUE; 1910 }
1911 else
1912 {
1913 struct s_lane *s = lua_toLane( L, 1);
1914 double secs = 0.0;
1915 uint_t force_i = 2;
1916 bool_t force, done= TRUE;
1823 1917
1824 if (lua_isnumber(L,2)) { 1918 if( lua_isnumber( L, 2))
1825 secs= lua_tonumber(L,2); 1919 {
1826 force_i++; 1920 secs = lua_tonumber( L, 2);
1827 } else if (lua_isnil(L,2)) 1921 ++ force_i;
1828 force_i++; 1922 }
1923 else if( lua_isnil( L, 2))
1924 ++ force_i;
1829 1925
1830 force= lua_toboolean(L,force_i); // FALSE if nothing there 1926 force = lua_toboolean( L, force_i); // FALSE if nothing there
1831 1927
1832 done = thread_cancel( s, secs, force); 1928 done = thread_cancel( s, secs, force);
1833 1929
1834 lua_pushboolean( L, done); 1930 lua_pushboolean( L, done);
1835 return 1; 1931 return 1;
1932 }
1836} 1933}
1837 1934
1838//--- 1935//---
@@ -2183,7 +2280,7 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
2183 // Selfdestruct chain handling 2280 // Selfdestruct chain handling
2184 // 2281 //
2185 MUTEX_INIT( &selfdestruct_cs ); 2282 MUTEX_INIT( &selfdestruct_cs );
2186 atexit( selfdestruct_atexit ); 2283 //atexit( selfdestruct_atexit );
2187 2284
2188 //--- 2285 //---
2189 // Linux needs SCHED_RR to change thread priorities, and that is only 2286 // Linux needs SCHED_RR to change thread priorities, and that is only
@@ -2233,7 +2330,17 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
2233 2330
2234 // The host Lua state must always have a reference to this Linda object in order for our 'timer_deep_ref' to be valid. 2331 // The host Lua state must always have a reference to this Linda object in order for our 'timer_deep_ref' to be valid.
2235 // So store a reference that we will never actually use. 2332 // So store a reference that we will never actually use.
2236 lua_pushlightuserdata(L, (void *)init_once_LOCKED); 2333 // at the same time, use this object as a 'desinit' marker:
2334 // when the main lua State is closed, this object will be GC'ed
2335 {
2336 lua_newuserdata( L, 1);
2337 lua_newtable( L);
2338 lua_pushcfunction( L, selfdestruct_atexit);
2339 lua_setfield( L, -2, "__gc");
2340 lua_pushliteral( L, "AtExit");
2341 lua_setfield( L, -2, "__metatable");
2342 lua_setmetatable( L, -2);
2343 }
2237 lua_insert(L, -2); // Swap key with the Linda object 2344 lua_insert(L, -2); // Swap key with the Linda object
2238 lua_rawset(L, LUA_REGISTRYINDEX); 2345 lua_rawset(L, LUA_REGISTRYINDEX);
2239 2346
@@ -2241,14 +2348,12 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
2241 STACK_END(L,0) 2348 STACK_END(L,0)
2242} 2349}
2243 2350
2244int 2351static volatile long s_initCount = 0;
2245#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 2352
2246__declspec(dllexport) 2353LUAG_FUNC( configure )
2247#endif
2248luaopen_lanes( lua_State *L )
2249{ 2354{
2250 static volatile int /*bool*/ go_ahead; // = 0 2355 char const *name = luaL_checkstring( L, lua_upvalueindex( 1));
2251 int const nbKeepers = luaL_optint( L, 2, 1); 2356 int const nbKeepers = luaL_optint( L, 1, 1);
2252 luaL_argcheck( L, nbKeepers > 0, 2, "Number of keeper states must be > 0"); 2357 luaL_argcheck( L, nbKeepers > 0, 2, "Number of keeper states must be > 0");
2253 /* 2358 /*
2254 * Making one-time initializations. 2359 * Making one-time initializations.
@@ -2259,31 +2364,29 @@ luaopen_lanes( lua_State *L )
2259 */ 2364 */
2260#ifdef PLATFORM_WIN32 2365#ifdef PLATFORM_WIN32
2261 { 2366 {
2262 // TBD: Someone please replace this with reliable Win32 API code. Problem is, 2367 static volatile int /*bool*/ go_ahead; // = 0
2263 // there's no autoinitializing locks (s.a. PTHREAD_MUTEX_INITIALIZER) in 2368 if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0)
2264 // Windows so 'InterlockedIncrement' or something needs to be used. 2369 {
2265 // This is 99.9999% safe, though (and always safe if host is single-threaded)
2266 // -- AKa 24-Jun-2009
2267 //
2268 static volatile unsigned my_number; // = 0
2269
2270 if (my_number++ == 0) { // almost atomic
2271 init_once_LOCKED(L, &timer_deep, nbKeepers); 2370 init_once_LOCKED(L, &timer_deep, nbKeepers);
2272 go_ahead= 1; // let others pass 2371 go_ahead= 1; // let others pass
2273 } else { 2372 }
2373 else
2374 {
2274 while( !go_ahead ) { Sleep(1); } // changes threads 2375 while( !go_ahead ) { Sleep(1); } // changes threads
2275 } 2376 }
2276 } 2377 }
2277#else 2378#else
2278 if (!go_ahead) { 2379 if( s_initCount == 0)
2380 {
2279 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; 2381 static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER;
2280 pthread_mutex_lock(&my_lock); 2382 pthread_mutex_lock(&my_lock);
2281 { 2383 {
2282 // Recheck now that we're within the lock 2384 // Recheck now that we're within the lock
2283 // 2385 //
2284 if (!go_ahead) { 2386 if (s_initCount == 0)
2387 {
2285 init_once_LOCKED(L, &timer_deep, nbKeepers); 2388 init_once_LOCKED(L, &timer_deep, nbKeepers);
2286 go_ahead= 1; 2389 s_initCount = 1;
2287 } 2390 }
2288 } 2391 }
2289 pthread_mutex_unlock(&my_lock); 2392 pthread_mutex_unlock(&my_lock);
@@ -2292,7 +2395,10 @@ luaopen_lanes( lua_State *L )
2292 assert( timer_deep != 0 ); 2395 assert( timer_deep != 0 );
2293 2396
2294 // Create main module interface table 2397 // Create main module interface table
2295 lua_newtable(L); 2398 lua_pushvalue( L, lua_upvalueindex( 2));
2399 // remove configure() (this function) from the module interface
2400 lua_pushnil( L);
2401 lua_setfield( L, -2, "configure");
2296 luaL_register(L, NULL, lanes_functions); 2402 luaL_register(L, NULL, lanes_functions);
2297 2403
2298 // metatable for threads 2404 // metatable for threads
@@ -2313,7 +2419,7 @@ luaopen_lanes( lua_State *L )
2313 lua_setfield( L, -2, "join"); 2419 lua_setfield( L, -2, "join");
2314 lua_pushcfunction( L, LG_thread_cancel); 2420 lua_pushcfunction( L, LG_thread_cancel);
2315 lua_setfield( L, -2, "cancel"); 2421 lua_setfield( L, -2, "cancel");
2316 lua_pushboolean( L, 0); 2422 lua_pushliteral( L, "Lane");
2317 lua_setfield( L, -2, "__metatable"); 2423 lua_setfield( L, -2, "__metatable");
2318 2424
2319 lua_pushcclosure( L, LG_thread_new, 1 ); // metatable as closure param 2425 lua_pushcclosure( L, LG_thread_new, 1 ); // metatable as closure param
@@ -2331,8 +2437,41 @@ luaopen_lanes( lua_State *L )
2331 lua_pushlightuserdata( L, CANCEL_ERROR ); 2437 lua_pushlightuserdata( L, CANCEL_ERROR );
2332 lua_setfield(L, -2, "cancel_error"); 2438 lua_setfield(L, -2, "cancel_error");
2333 2439
2334 // Return the local module table 2440 // register all native functions found in that module in the transferable functions database
2335 return 1; 2441 // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names)
2442 populate_func_lookup_table( L, -1, name);
2443 // record all existing C/JIT-fast functions
2444 populate_func_lookup_table( L, LUA_GLOBALSINDEX, NULL);
2445 // Return nothing
2446 lua_pop( L, 1);
2447 return 0;
2448}
2449
2450int
2451#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2452__declspec(dllexport)
2453#endif
2454luaopen_lanes( lua_State *L )
2455{
2456 // Create main module interface table
2457 // we only have 1 closure, which must be called to configure Lanes
2458 STACK_GROW( L, 3);
2459 STACK_CHECK( L)
2460 lua_newtable(L);
2461 lua_pushvalue(L, 1); // module name
2462 lua_pushvalue(L, -2); // module table
2463 lua_pushcclosure( L, LG_configure, 2);
2464 if( s_initCount == 0)
2465 {
2466 lua_setfield( L, -2, "configure");
2467 }
2468 else // already initialized: call it mmediately and be done
2469 {
2470 lua_pushinteger( L, 666); // any value will do, it will be ignored
2471 lua_call( L, 1, 0);
2472 }
2473 STACK_END( L, 1)
2474 return 1;
2336} 2475}
2337 2476
2338 2477