diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2011-02-21 20:33:39 +0100 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2011-02-21 20:33:39 +0100 |
commit | 974aa4343cf900938b5d357d10798d91faf60f5a (patch) | |
tree | b71a342e26ce04c447955f2fc135b69760ab7837 /src | |
parent | 1760eafa1d2ebce8f07e11414a53d4a251af5b8e (diff) | |
download | lanes-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.c | 39 | ||||
-rw-r--r-- | src/keeper.h | 2 | ||||
-rw-r--r-- | src/lanes.c | 33 | ||||
-rw-r--r-- | src/lanes.lua | 2 |
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 | */ |
69 | static struct s_Keeper GKeepers[KEEPER_STATES_N]; | 63 | static struct s_Keeper *GKeepers = NULL; |
70 | 64 | static 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 | */ | ||
74 | static 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 | */ |
91 | const char *init_keepers(void) | 81 | char 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) | |||
131 | struct s_Keeper *keeper_acquire( const void *ptr) | 127 | struct 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, | |||
190 | void close_keepers(void) | 186 | void 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 | ||
11 | const char *init_keepers(void); | 11 | const char *init_keepers( int const _nbKeepers); |
12 | struct s_Keeper *keeper_acquire( const void *ptr); | 12 | struct s_Keeper *keeper_acquire( const void *ptr); |
13 | void keeper_release( struct s_Keeper *K); | 13 | void keeper_release( struct s_Keeper *K); |
14 | int keeper_call( lua_State *K, char const *func_name, lua_State *L, void *linda, uint_t starting_index); | 14 | int 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 | ||
67 | const char *VERSION= "2.0.11"; | 54 | const 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 | */ |
1916 | static void init_once_LOCKED( lua_State *L, volatile DEEP_PRELUDE ** timer_deep_ref ) | 1903 | static 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 ) { | 1991 | luaopen_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 | ||
53 | local now_secs= assert( mm.now_secs ) | 53 | local now_secs= assert( mm.now_secs ) |
54 | local wakeup_conv= assert( mm.wakeup_conv ) | 54 | local wakeup_conv= assert( mm.wakeup_conv ) |
55 | local timer_gateway= assert( mm.timer_gateway ) | ||
56 | 55 | ||
57 | local max_prio= assert( mm.max_prio ) | 56 | local max_prio= assert( mm.max_prio ) |
58 | 57 | ||
@@ -239,6 +238,7 @@ linda = mm.linda | |||
239 | 238 | ||
240 | ---=== Timers ===--- | 239 | ---=== Timers ===--- |
241 | 240 | ||
241 | local 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 |