diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/keeper.c | 94 | ||||
-rw-r--r-- | src/keeper.h | 1 | ||||
-rw-r--r-- | src/lanes-keeper.lua | 4 | ||||
-rw-r--r-- | src/lanes.c | 29 | ||||
-rw-r--r-- | src/lanes.lua | 4 |
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) |
132 | static void fifo_pop( lua_State* L, keeper_fifo* fifo, int _count) | 132 | static 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 | ||
186 | int 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 |
176 | int keepercall_clear( lua_State* L) | 228 | int 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 |
227 | int keepercall_receive( lua_State* L) | 279 | int 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); | |||
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); |
15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); | 15 | void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); |
16 | int 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 | ||
54 | char const* VERSION = "3.3.0"; | 54 | char 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 | */ | ||
780 | LUAG_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? |