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? |
