From 974aa4343cf900938b5d357d10798d91faf60f5a Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 21 Feb 2011 20:33:39 +0100 Subject: Make the number of internal keeper states selectable by an optional parameter passed to require. --- src/keeper.c | 39 +++++++++++++++++++-------------------- src/keeper.h | 2 +- src/lanes.c | 33 +++++++++++---------------------- src/lanes.lua | 2 +- 4 files changed, 32 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/keeper.c b/src/keeper.c index f19beed..f89c638 100644 --- a/src/keeper.c +++ b/src/keeper.c @@ -53,12 +53,6 @@ /*---=== Keeper states ===--- */ -/* The selected number is not optimal; needs to be tested. Even using just -* one keeper state may be good enough (depends on the number of Lindas used -* in the applications). -*/ -#define KEEPER_STATES_N 1 // 6 - /* * Pool of keeper states * @@ -66,12 +60,8 @@ * bigger the pool, the less chances of unnecessary waits. Lindas map to the * keepers randomly, by a hash. */ -static struct s_Keeper GKeepers[KEEPER_STATES_N]; - -/* We could use an empty table in 'keeper.lua' as the sentinel, but maybe -* checking for a lightuserdata is faster. -*/ -static bool_t nil_sentinel = 0; +static struct s_Keeper *GKeepers = NULL; +static int GNbKeepers = 0; /* * Lua code for the keeper states (baked in) @@ -88,10 +78,13 @@ static char const keeper_chunk[]= * unclosed, because it does not really matter. In production code, this * function never fails. */ -const char *init_keepers(void) +char const *init_keepers( int const _nbKeepers) { - unsigned int i; - for( i=0; i= 1); + GNbKeepers = _nbKeepers; + GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper)); + for( i = 0; i < _nbKeepers; ++ i) { // Initialize Keeper states with bare minimum of libs (those required @@ -104,8 +97,11 @@ const char *init_keepers(void) luaG_openlibs( L, "io,table,package" ); // 'io' for debugging messages, package because we need to require modules exporting idfuncs serialize_require( L); - lua_pushlightuserdata( L, &nil_sentinel ); - lua_setglobal( L, "nil_sentinel" ); + /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe + * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours) + */ + lua_pushlightuserdata( L, &GNbKeepers); + lua_setglobal( L, "nil_sentinel"); // Read in the preloaded chunk (and run it) // @@ -131,12 +127,12 @@ const char *init_keepers(void) struct s_Keeper *keeper_acquire( const void *ptr) { /* - * Any hashing will do that maps pointers to 0..KEEPER_STATES_N-1 + * Any hashing will do that maps pointers to 0..GNbKeepers-1 * consistently. * * Pointers are often aligned by 8 or so - ignore the low order bits */ - unsigned int i= ((unsigned long)(ptr) >> 3) % KEEPER_STATES_N; + unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers; struct s_Keeper *K= &GKeepers[i]; MUTEX_LOCK( &K->lock_); @@ -190,10 +186,13 @@ int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, void close_keepers(void) { int i; - for(i=0;i 0, 2, "Number of keeper states must be > 0"); /* * Making one-time initializations. * @@ -2010,7 +2000,6 @@ __declspec(dllexport) * there is no problem. But if the host is multithreaded, we need to lock around the * initializations. */ - static volatile int /*bool*/ go_ahead; // = 0 #ifdef PLATFORM_WIN32 { // TBD: Someone please replace this with reliable Win32 API code. Problem is, @@ -2022,7 +2011,7 @@ __declspec(dllexport) static volatile unsigned my_number; // = 0 if (my_number++ == 0) { // almost atomic - init_once_LOCKED(L, &timer_deep); + init_once_LOCKED(L, &timer_deep, nbKeepers); go_ahead= 1; // let others pass } else { while( !go_ahead ) { Sleep(1); } // changes threads @@ -2036,7 +2025,7 @@ __declspec(dllexport) // Recheck now that we're within the lock // if (!go_ahead) { - init_once_LOCKED(L, &timer_deep); + init_once_LOCKED(L, &timer_deep, nbKeepers); go_ahead= 1; } } diff --git a/src/lanes.lua b/src/lanes.lua index 95bdeeb..78582f9 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -52,7 +52,6 @@ local _version= assert(mm._version) local now_secs= assert( mm.now_secs ) local wakeup_conv= assert( mm.wakeup_conv ) -local timer_gateway= assert( mm.timer_gateway ) local max_prio= assert( mm.max_prio ) @@ -239,6 +238,7 @@ linda = mm.linda ---=== Timers ===--- +local timer_gateway= assert( mm.timer_gateway ) -- -- On first 'require "lanes"', a timer lane is spawned that will maintain -- timer tables and sleep in between the timer events. All interaction with -- cgit v1.2.3-55-g6feb