aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--docs/index.html37
-rw-r--r--src/keeper.lua22
-rw-r--r--src/lanes.c136
-rw-r--r--src/lanes.lua9
5 files changed, 197 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index 58b6061..31ca342 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,11 @@ CHANGES:
3 3
4CHANGE X: 4CHANGE X:
5 5
6CHANGE 30 BGe 30-Mar-2011
7* linda honors __tostring and __concat
8* new accessor linda:keys(), to retrieve the list of keys with pending data inside a linda
9* new lanes options packagepath and packagecpath, in case one needs to set them differently than the default
10
6CHANGE 29 BGe 1-Mar-2011 11CHANGE 29 BGe 1-Mar-2011
7 fixed potential crash at application shutdown when calling lua_close() on a killed thread's VM. 12 fixed potential crash at application shutdown when calling lua_close() on a killed thread's VM.
8 exposed cancel_test() in the lanes to enable manual testing for cancellation requests. 13 exposed cancel_test() in the lanes to enable manual testing for cancellation requests.
diff --git a/docs/index.html b/docs/index.html
index ba25515..7d61d96 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -263,6 +263,19 @@ also in the new lanes.
263 Implementation and dependability of priorities varies 263 Implementation and dependability of priorities varies
264 by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode. 264 by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.
265 </td></tr> 265 </td></tr>
266
267 <tr valign="top">
268 <td width="40">
269 <td>
270 <code>.packagepath</code>
271 <br/><code>.packagecpath</code>
272 </td>
273 <td>
274 <code>package.path</code> and <code>package.cpath</code> overrides, if needed.
275 Specifying these when <code>libs_str</code> doesn't cause the <code>package</code> library to be loaded will generate an error.
276 <br>
277 </td>
278 </tr>
266 </table> 279 </table>
267 <p>Each lane also gets a function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says. 280 <p>Each lane also gets a function <tt>set_debug_threadname()</tt> that it can use anytime to do as the name says.
268Supported debuggers are Microsoft Visual Studio (for the C side) and Decoda (for the Lua side). 281Supported debuggers are Microsoft Visual Studio (for the C side) and Decoda (for the Lua side).
@@ -547,7 +560,18 @@ They can be used for making shared tables of storage among the lanes.
547Writing to a slot overwrites existing value, and clears any possible queued 560Writing to a slot overwrites existing value, and clears any possible queued
548entries. Table access and <tt>send</tt>/<tt>receive</tt> can be used together; 561entries. Table access and <tt>send</tt>/<tt>receive</tt> can be used together;
549reading a slot essentially peeks the next outcoming value of a queue. 562reading a slot essentially peeks the next outcoming value of a queue.
550</p> 563</p><p>
564
565 <table border="1" bgcolor="#E0E0FF" cellpadding="10">
566 <tr>
567 <td>
568 <code>[val]= linda_h:keys()</code>
569 </table>
570
571 </p>
572 <p>
573 A way to examine the slots in which a linda contains some pending data to be read.
574 </p>
551 575
552<!-- 576<!--
553<p> 577<p>
@@ -961,8 +985,15 @@ its actual value.
961 985
962<p> 986<p>
963 987
964Mar-2011 (2.1.0) 988 Mar-2011 (not yet versioned)
965<ul> 989 <ul>
990 <li>linda honors __tostring and __concat</li>
991 <li>new accessor linda:keys(), to retrieve the list of keys with pending data inside a linda</li>
992 <li>new lanes options packagepath and packagecpath, in case one needs to set them differently than the default</li>
993 </ul>
994
995 Mar-2011 (2.1.0)
996 <ul>
966 <li>fixed potential crash at application shutdown when calling lua_close() on a killed thread's VM.</li> 997 <li>fixed potential crash at application shutdown when calling lua_close() on a killed thread's VM.</li>
967 <li>exposed cancel_test() in the lanes to enable manual testing for cancellation requests.</li> 998 <li>exposed cancel_test() in the lanes to enable manual testing for cancellation requests.</li>
968 <li>removed kludgy {globals={threadName}} support, replaced with a new function set_debug_threadname().</li> 999 <li>removed kludgy {globals={threadName}} support, replaced with a new function set_debug_threadname().</li>
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 )
40 40
41-- We only need to have base and table libraries (and io for debugging) 41-- We only need to have base and table libraries (and io for debugging)
42-- 42--
43local table_remove= assert( table.remove ) 43local table_concat = assert( table.concat)
44local table_concat= assert( table.concat ) 44local table_insert = assert( table.insert)
45local table_remove = assert( table.remove)
45 46
46--[[ 47--[[
47local function WR(...) 48local function WR(...)
@@ -230,6 +231,21 @@ end
230 231
231 232
232----- 233-----
234-- [val]= keys( linda_deep_ud)
235--
236function keys( ud)
237
238 local data,_,_= tables(ud)
239
240 local out = {}
241 for key, v in pairs( data) do
242 table_insert( out, key)
243 end
244 return (#out > 0) and out or nil
245end
246
247
248-----
233-- void= clear( linda_deep_ud ) 249-- void= clear( linda_deep_ud )
234-- 250--
235-- Clear the data structures used for a Linda (at its destructor) 251-- Clear the data structures used for a Linda (at its destructor)
@@ -240,5 +256,3 @@ function clear( ud )
240 _incoming[ud]= nil 256 _incoming[ud]= nil
241 _limits[ud]= nil 257 _limits[ud]= nil
242end 258end
243
244
diff --git a/src/lanes.c b/src/lanes.c
index 0c943aa..e06d367 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -537,6 +537,33 @@ LUAG_FUNC( linda_set)
537 537
538 538
539/* 539/*
540* [val]= linda_keys( linda_ud)
541*
542* Get the list of keys with pending data in the linda
543*/
544LUAG_FUNC( linda_keys)
545{
546 struct s_Linda *linda= lua_toLinda( L, 1);
547 int pushed;
548 luaL_argcheck( L, linda, 1, "expected a linda object!");
549
550 {
551 struct s_Keeper *K = keeper_acquire( linda);
552 pushed = keeper_call( K->L, "keys", L, linda, 2);
553 ASSERT_L( pushed==0 || pushed==1 );
554 keeper_release(K);
555 // must trigger error after keeper state has been released
556 if( pushed < 0)
557 {
558 luaL_error( L, "tried to copy unsupported types");
559 }
560 }
561
562 return pushed;
563}
564
565
566/*
540* [val]= linda_get( linda_ud, key_num|str|bool|lightuserdata ) 567* [val]= linda_get( linda_ud, key_num|str|bool|lightuserdata )
541* 568*
542* Get a value from Linda. 569* Get a value from Linda.
@@ -608,6 +635,57 @@ LUAG_FUNC( linda_deep ) {
608 635
609 636
610/* 637/*
638* string = linda:__tostring( linda_ud)
639*
640* Return the stringification of a linda
641*
642* Useful for concatenation or debugging purposes
643*/
644LUAG_FUNC( linda_tostring)
645{
646 char text[32];
647 struct s_Linda *linda = lua_toLinda( L, 1);
648 luaL_argcheck( L, linda, 1, "expected a linda object!");
649 sprintf( text, "linda: %p", linda);
650 lua_pushstring( L, text);
651 return 1;
652}
653
654
655/*
656* string = linda:__concat( a, b)
657*
658* Return the concatenation of a pair of items, one of them being a linda
659*
660* Useful for concatenation or debugging purposes
661*/
662LUAG_FUNC( linda_concat)
663{
664 struct s_Linda *linda1 = lua_toLinda( L, 1);
665 struct s_Linda *linda2 = lua_toLinda( L, 2);
666 // lua semantics should enforce that one of the parameters we got is a linda
667 luaL_argcheck( L, linda1 || linda2, 1, "expected a linda object!");
668 // replace the lindas by their string equivalents in the stack
669 if ( linda1)
670 {
671 char text[32];
672 sprintf( text, "linda: %p", linda1);
673 lua_pushstring( L, text);
674 lua_replace( L, 1);
675 }
676 if ( linda2)
677 {
678 char text[32];
679 sprintf( text, "linda: %p", linda2);
680 lua_pushstring( L, text);
681 lua_replace( L, 2);
682 }
683 // concat the result
684 lua_concat( L, 2);
685 return 1;
686}
687
688/*
611* Identity function of a shared userdata object. 689* Identity function of a shared userdata object.
612* 690*
613* lightuserdata= linda_id( "new" [, ...] ) 691* lightuserdata= linda_id( "new" [, ...] )
@@ -678,17 +756,28 @@ static void linda_id( lua_State *L, char const * const which)
678 // metatable is its own index 756 // metatable is its own index
679 lua_pushvalue( L, -1); 757 lua_pushvalue( L, -1);
680 lua_setfield( L, -2, "__index"); 758 lua_setfield( L, -2, "__index");
759
681 // protect metatable from external access 760 // protect metatable from external access
682 lua_pushboolean( L, 0); 761 lua_pushboolean( L, 0);
683 lua_setfield( L, -2, "__metatable"); 762 lua_setfield( L, -2, "__metatable");
763
764 lua_pushcfunction( L, LG_linda_tostring);
765 lua_setfield( L, -2, "__tostring");
766
767 lua_pushcfunction( L, LG_linda_concat);
768 lua_setfield( L, -2, "__concat");
769
684 // 770 //
685 // [-1]: linda metatable 771 // [-1]: linda metatable
686 lua_pushcfunction( L, LG_linda_send ); 772 lua_pushcfunction( L, LG_linda_send );
687 lua_setfield( L, -2, "send" ); 773 lua_setfield( L, -2, "send" );
688 774
689 lua_pushcfunction( L, LG_linda_receive ); 775 lua_pushcfunction( L, LG_linda_receive );
690 lua_setfield( L, -2, "receive" ); 776 lua_setfield( L, -2, "receive" );
691 777
778 lua_pushcfunction( L, LG_linda_keys );
779 lua_setfield( L, -2, "keys" );
780
692 lua_pushcfunction( L, LG_linda_limit ); 781 lua_pushcfunction( L, LG_linda_limit );
693 lua_setfield( L, -2, "limit" ); 782 lua_setfield( L, -2, "limit" );
694 783
@@ -1359,6 +1448,7 @@ LUAG_FUNC( set_debug_threadname)
1359// [cancelstep_uint=0], 1448// [cancelstep_uint=0],
1360// [prio_int=0], 1449// [prio_int=0],
1361// [globals_tbl], 1450// [globals_tbl],
1451// [packagepath],
1362// [... args ...] ) 1452// [... args ...] )
1363// 1453//
1364// Upvalues: metatable to use for 'lane_ud' 1454// Upvalues: metatable to use for 'lane_ud'
@@ -1373,8 +1463,10 @@ LUAG_FUNC( thread_new )
1373 uint_t cs= luaG_optunsigned( L, 3,0); 1463 uint_t cs= luaG_optunsigned( L, 3,0);
1374 int prio= (int)luaL_optinteger( L, 4,0); 1464 int prio= (int)luaL_optinteger( L, 4,0);
1375 uint_t glob= luaG_isany(L,5) ? 5:0; 1465 uint_t glob= luaG_isany(L,5) ? 5:0;
1466 uint_t ppath = luaG_isany(L,6) ? 6:0;
1467 uint_t pcpath = luaG_isany(L,7) ? 7:0;
1376 1468
1377#define FIXED_ARGS (5) 1469#define FIXED_ARGS (7)
1378 uint_t args= lua_gettop(L) - FIXED_ARGS; 1470 uint_t args= lua_gettop(L) - FIXED_ARGS;
1379 1471
1380 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX) 1472 if (prio < THREAD_PRIO_MIN || prio > THREAD_PRIO_MAX)
@@ -1424,6 +1516,44 @@ LUAG_FUNC( thread_new )
1424 serialize_require( L2 ); 1516 serialize_require( L2 );
1425 } 1517 }
1426 1518
1519 // package.path
1520 STACK_CHECK(L2)
1521 if( ppath)
1522 {
1523 if (lua_type(L,ppath) != LUA_TSTRING)
1524 luaL_error( L, "expected packagepath as string, got %s", luaG_typename(L,ppath));
1525 lua_getglobal( L2, "package");
1526 if( lua_isnil( L2, -1))
1527 {
1528 lua_pop( L2, 1);
1529 luaL_error( L, "specifying a new path for packages, but lane doesn't load package library");
1530 }
1531 lua_pushvalue( L, ppath);
1532 luaG_inter_move( L, L2, 1); // moves the new path to L2
1533 lua_setfield( L2, -2, "path"); // set package.path
1534 lua_pop( L2, 1);
1535 }
1536 STACK_END(L2,0)
1537
1538 // package.cpath
1539 STACK_CHECK(L2)
1540 if( pcpath)
1541 {
1542 if (lua_type(L,pcpath) != LUA_TSTRING)
1543 luaL_error( L, "expected packagecpath as string, got %s", luaG_typename(L,pcpath));
1544 lua_getglobal( L2, "package");
1545 if( lua_isnil( L2, -1))
1546 {
1547 lua_pop( L2, 1);
1548 luaL_error( L, "specifying a new cpath for packages, but lane doesn't load package library");
1549 }
1550 lua_pushvalue( L, pcpath);
1551 luaG_inter_move( L, L2, 1); // moves the new cpath to L2
1552 lua_setfield( L2, -2, "cpath"); // set package.cpath
1553 lua_pop( L2, 1);
1554 }
1555 STACK_END(L2,0)
1556
1427 // Lane main function 1557 // Lane main function
1428 // 1558 //
1429 STACK_CHECK(L) 1559 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( ... )
204 end 204 end
205 end 205 end
206 206
207 local prio, cs, g_tbl 207 local prio, cs, g_tbl, packagepath, packagecpath
208 208
209 for k,v in pairs(opt) do 209 for k,v in pairs(opt) do
210 if k=="priority" then prio= v 210 if k=="priority" then prio= v
@@ -213,6 +213,8 @@ function gen( ... )
213 type(v)=="number" and v or 213 type(v)=="number" and v or
214 error( "Bad cancelstep: "..tostring(v), lev ) 214 error( "Bad cancelstep: "..tostring(v), lev )
215 elseif k=="globals" then g_tbl= v 215 elseif k=="globals" then g_tbl= v
216 elseif k=="packagepath" then packagepath= v
217 elseif k=="packagecpath" then packagecpath= v
216 --.. 218 --..
217 elseif k==1 then error( "unkeyed option: ".. tostring(v), lev ) 219 elseif k==1 then error( "unkeyed option: ".. tostring(v), lev )
218 else error( "Bad option: ".. tostring(k), lev ) 220 else error( "Bad option: ".. tostring(k), lev )
@@ -222,7 +224,7 @@ function gen( ... )
222 -- Lane generator 224 -- Lane generator
223 -- 225 --
224 return function(...) 226 return function(...)
225 return thread_new( func, libs, cs, prio, g_tbl, ...) -- args 227 return thread_new( func, libs, cs, prio, g_tbl, packagepath, packagecpath, ...) -- args
226 end 228 end
227end 229end
228 230
@@ -237,6 +239,8 @@ linda = mm.linda
237 239
238 240
239---=== Timers ===--- 241---=== Timers ===---
242local want_timers = true
243if want_timers then
240 244
241local timer_gateway= assert( mm.timer_gateway ) 245local timer_gateway= assert( mm.timer_gateway )
242-- 246--
@@ -452,6 +456,7 @@ function timer( linda, key, a, period )
452 timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period ) 456 timer_gateway:send( TGW_KEY, linda, key, wakeup_at, period )
453end 457end
454 458
459end -- want_timers
455 460
456---=== Lock & atomic generators ===--- 461---=== Lock & atomic generators ===---
457 462