aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-02-21 20:33:39 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-02-21 20:33:39 +0100
commit974aa4343cf900938b5d357d10798d91faf60f5a (patch)
treeb71a342e26ce04c447955f2fc135b69760ab7837 /src
parent1760eafa1d2ebce8f07e11414a53d4a251af5b8e (diff)
downloadlanes-974aa4343cf900938b5d357d10798d91faf60f5a.tar.gz
lanes-974aa4343cf900938b5d357d10798d91faf60f5a.tar.bz2
lanes-974aa4343cf900938b5d357d10798d91faf60f5a.zip
Make the number of internal keeper states selectable by an optional parameter passed to require.
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c39
-rw-r--r--src/keeper.h2
-rw-r--r--src/lanes.c33
-rw-r--r--src/lanes.lua2
4 files changed, 32 insertions, 44 deletions
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 @@
53/*---=== Keeper states ===--- 53/*---=== Keeper states ===---
54*/ 54*/
55 55
56/* The selected number is not optimal; needs to be tested. Even using just
57* one keeper state may be good enough (depends on the number of Lindas used
58* in the applications).
59*/
60#define KEEPER_STATES_N 1 // 6
61
62/* 56/*
63* Pool of keeper states 57* Pool of keeper states
64* 58*
@@ -66,12 +60,8 @@
66* bigger the pool, the less chances of unnecessary waits. Lindas map to the 60* bigger the pool, the less chances of unnecessary waits. Lindas map to the
67* keepers randomly, by a hash. 61* keepers randomly, by a hash.
68*/ 62*/
69static struct s_Keeper GKeepers[KEEPER_STATES_N]; 63static struct s_Keeper *GKeepers = NULL;
70 64static int GNbKeepers = 0;
71/* We could use an empty table in 'keeper.lua' as the sentinel, but maybe
72* checking for a lightuserdata is faster.
73*/
74static bool_t nil_sentinel = 0;
75 65
76/* 66/*
77* Lua code for the keeper states (baked in) 67* Lua code for the keeper states (baked in)
@@ -88,10 +78,13 @@ static char const keeper_chunk[]=
88* unclosed, because it does not really matter. In production code, this 78* unclosed, because it does not really matter. In production code, this
89* function never fails. 79* function never fails.
90*/ 80*/
91const char *init_keepers(void) 81char const *init_keepers( int const _nbKeepers)
92{ 82{
93 unsigned int i; 83 int i;
94 for( i=0; i<KEEPER_STATES_N; i++ ) 84 assert( _nbKeepers >= 1);
85 GNbKeepers = _nbKeepers;
86 GKeepers = malloc( _nbKeepers * sizeof( struct s_Keeper));
87 for( i = 0; i < _nbKeepers; ++ i)
95 { 88 {
96 89
97 // Initialize Keeper states with bare minimum of libs (those required 90 // Initialize Keeper states with bare minimum of libs (those required
@@ -104,8 +97,11 @@ const char *init_keepers(void)
104 luaG_openlibs( L, "io,table,package" ); // 'io' for debugging messages, package because we need to require modules exporting idfuncs 97 luaG_openlibs( L, "io,table,package" ); // 'io' for debugging messages, package because we need to require modules exporting idfuncs
105 serialize_require( L); 98 serialize_require( L);
106 99
107 lua_pushlightuserdata( L, &nil_sentinel ); 100 /* We could use an empty table in 'keeper.lua' as the sentinel, but maybe
108 lua_setglobal( L, "nil_sentinel" ); 101 * checking for a lightuserdata is faster. (any unique value will do -> take the address of some global of ours)
102 */
103 lua_pushlightuserdata( L, &GNbKeepers);
104 lua_setglobal( L, "nil_sentinel");
109 105
110 // Read in the preloaded chunk (and run it) 106 // Read in the preloaded chunk (and run it)
111 // 107 //
@@ -131,12 +127,12 @@ const char *init_keepers(void)
131struct s_Keeper *keeper_acquire( const void *ptr) 127struct s_Keeper *keeper_acquire( const void *ptr)
132{ 128{
133 /* 129 /*
134 * Any hashing will do that maps pointers to 0..KEEPER_STATES_N-1 130 * Any hashing will do that maps pointers to 0..GNbKeepers-1
135 * consistently. 131 * consistently.
136 * 132 *
137 * Pointers are often aligned by 8 or so - ignore the low order bits 133 * Pointers are often aligned by 8 or so - ignore the low order bits
138 */ 134 */
139 unsigned int i= ((unsigned long)(ptr) >> 3) % KEEPER_STATES_N; 135 unsigned int i= ((unsigned long)(ptr) >> 3) % GNbKeepers;
140 struct s_Keeper *K= &GKeepers[i]; 136 struct s_Keeper *K= &GKeepers[i];
141 137
142 MUTEX_LOCK( &K->lock_); 138 MUTEX_LOCK( &K->lock_);
@@ -190,10 +186,13 @@ int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda,
190void close_keepers(void) 186void close_keepers(void)
191{ 187{
192 int i; 188 int i;
193 for(i=0;i<KEEPER_STATES_N;i++) 189 for( i = 0; i < GNbKeepers; ++ i)
194 { 190 {
195 lua_close( GKeepers[i].L); 191 lua_close( GKeepers[i].L);
196 GKeepers[i].L = 0; 192 GKeepers[i].L = 0;
197 //assert( GKeepers[i].count == 0); 193 //assert( GKeepers[i].count == 0);
198 } 194 }
195 if( GKeepers) free( GKeepers);
196 GKeepers = NULL;
197 GNbKeepers = 0;
199} 198}
diff --git a/src/keeper.h b/src/keeper.h
index 66d8d7e..e959c7c 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
11const char *init_keepers(void); 11const char *init_keepers( int const _nbKeepers);
12struct s_Keeper *keeper_acquire( const void *ptr); 12struct s_Keeper *keeper_acquire( const void *ptr);
13void keeper_release( struct s_Keeper *K); 13void keeper_release( struct s_Keeper *K);
14int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); 14int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index);
diff --git a/src/lanes.c b/src/lanes.c
index a8aba71..8b62532 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -4,20 +4,7 @@
4 * Multithreading in Lua. 4 * Multithreading in Lua.
5 * 5 *
6 * History: 6 * History:
7 * 3-Jan-11 (2.0.10): linda_send bugfix, was waiting on the wrong signal 7 * See CHANGES
8 * 3-Dec-10 (2.0.9): Added support to generate a lane from a string
9 * 2-Dec-10 (2.0.8): Fix LuaJIT2 incompatibility (no 'tostring' hijack anymore)
10 * ???????? (2.0.7): Fixed 'memory leak' in some situations where a free running
11 * lane is collected before application shutdown
12 * 24-Aug-10 (2.0.6): Mem fixes, argument checking (lua_toLinda result), thread name
13 * 24-Jun-09 (2.0.4): Made friendly to already multithreaded host apps.
14 * 20-Oct-08 (2.0.2): Added closing of free-running threads, but it does
15 * not seem to eliminate the occasional segfaults at process
16 * exit.
17 * ...
18 * 24-Jun-08 .. 14-Aug-08 AKa: Major revise, Lanes 2008 version (2.0 rc1)
19 * ...
20 * 18-Sep-06 AKa: Started the module.
21 * 8 *
22 * Platforms (tested internally): 9 * Platforms (tested internally):
23 * OS X (10.5.7 PowerPC/Intel) 10 * OS X (10.5.7 PowerPC/Intel)
@@ -64,7 +51,7 @@
64 * ... 51 * ...
65 */ 52 */
66 53
67const char *VERSION= "2.0.11"; 54const char *VERSION= "2.1.0";
68 55
69/* 56/*
70=============================================================================== 57===============================================================================
@@ -1913,7 +1900,7 @@ static const struct luaL_reg lanes_functions [] = {
1913/* 1900/*
1914* One-time initializations 1901* One-time initializations
1915*/ 1902*/
1916static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref ) 1903static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref, int const nbKeepers)
1917{ 1904{
1918 const char *err; 1905 const char *err;
1919 1906
@@ -1964,7 +1951,7 @@ static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_
1964 } 1951 }
1965 #endif 1952 #endif
1966#endif 1953#endif
1967 err= init_keepers(); 1954 err= init_keepers( nbKeepers);
1968 if (err) 1955 if (err)
1969 { 1956 {
1970 luaL_error( L, "Unable to initialize: %s", err ); 1957 luaL_error( L, "Unable to initialize: %s", err );
@@ -2001,8 +1988,11 @@ int
2001#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 1988#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
2002__declspec(dllexport) 1989__declspec(dllexport)
2003#endif 1990#endif
2004 luaopen_lanes( lua_State *L ) { 1991luaopen_lanes( lua_State *L )
2005 1992{
1993 static volatile int /*bool*/ go_ahead; // = 0
1994 int const nbKeepers = luaL_optint( L, 2, 1);
1995 luaL_argcheck( L, nbKeepers > 0, 2, "Number of keeper states must be > 0");
2006 /* 1996 /*
2007 * Making one-time initializations. 1997 * Making one-time initializations.
2008 * 1998 *
@@ -2010,7 +2000,6 @@ __declspec(dllexport)
2010 * there is no problem. But if the host is multithreaded, we need to lock around the 2000 * there is no problem. But if the host is multithreaded, we need to lock around the
2011 * initializations. 2001 * initializations.
2012 */ 2002 */
2013 static volatile int /*bool*/ go_ahead; // = 0
2014#ifdef PLATFORM_WIN32 2003#ifdef PLATFORM_WIN32
2015 { 2004 {
2016 // TBD: Someone please replace this with reliable Win32 API code. Problem is, 2005 // TBD: Someone please replace this with reliable Win32 API code. Problem is,
@@ -2022,7 +2011,7 @@ __declspec(dllexport)
2022 static volatile unsigned my_number; // = 0 2011 static volatile unsigned my_number; // = 0
2023 2012
2024 if (my_number++ == 0) { // almost atomic 2013 if (my_number++ == 0) { // almost atomic
2025 init_once_LOCKED(L, &timer_deep); 2014 init_once_LOCKED(L, &timer_deep, nbKeepers);
2026 go_ahead= 1; // let others pass 2015 go_ahead= 1; // let others pass
2027 } else { 2016 } else {
2028 while( !go_ahead ) { Sleep(1); } // changes threads 2017 while( !go_ahead ) { Sleep(1); } // changes threads
@@ -2036,7 +2025,7 @@ __declspec(dllexport)
2036 // Recheck now that we're within the lock 2025 // Recheck now that we're within the lock
2037 // 2026 //
2038 if (!go_ahead) { 2027 if (!go_ahead) {
2039 init_once_LOCKED(L, &timer_deep); 2028 init_once_LOCKED(L, &timer_deep, nbKeepers);
2040 go_ahead= 1; 2029 go_ahead= 1;
2041 } 2030 }
2042 } 2031 }
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)
52 52
53local now_secs= assert( mm.now_secs ) 53local now_secs= assert( mm.now_secs )
54local wakeup_conv= assert( mm.wakeup_conv ) 54local wakeup_conv= assert( mm.wakeup_conv )
55local timer_gateway= assert( mm.timer_gateway )
56 55
57local max_prio= assert( mm.max_prio ) 56local max_prio= assert( mm.max_prio )
58 57
@@ -239,6 +238,7 @@ linda = mm.linda
239 238
240---=== Timers ===--- 239---=== Timers ===---
241 240
241local timer_gateway= assert( mm.timer_gateway )
242-- 242--
243-- On first 'require "lanes"', a timer lane is spawned that will maintain 243-- On first 'require "lanes"', a timer lane is spawned that will maintain
244-- timer tables and sleep in between the timer events. All interaction with 244-- timer tables and sleep in between the timer events. All interaction with