Exemple #1
0
// 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;
}
Exemple #2
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;
	}
}
Exemple #3
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;
}
Exemple #4
0
//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;
}
Exemple #5
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;
}
Exemple #6
0
// 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;
}
Exemple #7
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;
}
Exemple #8
0
// 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;
}
Exemple #9
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;
}
Exemple #10
0
//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;
}