summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c94
-rw-r--r--src/keeper.h1
-rw-r--r--src/lanes-keeper.lua4
-rw-r--r--src/lanes.c29
-rw-r--r--src/lanes.lua4
5 files changed, 107 insertions, 25 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 338f794..83ec8f3 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -128,20 +128,31 @@ static void fifo_peek( lua_State* L, keeper_fifo* fifo, int _count)
128} 128}
129 129
130// in: fifo 130// in: fifo
131// out: pushes as many items as required on the stack (function assumes they exist in sufficient number) 131// out: remove the fifo from the stack, push as many items as required on the stack (function assumes they exist in sufficient number)
132static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count) 132static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count)
133{ 133{
134 int fifo_idx = lua_gettop( L); // ... fifo 134 int fifo_idx = lua_gettop( L); // ... fifo
135 int i; 135 int i;
136 // each iteration pushes a value on the stack! 136 // each iteration pushes a value on the stack!
137 STACK_GROW( L, _count + 1); 137 STACK_GROW( L, _count + 2);
138 for( i = 0; i < _count; ++ i) 138 // skip first item, we will push it last
139 for( i = 1; i < _count; ++ i)
139 { 140 {
140 int at = fifo->first + i; 141 int const at = fifo->first + i;
142 // push item on the stack
141 lua_rawgeti( L, fifo_idx, at); // ... fifo val 143 lua_rawgeti( L, fifo_idx, at); // ... fifo val
144 // remove item from the fifo
142 lua_pushnil( L); // ... fifo val nil 145 lua_pushnil( L); // ... fifo val nil
143 lua_rawseti( L, fifo_idx, at); // ... fifo val 146 lua_rawseti( L, fifo_idx, at); // ... fifo val
144 } 147 }
148 // now process first item
149 {
150 int const at = fifo->first;
151 lua_rawgeti( L, fifo_idx, at); // ... fifo vals val
152 lua_pushnil( L); // ... fifo vals val nil
153 lua_rawseti( L, fifo_idx, at); // ... fifo vals val
154 lua_replace( L, fifo_idx); // ... vals
155 }
145 fifo->first += _count; 156 fifo->first += _count;
146 fifo->count -= _count; 157 fifo->count -= _count;
147} 158}
@@ -172,6 +183,47 @@ static void push_table( lua_State* L, int idx)
172 STACK_END( L, 1); 183 STACK_END( L, 1);
173} 184}
174 185
186int keeper_push_linda_storage( lua_State* L, void* ptr)
187{
188 struct s_Keeper* K = keeper_acquire( ptr);
189 STACK_CHECK( K->L)
190 lua_pushlightuserdata( K->L, fifos_key); // fifos_key
191 lua_rawget( K->L, LUA_REGISTRYINDEX); // fifos
192 lua_pushlightuserdata( K->L, ptr); // fifos ud
193 lua_rawget( K->L, -2); // fifos storage
194 lua_remove( K->L, -2); // storage
195 if( !lua_istable( K->L, -1))
196 {
197 lua_pop( K->L, 1); //
198 STACK_MID( K->L, 0);
199 return 0;
200 }
201 lua_pushnil( K->L); // storage nil
202 lua_newtable( L); // out
203 while( lua_next( K->L, -2)) // storage key fifo
204 {
205 keeper_fifo* fifo = prepare_fifo_access( K->L, -1); // storage key fifo
206 lua_pushvalue( K->L, -2); // storage key fifo key
207 luaG_inter_move( K->L, L, 1); // storage key fifo // out key
208 STACK_CHECK( L)
209 lua_newtable( L); // out key keyout
210 luaG_inter_move( K->L, L, 1); // storage key // out key keyout fifo
211 lua_pushinteger( L, fifo->first); // out key keyout fifo first
212 lua_setfield( L, -3, "first"); // out key keyout fifo
213 lua_pushinteger( L, fifo->count); // out key keyout fifo count
214 lua_setfield( L, -3, "count"); // out key keyout fifo
215 lua_pushinteger( L, fifo->limit); // out key keyout fifo limit
216 lua_setfield( L, -3, "limit"); // out key keyout fifo
217 lua_setfield( L, -2, "fifo"); // out key keyout
218 lua_rawset( L, -3); // out
219 STACK_END( L, 0)
220 }
221 lua_pop( K->L, 1); //
222 STACK_END( K->L, 0)
223 keeper_release( K);
224 return 1;
225}
226
175// in: linda_ud 227// in: linda_ud
176int keepercall_clear( lua_State* L) 228int keepercall_clear( lua_State* L)
177{ 229{
@@ -223,7 +275,7 @@ int keepercall_send( lua_State* L)
223} 275}
224 276
225// in: linda_ud, key [, key]? 277// in: linda_ud, key [, key]?
226// out: (val, key) or nothing 278// out: (key, val) or nothing
227int keepercall_receive( lua_State* L) 279int keepercall_receive( lua_State* L)
228{ 280{
229 int top = lua_gettop( L); 281 int top = lua_gettop( L);
@@ -238,16 +290,17 @@ int keepercall_receive( lua_State* L)
238 fifo = prepare_fifo_access( L, -1); // fifos keys fifo 290 fifo = prepare_fifo_access( L, -1); // fifos keys fifo
239 if( fifo && fifo->count > 0) 291 if( fifo && fifo->count > 0)
240 { 292 {
241 fifo_pop( L, fifo, 1); // fifos keys fifo val 293 fifo_pop( L, fifo, 1); // fifos keys val
242 if( !lua_isnil( L, -1)) 294 if( !lua_isnil( L, -1))
243 { 295 {
244 lua_replace( L, 1); // val keys fifo 296 lua_replace( L, 1); // val keys
297 lua_settop( L, i); // val keys key[i]
245 if( i != 2) 298 if( i != 2)
246 { 299 {
247 lua_pushvalue( L, i); // val keys fifo key[i] 300 lua_replace( L, 2); // val key keys
248 lua_replace( L, 2); // val key keys fifo 301 lua_settop( L, 2); // val key
249 } 302 }
250 lua_settop( L, 2); // val key 303 lua_insert( L, 1); // key, val
251 return 2; 304 return 2;
252 } 305 }
253 } 306 }
@@ -266,16 +319,22 @@ int keepercall_receive_batched( lua_State* L)
266 keeper_fifo* fifo; 319 keeper_fifo* fifo;
267 int const max_count = (int) luaL_optinteger( L, 4, min_count); 320 int const max_count = (int) luaL_optinteger( L, 4, min_count);
268 lua_settop( L, 2); // ud key 321 lua_settop( L, 2); // ud key
269 push_table( L, 1); // ud key fifos 322 lua_insert( L, 1); // key ud
270 lua_replace( L, 1); // fifos key 323 push_table( L, 2); // key ud fifos
271 lua_rawget( L, -2); // fifos fifo 324 lua_remove( L, 2); // key fifos
272 lua_remove( L, 1); // fifo 325 lua_pushvalue( L, 1); // key fifos key
273 fifo = prepare_fifo_access( L, 1); // fifo 326 lua_rawget( L, 2); // key fifos fifo
327 lua_remove( L, 2); // key fifo
328 fifo = prepare_fifo_access( L, 2); // key fifo
274 if( fifo && fifo->count >= min_count) 329 if( fifo && fifo->count >= min_count)
275 { 330 {
276 fifo_pop( L, fifo, __min( max_count, fifo->count)); // fifo ... 331 fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ...
332 }
333 else
334 {
335 lua_settop( L, 0);
277 } 336 }
278 return lua_gettop( L) - 1; 337 return lua_gettop( L);
279 } 338 }
280 else 339 else
281 { 340 {
@@ -521,6 +580,7 @@ char const* init_keepers( int const _nbKeepers, lua_CFunction _on_state_create)
521 } 580 }
522 // call close_keepers at the very last as we want to be sure no thread is GCing after. 581 // call close_keepers at the very last as we want to be sure no thread is GCing after.
523 // (and therefore may perform linda object dereferencing after keepers are gone) 582 // (and therefore may perform linda object dereferencing after keepers are gone)
583 // problem: maybe on some platforms atexit() is called after DLL/so are unloaded...
524 atexit( atexit_close_keepers); 584 atexit( atexit_close_keepers);
525 return NULL; // ok 585 return NULL; // ok
526} 586}
diff --git a/src/keeper.h b/src/keeper.h
index a0ea8c5..a9b5a22 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -13,6 +13,7 @@ void populate_keepers( lua_State *L);
13struct s_Keeper *keeper_acquire( const void *ptr); 13struct s_Keeper *keeper_acquire( const void *ptr);
14void keeper_release( struct s_Keeper *K); 14void keeper_release( struct s_Keeper *K);
15void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); 15void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel);
16int keeper_push_linda_storage( lua_State* L, void* ptr);
16 17
17#define KEEPER_MODEL_LUA 1 18#define KEEPER_MODEL_LUA 1
18#define KEEPER_MODEL_C 2 19#define KEEPER_MODEL_C 2
diff --git a/src/lanes-keeper.lua b/src/lanes-keeper.lua
index b07d6a9..a03ef4b 100644
--- a/src/lanes-keeper.lua
+++ b/src/lanes-keeper.lua
@@ -187,7 +187,7 @@ function receive( ud, ...)
187 if fifo and fifo.count > 0 then 187 if fifo and fifo.count > 0 then
188 local val = fifo_pop( fifo, 1) 188 local val = fifo_pop( fifo, 1)
189 if val ~= nil then 189 if val ~= nil then
190 return val, key 190 return key, val
191 end 191 end
192 end 192 end
193 end 193 end
@@ -207,7 +207,7 @@ receive_batched = function( ud, key, min_count, max_count)
207 if fifo_count >= min_count then 207 if fifo_count >= min_count then
208 max_count = max_count or min_count 208 max_count = max_count or min_count
209 max_count = (max_count > fifo_count) and fifo_count or max_count 209 max_count = (max_count > fifo_count) and fifo_count or max_count
210 return fifo_pop( fifo, max_count) 210 return key, fifo_pop( fifo, max_count)
211 end 211 end
212 end 212 end
213 end 213 end
diff --git a/src/lanes.c b/src/lanes.c
index eac4753..f2e8aa7 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -51,7 +51,7 @@
51 * ... 51 * ...
52 */ 52 */
53 53
54char const* VERSION = "3.3.0"; 54char const* VERSION = "3.4.0";
55 55
56/* 56/*
57=============================================================================== 57===============================================================================
@@ -348,7 +348,7 @@ LUAG_FUNC( linda_send)
348 STACK_CHECK(L) 348 STACK_CHECK(L)
349 lua_pushlightuserdata( L, CANCEL_TEST_KEY); 349 lua_pushlightuserdata( L, CANCEL_TEST_KEY);
350 lua_rawget( L, LUA_REGISTRYINDEX); 350 lua_rawget( L, LUA_REGISTRYINDEX);
351 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil 351 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state
352 lua_pop(L, 1); 352 lua_pop(L, 1);
353 STACK_END(L,0) 353 STACK_END(L,0)
354 if( s) 354 if( s)
@@ -445,6 +445,9 @@ LUAG_FUNC( linda_receive)
445 // we expect a user-defined amount of return value 445 // we expect a user-defined amount of return value
446 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1); 446 expected_pushed_min = (int)luaL_checkinteger( L, key_i + 1);
447 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min); 447 expected_pushed_max = (int)luaL_optinteger( L, key_i + 2, expected_pushed_min);
448 // don't forget to count the key in addition to the values
449 ++ expected_pushed_min;
450 ++ expected_pushed_max;
448 if( expected_pushed_min > expected_pushed_max) 451 if( expected_pushed_min > expected_pushed_max)
449 { 452 {
450 return luaL_error( L, "batched min/max error"); 453 return luaL_error( L, "batched min/max error");
@@ -503,7 +506,7 @@ LUAG_FUNC( linda_receive)
503 STACK_CHECK(L) 506 STACK_CHECK(L)
504 lua_pushlightuserdata( L, CANCEL_TEST_KEY); 507 lua_pushlightuserdata( L, CANCEL_TEST_KEY);
505 lua_rawget( L, LUA_REGISTRYINDEX); 508 lua_rawget( L, LUA_REGISTRYINDEX);
506 s= lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil 509 s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) or nil if in the main Lua state
507 lua_pop(L, 1); 510 lua_pop(L, 1);
508 STACK_END(L, 0) 511 STACK_END(L, 0)
509 if( s) 512 if( s)
@@ -771,6 +774,16 @@ LUAG_FUNC( linda_concat)
771} 774}
772 775
773/* 776/*
777 * table = linda:dump()
778 * return a table listing all pending data inside the linda
779 */
780LUAG_FUNC( linda_dump)
781{
782 struct s_Linda* linda = lua_toLinda( L, 1);
783 return keeper_push_linda_storage( L, linda);
784}
785
786/*
774* Identity function of a shared userdata object. 787* Identity function of a shared userdata object.
775* 788*
776* lightuserdata= linda_id( "new" [, ...] ) 789* lightuserdata= linda_id( "new" [, ...] )
@@ -860,6 +873,10 @@ static void linda_id( lua_State *L, char const * const which)
860 lua_pushcfunction( L, LG_linda_tostring); 873 lua_pushcfunction( L, LG_linda_tostring);
861 lua_setfield( L, -2, "__tostring"); 874 lua_setfield( L, -2, "__tostring");
862 875
876 // Decoda __towatch support
877 lua_pushcfunction( L, LG_linda_dump);
878 lua_setfield( L, -2, "__towatch");
879
863 lua_pushcfunction( L, LG_linda_concat); 880 lua_pushcfunction( L, LG_linda_concat);
864 lua_setfield( L, -2, "__concat"); 881 lua_setfield( L, -2, "__concat");
865 882
@@ -886,6 +903,9 @@ static void linda_id( lua_State *L, char const * const which)
886 lua_pushcfunction( L, LG_linda_deep ); 903 lua_pushcfunction( L, LG_linda_deep );
887 lua_setfield( L, -2, "deep" ); 904 lua_setfield( L, -2, "deep" );
888 905
906 lua_pushcfunction( L, LG_linda_dump);
907 lua_setfield( L, -2, "dump" );
908
889 lua_pushliteral( L, BATCH_SENTINEL); 909 lua_pushliteral( L, BATCH_SENTINEL);
890 lua_setfield(L, -2, "batched"); 910 lua_setfield(L, -2, "batched");
891 911
@@ -1752,7 +1772,8 @@ LUAG_FUNC( thread_new )
1752 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing 1772 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing
1753 { 1773 {
1754 int i; 1774 int i;
1755 char const *entries[] = { "path", "cpath", "preload", "loaders", NULL}; 1775 // package.loaders is renamed package.searchers in Lua 5.2
1776 char const* entries[] = { "path", "cpath", "preload", (LUA_VERSION_NUM == 501) ? "loaders" : "searchers", NULL};
1756 for( i = 0; entries[i]; ++ i) 1777 for( i = 0; entries[i]; ++ i)
1757 { 1778 {
1758 lua_getfield( L, package, entries[i]); 1779 lua_getfield( L, package, entries[i]);
diff --git a/src/lanes.lua b/src/lanes.lua
index c9ab07d..20168b8 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -488,10 +488,10 @@ if first_time then
488 secs = next_wakeup - now_secs() 488 secs = next_wakeup - now_secs()
489 if secs < 0 then secs = 0 end 489 if secs < 0 then secs = 0 end
490 end 490 end
491 local linda = timer_gateway:receive( secs, TGW_KEY) 491 local _, linda = timer_gateway:receive( secs, TGW_KEY)
492 492
493 if linda then 493 if linda then
494 local key, wakeup_at, period = timer_gateway:receive( 0, timer_gateway_batched, TGW_KEY, 3) 494 local _, key, wakeup_at, period = timer_gateway:receive( 0, timer_gateway_batched, TGW_KEY, 3)
495 assert( key) 495 assert( key)
496 set_timer( linda, key, wakeup_at, period and period > 0 and period or nil) 496 set_timer( linda, key, wakeup_at, period and period > 0 and period or nil)
497 --elseif secs == nil then -- got no value while block-waiting? 497 --elseif secs == nil then -- got no value while block-waiting?