diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2012-02-18 14:08:52 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2012-02-18 14:08:52 +0100 |
| commit | 076344633e7b2525cf48005f84f3935f324b60bf (patch) | |
| tree | 2a013da0ba2cd4a9f7eaf073a5ba128723f13154 /src | |
| parent | b4582dd0bb65a916de7fa9612880b75a17c7ae7f (diff) | |
| download | lanes-076344633e7b2525cf48005f84f3935f324b60bf.tar.gz lanes-076344633e7b2525cf48005f84f3935f324b60bf.tar.bz2 lanes-076344633e7b2525cf48005f84f3935f324b60bf.zip | |
* changed lanes.configure signature to receive a table instead of individual parameters
* added support for an on_state_create callback called to load custom functions in a state in addition to the base libraries
Diffstat (limited to 'src')
| -rw-r--r-- | src/keeper.c | 18 | ||||
| -rw-r--r-- | src/keeper.h | 2 | ||||
| -rw-r--r-- | src/lanes.c | 66 | ||||
| -rw-r--r-- | src/lanes.lua | 32 | ||||
| -rw-r--r-- | src/tools.c | 81 | ||||
| -rw-r--r-- | src/tools.h | 4 |
6 files changed, 108 insertions, 95 deletions
diff --git a/src/keeper.c b/src/keeper.c index 1f69d40..6f5bd95 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
| @@ -78,7 +78,7 @@ static char const keeper_chunk[]= | |||
| 78 | * unclosed, because it does not really matter. In production code, this | 78 | * unclosed, because it does not really matter. In production code, this |
| 79 | * function never fails. | 79 | * function never fails. |
| 80 | */ | 80 | */ |
| 81 | char const *init_keepers( int const _nbKeepers) | 81 | char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create) |
| 82 | { | 82 | { |
| 83 | int i; | 83 | int i; |
| 84 | assert( _nbKeepers >= 1); | 84 | assert( _nbKeepers >= 1); |
| @@ -87,10 +87,11 @@ char const *init_keepers( int const _nbKeepers) | |||
| 87 | for( i = 0; i < _nbKeepers; ++ i) | 87 | for( i = 0; i < _nbKeepers; ++ i) |
| 88 | { | 88 | { |
| 89 | 89 | ||
| 90 | // Initialize Keeper states with bare minimum of libs (those required | 90 | // Initialize Keeper states with bare minimum of libs (those required by 'keeper.lua') |
| 91 | // by 'keeper.lua') | 91 | // |
| 92 | // | 92 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs |
| 93 | lua_State *K = luaL_newstate(); | 93 | // the others because they export functions that we may store in a keeper for transfer between lanes |
| 94 | lua_State* K = luaG_newstate( "*", _on_state_create); | ||
| 94 | if (!K) | 95 | if (!K) |
| 95 | return "out of memory"; | 96 | return "out of memory"; |
| 96 | 97 | ||
| @@ -100,11 +101,6 @@ char const *init_keepers( int const _nbKeepers) | |||
| 100 | lua_concat( K, 2); | 101 | lua_concat( K, 2); |
| 101 | lua_setglobal( K, "decoda_name"); | 102 | lua_setglobal( K, "decoda_name"); |
| 102 | 103 | ||
| 103 | // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs | ||
| 104 | // the others because they export functions that we may store in a keeper for transfer between lanes | ||
| 105 | luaG_openlibs( K, "*"); | ||
| 106 | serialize_require( K); | ||
| 107 | |||
| 108 | // Read in the preloaded chunk (and run it) | 104 | // Read in the preloaded chunk (and run it) |
| 109 | // | 105 | // |
| 110 | if( luaL_loadbuffer( K, keeper_chunk, sizeof(keeper_chunk), "@keeper.lua")) | 106 | if( luaL_loadbuffer( K, keeper_chunk, sizeof(keeper_chunk), "@keeper.lua")) |
| @@ -114,7 +110,7 @@ char const *init_keepers( int const _nbKeepers) | |||
| 114 | { | 110 | { |
| 115 | // LUA_ERRRUN / LUA_ERRMEM / LUA_ERRERR | 111 | // LUA_ERRRUN / LUA_ERRMEM / LUA_ERRERR |
| 116 | // | 112 | // |
| 117 | const char *err = lua_tostring(K, -1); | 113 | char const* err = lua_tostring( K, -1); |
| 118 | assert( err); | 114 | assert( err); |
| 119 | return err; | 115 | return err; |
| 120 | } | 116 | } |
diff --git a/src/keeper.h b/src/keeper.h index 1bcb36b..0990846 100644 --- a/src/keeper.h +++ b/src/keeper.h | |||
| @@ -8,7 +8,7 @@ struct s_Keeper | |||
| 8 | //int count; | 8 | //int count; |
| 9 | }; | 9 | }; |
| 10 | 10 | ||
| 11 | const char *init_keepers( int const _nbKeepers); | 11 | char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create); |
| 12 | void populate_keepers( lua_State *L); | 12 | void populate_keepers( lua_State *L); |
| 13 | struct s_Keeper *keeper_acquire( const void *ptr); | 13 | struct s_Keeper *keeper_acquire( const void *ptr); |
| 14 | void keeper_release( struct s_Keeper *K); | 14 | void keeper_release( struct s_Keeper *K); |
diff --git a/src/lanes.c b/src/lanes.c index 676032a..513a006 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -51,7 +51,7 @@ | |||
| 51 | * ... | 51 | * ... |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | const char *VERSION= "3.0-beta"; | 54 | char const* VERSION = "3.1.0"; |
| 55 | 55 | ||
| 56 | /* | 56 | /* |
| 57 | =============================================================================== | 57 | =============================================================================== |
| @@ -1540,7 +1540,7 @@ static void require_one_module( lua_State *L, lua_State *L2, bool_t _fatal) | |||
| 1540 | { | 1540 | { |
| 1541 | lua_pop( L2, 1); | 1541 | lua_pop( L2, 1); |
| 1542 | if( _fatal) | 1542 | if( _fatal) |
| 1543 | luaL_error( L, "cannot pre-require modules without loading package library first"); | 1543 | luaL_error( L, "cannot pre-require modules without loading 'package' library first"); |
| 1544 | } | 1544 | } |
| 1545 | else | 1545 | else |
| 1546 | { | 1546 | { |
| @@ -1557,14 +1557,15 @@ LUAG_FUNC( thread_new ) | |||
| 1557 | struct s_lane *s; | 1557 | struct s_lane *s; |
| 1558 | struct s_lane **ud; | 1558 | struct s_lane **ud; |
| 1559 | 1559 | ||
| 1560 | const char *libs= lua_tostring( L, 2 ); | 1560 | char const* libs = lua_tostring( L, 2); |
| 1561 | uint_t cs= luaG_optunsigned( L, 3,0); | 1561 | lua_CFunction on_state_create = lua_iscfunction( L, 3) ? lua_tocfunction( L, 3) : NULL; |
| 1562 | int prio= (int)luaL_optinteger( L, 4,0); | 1562 | uint_t cs = luaG_optunsigned( L, 4, 0); |
| 1563 | uint_t glob= luaG_isany(L,5) ? 5:0; | 1563 | int prio = (int) luaL_optinteger( L, 5, 0); |
| 1564 | uint_t package = luaG_isany(L,6) ? 6:0; | 1564 | uint_t glob = luaG_isany( L, 6) ? 6 : 0; |
| 1565 | uint_t required = luaG_isany(L,7) ? 7:0; | 1565 | uint_t package = luaG_isany( L,7) ? 7 : 0; |
| 1566 | uint_t required = luaG_isany( L, 8) ? 8 : 0; | ||
| 1566 | 1567 | ||
| 1567 | #define FIXED_ARGS (7) | 1568 | #define FIXED_ARGS 8 |
| 1568 | uint_t args= lua_gettop(L) - FIXED_ARGS; | 1569 | uint_t args= lua_gettop(L) - FIXED_ARGS; |
| 1569 | 1570 | ||
| 1570 | if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) | 1571 | if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) |
| @@ -1575,23 +1576,13 @@ LUAG_FUNC( thread_new ) | |||
| 1575 | 1576 | ||
| 1576 | /* --- Create and prepare the sub state --- */ | 1577 | /* --- Create and prepare the sub state --- */ |
| 1577 | 1578 | ||
| 1578 | L2 = luaL_newstate(); // uses standard 'realloc()'-based allocator, | 1579 | // populate with selected libraries at the same time |
| 1579 | // sets the panic callback | 1580 | // |
| 1580 | 1581 | L2 = luaG_newstate( libs, on_state_create); | |
| 1581 | if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" ); | 1582 | if (!L2) luaL_error( L, "'luaL_newstate()' failed; out of memory" ); |
| 1582 | 1583 | ||
| 1583 | STACK_GROW( L, 2); | 1584 | STACK_GROW( L, 2); |
| 1584 | 1585 | ||
| 1585 | // Selected libraries | ||
| 1586 | // | ||
| 1587 | if (libs) | ||
| 1588 | { | ||
| 1589 | const char *err= luaG_openlibs( L2, libs); | ||
| 1590 | ASSERT_L( !err ); // bad libs should have been noticed by 'lanes.lua' | ||
| 1591 | |||
| 1592 | serialize_require( L2); | ||
| 1593 | } | ||
| 1594 | |||
| 1595 | ASSERT_L( lua_gettop(L2) == 0); | 1586 | ASSERT_L( lua_gettop(L2) == 0); |
| 1596 | 1587 | ||
| 1597 | // package.path | 1588 | // package.path |
| @@ -1600,7 +1591,7 @@ LUAG_FUNC( thread_new ) | |||
| 1600 | if( package) | 1591 | if( package) |
| 1601 | { | 1592 | { |
| 1602 | if (lua_type(L,package) != LUA_TTABLE) | 1593 | if (lua_type(L,package) != LUA_TTABLE) |
| 1603 | luaL_error( L, "expected package as table, got %s", luaG_typename(L,package)); | 1594 | luaL_error( L, "expected package as table, got %s", luaL_typename(L,package)); |
| 1604 | lua_getglobal( L2, "package"); | 1595 | lua_getglobal( L2, "package"); |
| 1605 | if( !lua_isnil( L2, -1)) // package library not loaded: do nothing | 1596 | if( !lua_isnil( L2, -1)) // package library not loaded: do nothing |
| 1606 | { | 1597 | { |
| @@ -1628,7 +1619,7 @@ LUAG_FUNC( thread_new ) | |||
| 1628 | // modules to require in the target lane *before* the function is transfered! | 1619 | // modules to require in the target lane *before* the function is transfered! |
| 1629 | 1620 | ||
| 1630 | //start by requiring lua51-lanes, since it is a bit special | 1621 | //start by requiring lua51-lanes, since it is a bit special |
| 1631 | // 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) | 1622 | // it is not fatal if 'require' isn't loaded, just ignore (may cause function transfer errors later on if the lane pulls the lanes module itself) |
| 1632 | STACK_CHECK(L) | 1623 | STACK_CHECK(L) |
| 1633 | STACK_CHECK(L2) | 1624 | STACK_CHECK(L2) |
| 1634 | lua_pushliteral( L, "lua51-lanes"); | 1625 | lua_pushliteral( L, "lua51-lanes"); |
| @@ -1644,7 +1635,7 @@ LUAG_FUNC( thread_new ) | |||
| 1644 | int nbRequired = 1; | 1635 | int nbRequired = 1; |
| 1645 | // should not happen, was checked in lanes.lua before calling thread_new() | 1636 | // should not happen, was checked in lanes.lua before calling thread_new() |
| 1646 | if (lua_type(L, required) != LUA_TTABLE) | 1637 | if (lua_type(L, required) != LUA_TTABLE) |
| 1647 | luaL_error( L, "expected required module list as a table, got %s", luaG_typename( L, required)); | 1638 | luaL_error( L, "expected required module list as a table, got %s", luaL_typename( L, required)); |
| 1648 | lua_pushnil( L); | 1639 | lua_pushnil( L); |
| 1649 | while( lua_next( L, required) != 0) | 1640 | while( lua_next( L, required) != 0) |
| 1650 | { | 1641 | { |
| @@ -1671,7 +1662,7 @@ LUAG_FUNC( thread_new ) | |||
| 1671 | STACK_CHECK(L) | 1662 | STACK_CHECK(L) |
| 1672 | STACK_CHECK(L2) | 1663 | STACK_CHECK(L2) |
| 1673 | if (!lua_istable(L,glob)) | 1664 | if (!lua_istable(L,glob)) |
| 1674 | luaL_error( L, "Expected table, got %s", luaG_typename(L,glob)); | 1665 | luaL_error( L, "Expected table, got %s", luaL_typename(L,glob)); |
| 1675 | 1666 | ||
| 1676 | lua_pushnil( L); | 1667 | lua_pushnil( L); |
| 1677 | while( lua_next( L, glob)) | 1668 | while( lua_next( L, glob)) |
| @@ -2240,7 +2231,7 @@ static const struct luaL_reg lanes_functions [] = { | |||
| 2240 | /* | 2231 | /* |
| 2241 | * One-time initializations | 2232 | * One-time initializations |
| 2242 | */ | 2233 | */ |
| 2243 | static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref, int const nbKeepers) | 2234 | static void init_once_LOCKED( lua_State* L, volatile DEEP_PRELUDE** timer_deep_ref, int const nbKeepers, lua_CFunction _on_state_create) |
| 2244 | { | 2235 | { |
| 2245 | const char *err; | 2236 | const char *err; |
| 2246 | 2237 | ||
| @@ -2291,7 +2282,7 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ | |||
| 2291 | } | 2282 | } |
| 2292 | #endif | 2283 | #endif |
| 2293 | #endif | 2284 | #endif |
| 2294 | err= init_keepers( nbKeepers); | 2285 | err = init_keepers( nbKeepers, _on_state_create); |
| 2295 | if (err) | 2286 | if (err) |
| 2296 | { | 2287 | { |
| 2297 | luaL_error( L, "Unable to initialize: %s", err ); | 2288 | luaL_error( L, "Unable to initialize: %s", err ); |
| @@ -2338,9 +2329,11 @@ static volatile long s_initCount = 0; | |||
| 2338 | 2329 | ||
| 2339 | LUAG_FUNC( configure ) | 2330 | LUAG_FUNC( configure ) |
| 2340 | { | 2331 | { |
| 2341 | char const *name = luaL_checkstring( L, lua_upvalueindex( 1)); | 2332 | char const* name = luaL_checkstring( L, lua_upvalueindex( 1)); |
| 2342 | int const nbKeepers = luaL_optint( L, 1, 1); | 2333 | int const nbKeepers = luaL_optint( L, 1, 1); |
| 2343 | luaL_argcheck( L, nbKeepers > 0, 2, "Number of keeper states must be > 0"); | 2334 | lua_CFunction on_state_create = lua_iscfunction( L, 2) ? lua_tocfunction( L, 2) : NULL; |
| 2335 | luaL_argcheck( L, nbKeepers > 0, 1, "Number of keeper states must be > 0"); | ||
| 2336 | luaL_argcheck( L, lua_iscfunction( L, 2) || lua_isnil( L, 2), 2, "on_state_create should be a C function"); | ||
| 2344 | /* | 2337 | /* |
| 2345 | * Making one-time initializations. | 2338 | * Making one-time initializations. |
| 2346 | * | 2339 | * |
| @@ -2353,7 +2346,7 @@ LUAG_FUNC( configure ) | |||
| 2353 | static volatile int /*bool*/ go_ahead; // = 0 | 2346 | static volatile int /*bool*/ go_ahead; // = 0 |
| 2354 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) | 2347 | if( InterlockedCompareExchange( &s_initCount, 1, 0) == 0) |
| 2355 | { | 2348 | { |
| 2356 | init_once_LOCKED(L, &timer_deep, nbKeepers); | 2349 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create); |
| 2357 | go_ahead= 1; // let others pass | 2350 | go_ahead= 1; // let others pass |
| 2358 | } | 2351 | } |
| 2359 | else | 2352 | else |
| @@ -2365,13 +2358,13 @@ LUAG_FUNC( configure ) | |||
| 2365 | if( s_initCount == 0) | 2358 | if( s_initCount == 0) |
| 2366 | { | 2359 | { |
| 2367 | static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; | 2360 | static pthread_mutex_t my_lock= PTHREAD_MUTEX_INITIALIZER; |
| 2368 | pthread_mutex_lock(&my_lock); | 2361 | pthread_mutex_lock( &my_lock); |
| 2369 | { | 2362 | { |
| 2370 | // Recheck now that we're within the lock | 2363 | // Recheck now that we're within the lock |
| 2371 | // | 2364 | // |
| 2372 | if (s_initCount == 0) | 2365 | if( s_initCount == 0) |
| 2373 | { | 2366 | { |
| 2374 | init_once_LOCKED(L, &timer_deep, nbKeepers); | 2367 | init_once_LOCKED( L, &timer_deep, nbKeepers, on_state_create); |
| 2375 | s_initCount = 1; | 2368 | s_initCount = 1; |
| 2376 | } | 2369 | } |
| 2377 | } | 2370 | } |
| @@ -2451,10 +2444,11 @@ luaopen_lanes( lua_State *L ) | |||
| 2451 | { | 2444 | { |
| 2452 | lua_setfield( L, -2, "configure"); | 2445 | lua_setfield( L, -2, "configure"); |
| 2453 | } | 2446 | } |
| 2454 | else // already initialized: call it mmediately and be done | 2447 | else // already initialized: call it immediately and be done |
| 2455 | { | 2448 | { |
| 2456 | lua_pushinteger( L, 666); // any value will do, it will be ignored | 2449 | lua_pushinteger( L, 666); // any value will do, it will be ignored |
| 2457 | lua_call( L, 1, 0); | 2450 | lua_pushnil( L); // almost idem |
| 2451 | lua_call( L, 2, 0); | ||
| 2458 | } | 2452 | } |
| 2459 | STACK_END( L, 1) | 2453 | STACK_END( L, 1) |
| 2460 | return 1; | 2454 | return 1; |
diff --git a/src/lanes.lua b/src/lanes.lua index d56e05f..ec5a4e4 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
| @@ -45,13 +45,21 @@ THE SOFTWARE. | |||
| 45 | -- -> simply create a table, populate it, return it, and be done | 45 | -- -> simply create a table, populate it, return it, and be done |
| 46 | local lanes = {} | 46 | local lanes = {} |
| 47 | 47 | ||
| 48 | lanes.configure = function( _nb_keepers, _timers) | 48 | lanes.configure = function( _params) |
| 49 | _params = _params or { nb_keepers = 1, with_timers = true, on_state_create = nil} | ||
| 50 | if type( _params) ~= "table" then | ||
| 51 | error( "Bad parameter #1 to lanes.configure(), should be a table") | ||
| 52 | end | ||
| 53 | -- on_state_create may be nil or a function | ||
| 54 | if _params.on_state_create and (type( _params.on_state_create) ~= "function") then | ||
| 55 | error( "Bad on_state_create: " .. tostring( _params.on_state_create), 2) | ||
| 56 | end | ||
| 49 | 57 | ||
| 50 | local mm = require "lua51-lanes" | 58 | local mm = require "lua51-lanes" |
| 51 | assert( type(mm)=="table" ) | 59 | assert( type(mm)=="table" ) |
| 52 | 60 | ||
| 53 | -- configure() is available only the first time lua51-lanes is required process-wide, and we *must* call it to have the other functions in the interface | 61 | -- configure() is available only the first time lua51-lanes is required process-wide, and we *must* call it to have the other functions in the interface |
| 54 | if mm.configure then mm.configure( _nb_keepers) end | 62 | if mm.configure then mm.configure( _params.nb_keepers, _params.on_state_create) end |
| 55 | 63 | ||
| 56 | local thread_new = assert(mm.thread_new) | 64 | local thread_new = assert(mm.thread_new) |
| 57 | 65 | ||
| @@ -238,7 +246,7 @@ local function gen( ... ) | |||
| 238 | -- Lane generator | 246 | -- Lane generator |
| 239 | -- | 247 | -- |
| 240 | return function(...) | 248 | return function(...) |
| 241 | return thread_new( func, libs, cs, prio, g_tbl, package_tbl, required, ...) -- args | 249 | return thread_new( func, libs, _params.on_state_create, cs, prio, g_tbl, package_tbl, required, ...) -- args |
| 242 | end | 250 | end |
| 243 | end | 251 | end |
| 244 | 252 | ||
| @@ -258,7 +266,7 @@ local linda = mm.linda | |||
| 258 | -- PUBLIC LANES API | 266 | -- PUBLIC LANES API |
| 259 | local timer = function() error "timers are not active" end | 267 | local timer = function() error "timers are not active" end |
| 260 | 268 | ||
| 261 | if _timers ~= "NO_TIMERS" then | 269 | if _params.with_timers ~= false then |
| 262 | 270 | ||
| 263 | local timer_gateway= assert( mm.timer_gateway ) | 271 | local timer_gateway= assert( mm.timer_gateway ) |
| 264 | -- | 272 | -- |
| @@ -477,7 +485,7 @@ timer = function( linda, key, a, period ) | |||
| 477 | timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) | 485 | timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) |
| 478 | end | 486 | end |
| 479 | 487 | ||
| 480 | end -- _timers | 488 | end -- _params.with_timers |
| 481 | 489 | ||
| 482 | ---=== Lock & atomic generators ===--- | 490 | ---=== Lock & atomic generators ===--- |
| 483 | 491 | ||
| @@ -552,12 +560,16 @@ end | |||
| 552 | lanes.genlock = genlock | 560 | lanes.genlock = genlock |
| 553 | lanes.genatomic = genatomic | 561 | lanes.genatomic = genatomic |
| 554 | -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation | 562 | -- from now on, calling configure does nothing but checking that we don't call it with parameters that changed compared to the first invocation |
| 555 | lanes.configure = function( _nk, _t) | 563 | lanes.configure = function( _params2) |
| 556 | if _nk ~= _nb_keepers then | 564 | _params2 = _params2 or _params |
| 557 | error( "mismatched configuration: " .. tostring( _nk) .. " keepers instead of " .. tostring( _nb_keepers)) | 565 | if _params2.nb_keepers ~= _params.nb_keepers then |
| 566 | error( "mismatched configuration: " .. tostring( _params2.nb_keepers) .. " keepers instead of " .. tostring( _params.nb_keepers)) | ||
| 567 | end | ||
| 568 | if _params2.with_timers ~= _params.with_timers then | ||
| 569 | error( "mismatched configuration: " .. tostring( _params2.with_timers) .. " timer activity instead of " .. tostring( _params.with_timers)) | ||
| 558 | end | 570 | end |
| 559 | if _t ~= _timers then | 571 | if _params2.on_create_state and _params2.on_create_state ~= _params.on_create_state then |
| 560 | error( "mismatched configuration: " .. tostring( _t) .. " timer activity instead of " .. tostring( _timers)) | 572 | error( "mismatched configuration: " .. tostring( _params2.on_create_state) .. " timer activity instead of " .. tostring( _params.on_create_state)) |
| 561 | end | 573 | end |
| 562 | return lanes | 574 | return lanes |
| 563 | end | 575 | end |
diff --git a/src/tools.c b/src/tools.c index 85672e2..212cf52 100644 --- a/src/tools.c +++ b/src/tools.c | |||
| @@ -91,7 +91,7 @@ void luaG_dump( lua_State* L ) { | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | 93 | ||
| 94 | /*---=== luaG_openlibs ===---*/ | 94 | /*---=== luaG_newstate ===---*/ |
| 95 | 95 | ||
| 96 | static const luaL_Reg libs[] = { | 96 | static const luaL_Reg libs[] = { |
| 97 | { LUA_LOADLIBNAME, luaopen_package }, | 97 | { LUA_LOADLIBNAME, luaopen_package }, |
| @@ -371,7 +371,7 @@ static void populate_func_lookup_table_recur( lua_State *L, int _ctx_base, int _ | |||
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | /* | 373 | /* |
| 374 | * create a "fully.qualified.name" <-> function equivalence dabase | 374 | * create a "fully.qualified.name" <-> function equivalence database |
| 375 | */ | 375 | */ |
| 376 | void populate_func_lookup_table( lua_State *L, int _i, char const *_name) | 376 | void populate_func_lookup_table( lua_State *L, int _i, char const *_name) |
| 377 | { | 377 | { |
| @@ -422,39 +422,52 @@ void populate_func_lookup_table( lua_State *L, int _i, char const *_name) | |||
| 422 | */ | 422 | */ |
| 423 | #define is_name_char(c) (isalpha(c) || (c)=='*') | 423 | #define is_name_char(c) (isalpha(c) || (c)=='*') |
| 424 | 424 | ||
| 425 | const char *luaG_openlibs( lua_State *L, const char *libs) | 425 | lua_State* luaG_newstate( char const* libs, lua_CFunction _on_state_create) |
| 426 | { | 426 | { |
| 427 | const char *p; | 427 | char const* p; |
| 428 | unsigned len; | 428 | unsigned int len; |
| 429 | lua_State* const L = luaL_newstate(); | ||
| 429 | 430 | ||
| 430 | if (!libs) return NULL; // no libs, not even 'base' | 431 | // no libs, or special init func (not even 'base') |
| 431 | 432 | if (libs || _on_state_create) | |
| 432 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | ||
| 433 | // | ||
| 434 | lua_gc( L, LUA_GCSTOP, 0); | ||
| 435 | |||
| 436 | // Anything causes 'base' to be taken in | ||
| 437 | // | ||
| 438 | STACK_GROW(L,2); | ||
| 439 | STACK_CHECK(L) | ||
| 440 | lua_pushcfunction( L, luaopen_base); | ||
| 441 | lua_call( L, 0, 1); | ||
| 442 | // after opening base, register the functions they exported in our name<->function database | ||
| 443 | populate_func_lookup_table( L, LUA_GLOBALSINDEX, NULL); | ||
| 444 | lua_pop( L, 1); | ||
| 445 | STACK_MID( L, 0); | ||
| 446 | for( p= libs; *p; p+=len ) | ||
| 447 | { | 433 | { |
| 448 | len=0; | 434 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) |
| 449 | while (*p && !is_name_char(*p)) p++; // bypass delimiters | 435 | // |
| 450 | while (is_name_char(p[len])) len++; // bypass name | 436 | lua_gc( L, LUA_GCSTOP, 0); |
| 451 | if (len && (!openlib( L, p, len ))) | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | STACK_END(L,0) | ||
| 455 | lua_gc(L, LUA_GCRESTART, 0); | ||
| 456 | 437 | ||
| 457 | return *p ? p : NULL; | 438 | // Anything causes 'base' to be taken in |
| 439 | // | ||
| 440 | STACK_GROW( L, 2); | ||
| 441 | STACK_CHECK( L) | ||
| 442 | if( _on_state_create) | ||
| 443 | { | ||
| 444 | lua_pushcfunction( L, _on_state_create); | ||
| 445 | lua_call( L, 0, 0); | ||
| 446 | } | ||
| 447 | if( libs) | ||
| 448 | { | ||
| 449 | lua_pushcfunction( L, luaopen_base); | ||
| 450 | lua_call( L, 0, 0); | ||
| 451 | } | ||
| 452 | // after opening base, register the functions it exported in our name<->function database | ||
| 453 | populate_func_lookup_table( L, LUA_GLOBALSINDEX, NULL); | ||
| 454 | STACK_MID( L, 0); | ||
| 455 | if( libs) | ||
| 456 | { | ||
| 457 | for( p = libs; *p; p += len) | ||
| 458 | { | ||
| 459 | len=0; | ||
| 460 | while (*p && !is_name_char(*p)) p++; // bypass delimiters | ||
| 461 | while (is_name_char(p[len])) len++; // bypass name | ||
| 462 | if (len && (!openlib( L, p, len ))) | ||
| 463 | break; | ||
| 464 | } | ||
| 465 | serialize_require( L); | ||
| 466 | } | ||
| 467 | STACK_END(L,0) | ||
| 468 | lua_gc( L, LUA_GCRESTART, 0); | ||
| 469 | } | ||
| 470 | return L; | ||
| 458 | } | 471 | } |
| 459 | 472 | ||
| 460 | 473 | ||
| @@ -1317,7 +1330,7 @@ static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uin | |||
| 1317 | else | 1330 | else |
| 1318 | { | 1331 | { |
| 1319 | if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop(L), VT_NORMAL)) | 1332 | if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop(L), VT_NORMAL)) |
| 1320 | luaL_error( L, "Cannot copy upvalue type '%s'", luaG_typename( L, -1)); | 1333 | luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); |
| 1321 | } | 1334 | } |
| 1322 | lua_pop( L, 1); | 1335 | lua_pop( L, 1); |
| 1323 | } | 1336 | } |
| @@ -1475,7 +1488,7 @@ static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, u | |||
| 1475 | lua_rawset( L2, -3 ); // add to table (pops key & val) | 1488 | lua_rawset( L2, -3 ); // add to table (pops key & val) |
| 1476 | } else { | 1489 | } else { |
| 1477 | luaL_error( L, "Unable to copy over type '%s' (in %s)", | 1490 | luaL_error( L, "Unable to copy over type '%s' (in %s)", |
| 1478 | luaG_typename(L,val_i), | 1491 | luaL_typename(L,val_i), |
| 1479 | vt==VT_NORMAL ? "table":"metatable" ); | 1492 | vt==VT_NORMAL ? "table":"metatable" ); |
| 1480 | } | 1493 | } |
| 1481 | } | 1494 | } |
| @@ -1647,7 +1660,7 @@ static int new_require( lua_State *L) | |||
| 1647 | { | 1660 | { |
| 1648 | int rc, i; | 1661 | int rc, i; |
| 1649 | int args = lua_gettop( L); | 1662 | int args = lua_gettop( L); |
| 1650 | //char const *modname = luaL_checkstring( L, 1); | 1663 | //char const* modname = luaL_checkstring( L, 1); |
| 1651 | 1664 | ||
| 1652 | STACK_GROW( L, args + 1); | 1665 | STACK_GROW( L, args + 1); |
| 1653 | STACK_CHECK( L) | 1666 | STACK_CHECK( L) |
diff --git a/src/tools.h b/src/tools.h index 1c9b00a..67f9874 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -46,13 +46,11 @@ | |||
| 46 | 46 | ||
| 47 | #define luaG_isany(L,i) (!lua_isnil(L,i)) | 47 | #define luaG_isany(L,i) (!lua_isnil(L,i)) |
| 48 | 48 | ||
| 49 | #define luaG_typename( L, index ) lua_typename( L, lua_type(L,index) ) | ||
| 50 | |||
| 51 | typedef void (*luaG_IdFunction)( lua_State *L, char const * const which); | 49 | typedef void (*luaG_IdFunction)( lua_State *L, char const * const which); |
| 52 | 50 | ||
| 53 | void luaG_dump( lua_State* L ); | 51 | void luaG_dump( lua_State* L ); |
| 54 | 52 | ||
| 55 | const char *luaG_openlibs( lua_State *L, const char *libs ); | 53 | lua_State* luaG_newstate( char const* libs, lua_CFunction _on_state_create); |
| 56 | 54 | ||
| 57 | int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc); | 55 | int luaG_deep_userdata( lua_State *L, luaG_IdFunction idfunc); |
| 58 | void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index ); | 56 | void *luaG_todeep( lua_State *L, luaG_IdFunction idfunc, int index ); |
