// in: linda_ud, key [, key]? // out: (key, val) or nothing int keepercall_receive( lua_State* L) { int top = lua_gettop( L); int i; push_table( L, 1); // ud keys fifos lua_replace( L, 1); // fifos keys for( i = 2; i <= top; ++ i) { keeper_fifo* fifo; lua_pushvalue( L, i); // fifos keys key[i] lua_rawget( L, 1); // fifos keys fifo fifo = prepare_fifo_access( L, -1); // fifos keys fifo if( fifo != NULL && fifo->count > 0) { fifo_pop( L, fifo, 1); // fifos keys val if( !lua_isnil( L, -1)) { lua_replace( L, 1); // val keys lua_settop( L, i); // val keys key[i] if( i != 2) { lua_replace( L, 2); // val key keys lua_settop( L, 2); // val key } lua_insert( L, 1); // key, val return 2; } } lua_settop( L, top); // data keys } // nothing to receive return 0; }
//in: linda_ud key mincount [maxcount] int keepercall_receive_batched( lua_State* L) { int const min_count = (int) lua_tointeger( L, 3); if( min_count > 0) { keeper_fifo* fifo; int const max_count = (int) luaL_optinteger( L, 4, min_count); lua_settop( L, 2); // ud key lua_insert( L, 1); // key ud push_table( L, 2); // key ud fifos lua_remove( L, 2); // key fifos lua_pushvalue( L, 1); // key fifos key lua_rawget( L, 2); // key fifos fifo lua_remove( L, 2); // key fifo fifo = prepare_fifo_access( L, 2); // key fifo if( fifo != NULL && fifo->count >= min_count) { fifo_pop( L, fifo, __min( max_count, fifo->count)); // key ... } else { lua_settop( L, 0); } return lua_gettop( L); } else { return 0; } }
// in: linda_ud, key, ... // out: true|false int keepercall_send( lua_State* L) { keeper_fifo* fifo; int n = lua_gettop( L) - 2; push_table( L, 1); // ud key ... fifos // get the fifo associated to this key in this linda, create it if it doesn't exist lua_pushvalue( L, 2); // ud key ... fifos key lua_rawget( L, -2); // ud key ... fifos fifo if( lua_isnil( L, -1)) { lua_pop( L, 1); // ud key ... fifos fifo_new( L); // ud key ... fifos fifo lua_pushvalue( L, 2); // ud key ... fifos fifo key lua_pushvalue( L, -2); // ud key ... fifos fifo key fifo lua_rawset( L, -4); // ud key ... fifos fifo } lua_remove( L, -2); // ud key ... fifo fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo->limit >= 0 && fifo->count + n > fifo->limit) { lua_settop( L, 0); // lua_pushboolean( L, 0); // false } else { fifo = prepare_fifo_access( L, -1); lua_replace( L, 2); // ud fifo ... fifo_push( L, fifo, n); // ud fifo lua_settop( L, 0); // lua_pushboolean( L, 1); // true } return 1; }
//in: linda_ud key [val] int keepercall_set( lua_State* L) { STACK_GROW( L, 6); // make sure we have a value on the stack if( lua_gettop( L) == 2) // ud key val? { lua_pushnil( L); // ud key nil } // retrieve fifos associated with the linda push_table( L, 1); // ud key val fifos lua_replace( L, 1); // fifos key val if( !lua_isnil( L, 3)) // set/replace contents stored at the specified key? { keeper_fifo* fifo; lua_pushvalue( L, -2); // fifos key val key lua_rawget( L, 1); // fifos key val fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) // might be NULL if we set a nonexistent key to nil { lua_pop( L, 1); // fifos key val fifo_new( L); // fifos key val fifo lua_pushvalue( L, 2); // fifos key val fifo key lua_pushvalue( L, -2); // fifos key val fifo key fifo lua_rawset( L, 1); // fifos key val fifo } else // the fifo exists, we just want to clear its contents { // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! lua_newtable( L); // fifos key val fifo {} lua_setuservalue( L, -2); // fifos key val fifo fifo->first = 1; fifo->count = 0; } fifo = prepare_fifo_access( L, -1); lua_insert( L, -2); // fifos key fifo val fifo_push( L, fifo, 1); // fifos key fifo } else // val == nil // fifos key nil { keeper_fifo* fifo; lua_pop( L, 1); // fifos key lua_rawget( L, 1); // fifos fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo != NULL) // might be NULL if we set a nonexistent key to nil { lua_newtable( L); // fifos fifo {} lua_setuservalue( L, -2); // fifos fifo fifo->first = 1; fifo->count = 0; } } return 0; }
int keeper_push_linda_storage( struct s_Universe* U, lua_State* L, void* ptr, unsigned long magic_) { struct s_Keeper* K = keeper_acquire( U->keepers, magic_); lua_State* KL = K ? K->L : NULL; if( KL == NULL) return 0; STACK_GROW( KL, 4); STACK_CHECK( KL); lua_pushlightuserdata( KL, fifos_key); // fifos_key lua_rawget( KL, LUA_REGISTRYINDEX); // fifos lua_pushlightuserdata( KL, ptr); // fifos ud lua_rawget( KL, -2); // fifos storage lua_remove( KL, -2); // storage if( !lua_istable( KL, -1)) { lua_pop( KL, 1); // STACK_MID( KL, 0); return 0; } // move data from keeper to destination state KEEPER MAIN lua_pushnil( KL); // storage nil STACK_GROW( L, 5); STACK_CHECK( L); lua_newtable( L); // out while( lua_next( KL, -2)) // storage key fifo { keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo lua_pushvalue( KL, -2); // storage key fifo key luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key STACK_MID( L, 2); lua_newtable( L); // out key keyout luaG_inter_move( U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo lua_pushinteger( L, fifo->first); // out key keyout fifo first STACK_MID( L, 5); lua_setfield( L, -3, "first"); // out key keyout fifo lua_pushinteger( L, fifo->count); // out key keyout fifo count STACK_MID( L, 5); lua_setfield( L, -3, "count"); // out key keyout fifo lua_pushinteger( L, fifo->limit); // out key keyout fifo limit STACK_MID( L, 5); lua_setfield( L, -3, "limit"); // out key keyout fifo lua_setfield( L, -2, "fifo"); // out key keyout lua_rawset( L, -3); // out STACK_MID( L, 1); } STACK_END( L, 1); lua_pop( KL, 1); // STACK_END( KL, 0); keeper_release( K); return 1; }
// in: linda_ud key int keepercall_get( lua_State* L) { keeper_fifo* fifo; push_table( L, 1); // ud key fifos lua_replace( L, 1); // fifos key lua_rawget( L, 1); // fifos fifo fifo = prepare_fifo_access( L, -1); // fifos fifo if( fifo != NULL && fifo->count > 0) { lua_remove( L, 1); // fifo // read one value off the fifo fifo_peek( L, fifo, 1); // fifo ... return 1; } // no fifo was ever registered for this key, or it is empty return 0; }
int keeper_push_linda_storage( lua_State* L, void* ptr) { struct s_Keeper* K = keeper_acquire( ptr); lua_State* KL = K->L; STACK_CHECK( KL) lua_pushlightuserdata( KL, fifos_key); // fifos_key lua_rawget( KL, LUA_REGISTRYINDEX); // fifos lua_pushlightuserdata( KL, ptr); // fifos ud lua_rawget( KL, -2); // fifos storage lua_remove( KL, -2); // storage if( !lua_istable( KL, -1)) { lua_pop( KL, 1); // STACK_MID( KL, 0); return 0; } lua_pushnil( KL); // storage nil lua_newtable( L); // out while( lua_next( KL, -2)) // storage key fifo { keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo lua_pushvalue( KL, -2); // storage key fifo key luaG_inter_move( KL, L, 1); // storage key fifo // out key STACK_CHECK( L) lua_newtable( L); // out key keyout luaG_inter_move( KL, L, 1); // storage key // out key keyout fifo lua_pushinteger( L, fifo->first); // out key keyout fifo first lua_setfield( L, -3, "first"); // out key keyout fifo lua_pushinteger( L, fifo->count); // out key keyout fifo count lua_setfield( L, -3, "count"); // out key keyout fifo lua_pushinteger( L, fifo->limit); // out key keyout fifo limit lua_setfield( L, -3, "limit"); // out key keyout fifo lua_setfield( L, -2, "fifo"); // out key keyout lua_rawset( L, -3); // out STACK_END( L, 0) } lua_pop( KL, 1); // STACK_END( KL, 0) keeper_release( K); return 1; }
// in: linda_ud key [count] // out: at most <count> values int keepercall_get( lua_State* L) { keeper_fifo* fifo; int count = 1; if( lua_gettop( L) == 3) // ud key count { count = lua_tointeger( L, 3); lua_pop( L, 1); // ud key } push_table( L, 1); // ud key fifos lua_replace( L, 1); // fifos key lua_rawget( L, 1); // fifos fifo fifo = prepare_fifo_access( L, -1); // fifos fifo if( fifo != NULL && fifo->count > 0) { lua_remove( L, 1); // fifo count = __min( count, fifo->count); // read <count> value off the fifo fifo_peek( L, fifo, count); // fifo ... return count; } // no fifo was ever registered for this key, or it is empty return 0; }
// in: linda_ud [, key [, ...]] int keepercall_count( lua_State* L) { int top; push_table( L, 1); // ud keys fifos switch( lua_gettop( L)) { // no key is specified: return a table giving the count of all known keys case 2: // ud fifos lua_newtable( L); // ud fifos out lua_replace( L, 1); // out fifos lua_pushnil( L); // out fifos nil while( lua_next( L, 2)) // out fifos key fifo { keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo lua_pop( L, 1); // out fifos key lua_pushvalue( L, -1); // out fifos key key lua_pushinteger( L, fifo->count); // out fifos key key count lua_rawset( L, -5); // out fifos key } lua_pop( L, 1); // out break; // 1 key is specified: return its count case 3: // ud key fifos { keeper_fifo* fifo; lua_replace( L, 1); // fifos key lua_rawget( L, -2); // fifos fifo fifo = prepare_fifo_access( L, -1); // fifos fifo lua_pushinteger( L, fifo->count); // fifos fifo count lua_replace( L, -3); // count fifo lua_pop( L, 1); // count } break; // a variable number of keys is specified: return a table of their counts default: // ud keys fifos lua_newtable( L); // ud keys fifos out lua_replace( L, 1); // out keys fifos // shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable lua_insert( L, 2); // out fifos keys while( (top = lua_gettop( L)) > 2) { keeper_fifo* fifo; lua_pushvalue( L, -1); // out fifos keys key lua_rawget( L, 2); // out fifos keys fifo fifo = prepare_fifo_access( L, -1); // out fifos keys fifo lua_pop( L, 1); // out fifos keys if( fifo != NULL) { lua_pushinteger( L, fifo->count); // out fifos keys count lua_rawset( L, 1); // out fifos keys } else { lua_pop( L, 1); // out fifos keys } } lua_pop( L, 1); // out } return 1; }
//in: linda_ud key [[val] ...] //out: true or nil int keepercall_set( lua_State* L) { bool_t should_wake_writers = FALSE; STACK_GROW( L, 6); // retrieve fifos associated with the linda push_table( L, 1); // ud key [val [, ...]] fifos lua_replace( L, 1); // fifos key [val [, ...]] // make sure we have a value on the stack if( lua_gettop( L) == 2) // fifos key { keeper_fifo* fifo; lua_pushvalue( L, -1); // fifos key key lua_rawget( L, 1); // fifos key fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo != NULL) // might be NULL if we set a nonexistent key to nil { // fifos key fifo if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it { lua_pop( L, 1); // fifos key lua_pushnil( L); // fifos key nil lua_rawset( L, -3); // fifos } else { // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); lua_remove( L, -2); // fifos fifo lua_newtable( L); // fifos fifo {} lua_setuservalue( L, -2); // fifos fifo fifo->first = 1; fifo->count = 0; } } } else // set/replace contents stored at the specified key? { int count = lua_gettop( L) - 2; // number of items we want to store keeper_fifo* fifo; // fifos key [val [, ...]] lua_pushvalue( L, 2); // fifos key [val [, ...]] key lua_rawget( L, 1); // fifos key [val [, ...]] fifo|nil fifo = (keeper_fifo*) lua_touserdata( L, -1); if( fifo == NULL) // can be NULL if we store a value at a new key { // fifos key [val [, ...]] nil // no need to wake writers in that case, because a writer can't wait on an inexistent key lua_pop( L, 1); // fifos key [val [, ...]] fifo_new( L); // fifos key [val [, ...]] fifo lua_pushvalue( L, 2); // fifos key [val [, ...]] fifo key lua_pushvalue( L, -2); // fifos key [val [, ...]] fifo key fifo lua_rawset( L, 1); // fifos key [val [, ...]] fifo } else // the fifo exists, we just want to update its contents { // fifos key [val [, ...]] fifo // we create room if the fifo was full but it is no longer the case should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! lua_newtable( L); // fifos key [val [, ...]] fifo {} lua_setuservalue( L, -2); // fifos key [val [, ...]] fifo fifo->first = 1; fifo->count = 0; } fifo = prepare_fifo_access( L, -1); // move the fifo below the values we want to store lua_insert( L, 3); // fifos key fifo [val [, ...]] fifo_push( L, fifo, count); // fifos key fifo } return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; }