From 2d5d798c24286f10c1bffd5ea4ac466c2c3a12fa Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Wed, 30 Mar 2011 19:16:39 +0200 Subject: New features * linda honors __tostring and __concat * new accessor linda:keys(), to retrieve the list of keys with pending data inside a linda * new lanes options packagepath and packagecpath, in case one needs to set them differently than the default --- src/keeper.lua | 22 ++++++++-- src/lanes.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/lanes.lua | 9 +++- 3 files changed, 158 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/keeper.lua b/src/keeper.lua index 2c38c0b..4bb181a 100644 --- a/src/keeper.lua +++ b/src/keeper.lua @@ -40,8 +40,9 @@ assert( nil_sentinel ) -- We only need to have base and table libraries (and io for debugging) -- -local table_remove= assert( table.remove ) -local table_concat= assert( table.concat ) +local table_concat = assert( table.concat) +local table_insert = assert( table.insert) +local table_remove = assert( table.remove) --[[ local function WR(...) @@ -229,6 +230,21 @@ function get( ud, key ) end +----- +-- [val]= keys( linda_deep_ud) +-- +function keys( ud) + + local data,_,_= tables(ud) + + local out = {} + for key, v in pairs( data) do + table_insert( out, key) + end + return (#out > 0) and out or nil +end + + ----- -- void= clear( linda_deep_ud ) -- @@ -240,5 +256,3 @@ function clear( ud ) _incoming[ud]= nil _limits[ud]= nil end - - diff --git a/src/lanes.c b/src/lanes.c index 0c943aa..e06d367 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -536,6 +536,33 @@ LUAG_FUNC( linda_set) } +/* +* [val]= linda_keys( linda_ud) +* +* Get the list of keys with pending data in the linda +*/ +LUAG_FUNC( linda_keys) +{ + struct s_Linda *linda= lua_toLinda( L, 1); + int pushed; + luaL_argcheck( L, linda, 1, "expected a linda object!"); + + { + struct s_Keeper *K = keeper_acquire( linda); + pushed = keeper_call( K->L, "keys", L, linda, 2); + ASSERT_L( pushed==0 || pushed==1 ); + keeper_release(K); + // must trigger error after keeper state has been released + if( pushed < 0) + { + luaL_error( L, "tried to copy unsupported types"); + } + } + + return pushed; +} + + /* * [val]= linda_get( linda_ud, key_num|str|bool|lightuserdata ) * @@ -607,6 +634,57 @@ LUAG_FUNC( linda_deep ) { } +/* +* string = linda:__tostring( linda_ud) +* +* Return the stringification of a linda +* +* Useful for concatenation or debugging purposes +*/ +LUAG_FUNC( linda_tostring) +{ + char text[32]; + struct s_Linda *linda = lua_toLinda( L, 1); + luaL_argcheck( L, linda, 1, "expected a linda object!"); + sprintf( text, "linda: %p", linda); + lua_pushstring( L, text); + return 1; +} + + +/* +* string = linda:__concat( a, b) +* +* Return the concatenation of a pair of items, one of them being a linda +* +* Useful for concatenation or debugging purposes +*/ +LUAG_FUNC( linda_concat) +{ + struct s_Linda *linda1 = lua_toLinda( L, 1); + struct s_Linda *linda2 = lua_toLinda( L, 2); + // lua semantics should enforce that one of the parameters we got is a linda + luaL_argcheck( L, linda1 || linda2, 1, "expected a linda object!"); + // replace the lindas by their string equivalents in the stack + if ( linda1) + { + char text[32]; + sprintf( text, "linda: %p", linda1); + lua_pushstring( L, text); + lua_replace( L, 1); + } + if ( linda2) + { + char text[32]; + sprintf( text, "linda: %p", linda2); + lua_pushstring( L, text); + lua_replace( L, 2); + } + // concat the result + lua_concat( L, 2); + return 1; +} + /* * Identity function of a shared userdata object. * @@ -678,17 +756,28 @@ static void linda_id( lua_State *L, char const * const which) // metatable is its own index lua_pushvalue( L, -1); lua_setfield( L, -2, "__index"); + // protect metatable from external access lua_pushboolean( L, 0); lua_setfield( L, -2, "__metatable"); + + lua_pushcfunction( L, LG_linda_tostring); + lua_setfield( L, -2, "__tostring"); + + lua_pushcfunction( L, LG_linda_concat); + lua_setfield( L, -2, "__concat"); + // // [-1]: linda metatable lua_pushcfunction( L, LG_linda_send ); lua_setfield( L, -2, "send" ); - + lua_pushcfunction( L, LG_linda_receive ); lua_setfield( L, -2, "receive" ); - + + lua_pushcfunction( L, LG_linda_keys ); + lua_setfield( L, -2, "keys" ); + lua_pushcfunction( L, LG_linda_limit ); lua_setfield( L, -2, "limit" ); @@ -1359,6 +1448,7 @@ LUAG_FUNC( set_debug_threadname) // [cancelstep_uint=0], // [prio_int=0], // [globals_tbl], +// [packagepath], // [... args ...] ) // // Upvalues: metatable to use for 'lane_ud' @@ -1373,8 +1463,10 @@ LUAG_FUNC( thread_new ) uint_t cs= luaG_optunsigned( L, 3,0); int prio= (int)luaL_optinteger( L, 4,0); uint_t glob= luaG_isany(L,5) ? 5:0; + uint_t ppath = luaG_isany(L,6) ? 6:0; + uint_t pcpath = luaG_isany(L,7) ? 7:0; -#define FIXED_ARGS (5) +#define FIXED_ARGS (7) uint_t args= lua_gettop(L) - FIXED_ARGS; if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) @@ -1424,6 +1516,44 @@ LUAG_FUNC( thread_new ) serialize_require( L2 ); } + // package.path + STACK_CHECK(L2) + if( ppath) + { + if (lua_type(L,ppath) != LUA_TSTRING) + luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath)); + lua_getglobal( L2, "package"); + if( lua_isnil( L2, -1)) + { + lua_pop( L2, 1); + luaL_error( L, "specifying a new path for packages, but lane doesn't load package library"); + } + lua_pushvalue( L, ppath); + luaG_inter_move( L, L2, 1); // moves the new path to L2 + lua_setfield( L2, -2, "path"); // set package.path + lua_pop( L2, 1); + } + STACK_END(L2,0) + + // package.cpath + STACK_CHECK(L2) + if( pcpath) + { + if (lua_type(L,pcpath) != LUA_TSTRING) + luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath)); + lua_getglobal( L2, "package"); + if( lua_isnil( L2, -1)) + { + lua_pop( L2, 1); + luaL_error( L, "specifying a new cpath for packages, but lane doesn't load package library"); + } + lua_pushvalue( L, pcpath); + luaG_inter_move( L, L2, 1); // moves the new cpath to L2 + lua_setfield( L2, -2, "cpath"); // set package.cpath + lua_pop( L2, 1); + } + STACK_END(L2,0) + // Lane main function // STACK_CHECK(L) diff --git a/src/lanes.lua b/src/lanes.lua index 05c2ff1..252d151 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -204,7 +204,7 @@ function gen( ... ) end end - local prio, cs, g_tbl + local prio, cs, g_tbl, packagepath, packagecpath for k,v in pairs(opt) do if k=="priority" then prio= v @@ -213,6 +213,8 @@ function gen( ... ) type(v)=="number" and v or error( "Bad cancelstep: "..tostring(v), lev ) elseif k=="globals" then g_tbl= v + elseif k=="packagepath" then packagepath= v + elseif k=="packagecpath" then packagecpath= v --.. elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) else error( "Bad option: ".. tostring(k), lev ) @@ -222,7 +224,7 @@ function gen( ... ) -- Lane generator -- return function(...) - return thread_new( func, libs, cs, prio, g_tbl, ...) -- args + return thread_new( func, libs, cs, prio, g_tbl, packagepath, packagecpath, ...) -- args end end @@ -237,6 +239,8 @@ linda = mm.linda ---=== Timers ===--- +local want_timers = true +if want_timers then local timer_gateway= assert( mm.timer_gateway ) -- @@ -452,6 +456,7 @@ function timer( linda, key, a, period ) timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) end +end -- want_timers ---=== Lock & atomic generators ===--- -- cgit v1.2.3-55-g6feb