aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--docs/index.html32
-rw-r--r--src/keeper.c16
-rw-r--r--src/lanes.c25
4 files changed, 54 insertions, 24 deletions
diff --git a/CHANGES b/CHANGES
index 2e6838e..c196455 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,10 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 87: BGe 20-Dec-13
4 * version 3.7.5
5 * fixed a crash that can occur at shutdown when an object stored inside a keeper state performs a linda operation on a linda making use of another keeper
6 * new setting demote_full_userdata to select between light userdata demotion or raising an error when attempting to transfer a non-deep full userdata
7
3CHANGE 86: BGe 3-Dec-13 8CHANGE 86: BGe 3-Dec-13
4 * version 3.7.4 9 * version 3.7.4
5 * internal refactoring of pthread priority management code 10 * internal refactoring of pthread priority management code
diff --git a/docs/index.html b/docs/index.html
index af08397..f25463d 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
70 </p> 70 </p>
71 71
72 <p> 72 <p>
73 This document was revised on 3-Dec-13, and applies to version <tt>3.7.4</tt>. 73 This document was revised on 20-Dec-13, and applies to version <tt>3.7.5</tt>.
74 </p> 74 </p>
75 </font> 75 </font>
76 </center> 76 </center>
@@ -273,7 +273,7 @@
273 <th style="width:70%">definition</th> 273 <th style="width:70%">definition</th>
274 </tr> 274 </tr>
275 <tr valign=top> 275 <tr valign=top>
276 <td> 276 <td id="nb_keepers">
277 <code>.nb_keepers</code> 277 <code>.nb_keepers</code>
278 </td> 278 </td>
279 <td>integer >= 1</td> 279 <td>integer >= 1</td>
@@ -283,7 +283,7 @@
283 </tr> 283 </tr>
284 284
285 <tr valign=top> 285 <tr valign=top>
286 <td> 286 <td id="with_timers">
287 <code>.with_timers</code> 287 <code>.with_timers</code>
288 </td> 288 </td>
289 <td> 289 <td>
@@ -296,7 +296,7 @@
296 </tr> 296 </tr>
297 297
298 <tr valign=top> 298 <tr valign=top>
299 <td> 299 <td id="verbose_errors">
300 <code>.verbose_errors</code> 300 <code>.verbose_errors</code>
301 </td> 301 </td>
302 <td> 302 <td>
@@ -309,7 +309,7 @@
309 </tr> 309 </tr>
310 310
311 <tr valign=top> 311 <tr valign=top>
312 <td> 312 <td id="protect_allocator">
313 <code>.protect_allocator</code> 313 <code>.protect_allocator</code>
314 </td> 314 </td>
315 <td> 315 <td>
@@ -322,6 +322,19 @@
322 </tr> 322 </tr>
323 323
324 <tr valign=top> 324 <tr valign=top>
325 <td id="demote_full_userdata">
326 <code>.demote_full_userdata</code>
327 </td>
328 <td>
329 <tt>nil</tt>/<tt>false</tt>/<tt>true</tt>
330 </td>
331 <td>
332 (Since v3.7.5) If equal to <tt>false</tt> or <tt>nil</tt>, Lanes raises an error when attempting to transfer a non-deep full userdata, else it will be demoted to a light userdata in the destination.
333 Default is <tt>false</tt> (set to <tt>true</tt> to get the legacy behaviour).
334 </td>
335 </tr>
336
337 <tr valign=top>
325 <td id="track_lanes"> 338 <td id="track_lanes">
326 <code>.track_lanes</code> 339 <code>.track_lanes</code>
327 </td> 340 </td>
@@ -335,7 +348,7 @@
335 </tr> 348 </tr>
336 349
337 <tr valign=top> 350 <tr valign=top>
338 <td> 351 <td id="on_state_create">
339 <code>.on_state_create</code> 352 <code>.on_state_create</code>
340 </td> 353 </td>
341 <td> 354 <td>
@@ -354,8 +367,8 @@
354 </tr> 367 </tr>
355 368
356 <tr valign=top> 369 <tr valign=top>
357 <td> 370 <td id="shutdown_timeout">
358 <code>.shutdown_timeout</code> <br/> 371 <code>.shutdown_timeout</code>
359 </td> 372 </td>
360 <td> 373 <td>
361 number >= 0 374 number >= 0
@@ -1133,7 +1146,7 @@ events to a common Linda, but... :).</font>
1133</pre></td></tr></table> 1146</pre></td></tr></table>
1134 1147
1135<p> 1148<p>
1136 Timers are implemented as a lane. They can be disabled by setting <tt>"with_timers"</tt> to <tt>nil</tt> or <tt>false</tt> to <tt>lanes.configure()</tt>. 1149 Timers are implemented as a lane. They can be disabled by setting "<tt><a href="#with_timers">with_timers</a></tt>" to <tt>nil</tt> or <tt>false</tt> to <tt>lanes.configure()</tt>.
1137</p> 1150</p>
1138 1151
1139<p> 1152<p>
@@ -1289,6 +1302,7 @@ events to a common Linda, but... :).</font>
1289 Full userdata can be passed only if it's prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management 1302 Full userdata can be passed only if it's prepared using the <a href="#deep_userdata">deep userdata</a> system, which handles its lifespan management
1290 <ul> 1303 <ul>
1291 <li>In particular, lane handles cannot be passed between lanes.</li> 1304 <li>In particular, lane handles cannot be passed between lanes.</li>
1305 <li>Lanes can either throw an error or attempt a <a href="#demote_full_userdata">light userdata demotion</a>.</li>
1292 </ul> 1306 </ul>
1293 </li> 1307 </li>
1294 <li>Coroutines cannot be passed. A coroutine's Lua state is tied to the Lua state that created it, and there is no way the mixed C/Lua stack of a coroutine can be transfered from one Lua state to another.</li> 1308 <li>Coroutines cannot be passed. A coroutine's Lua state is tied to the Lua state that created it, and there is no way the mixed C/Lua stack of a coroutine can be transfered from one Lua state to another.</li>
diff --git a/src/keeper.c b/src/keeper.c
index 99f510b..4c90069 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -184,7 +184,8 @@ static void push_table( lua_State* L, int idx)
184int keeper_push_linda_storage( lua_State* L, void* ptr) 184int keeper_push_linda_storage( lua_State* L, void* ptr)
185{ 185{
186 struct s_Keeper* K = keeper_acquire( ptr); 186 struct s_Keeper* K = keeper_acquire( ptr);
187 lua_State* KL = K->L; 187 lua_State* KL = K ? K->L : NULL;
188 if( KL == NULL) return 0;
188 STACK_CHECK( KL); 189 STACK_CHECK( KL);
189 lua_pushlightuserdata( KL, fifos_key); // fifos_key 190 lua_pushlightuserdata( KL, fifos_key); // fifos_key
190 lua_rawget( KL, LUA_REGISTRYINDEX); // fifos 191 lua_rawget( KL, LUA_REGISTRYINDEX); // fifos
@@ -535,14 +536,18 @@ void close_keepers( void)
535#endif // HAVE_KEEPER_ATEXIT_DESINIT 536#endif // HAVE_KEEPER_ATEXIT_DESINIT
536{ 537{
537 int i; 538 int i;
538 // 2-pass close, in case a keeper holds a reference to a linda bound to another keeoer 539 int const nbKeepers = GNbKeepers;
539 for( i = 0; i < GNbKeepers; ++ i) 540 // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it
541 // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists
542 // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success
543 GNbKeepers = 0;
544 for( i = 0; i < nbKeepers; ++ i)
540 { 545 {
541 lua_State* L = GKeepers[i].L; 546 lua_State* L = GKeepers[i].L;
542 GKeepers[i].L = NULL; 547 GKeepers[i].L = NULL;
543 lua_close( L); 548 lua_close( L);
544 } 549 }
545 for( i = 0; i < GNbKeepers; ++ i) 550 for( i = 0; i < nbKeepers; ++ i)
546 { 551 {
547 MUTEX_FREE( &GKeepers[i].lock_); 552 MUTEX_FREE( &GKeepers[i].lock_);
548 } 553 }
@@ -551,7 +556,6 @@ void close_keepers( void)
551 free( GKeepers); 556 free( GKeepers);
552 } 557 }
553 GKeepers = NULL; 558 GKeepers = NULL;
554 GNbKeepers = 0;
555} 559}
556 560
557/* 561/*
@@ -626,7 +630,7 @@ struct s_Keeper* keeper_acquire( void const* ptr)
626 * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer 630 * have to cast to unsigned long to avoid compilation warnings about loss of data when converting pointer-to-integer
627 */ 631 */
628 unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers); 632 unsigned int i = (unsigned int)(((unsigned long)(ptr) >> 3) % GNbKeepers);
629 struct s_Keeper *K= &GKeepers[i]; 633 struct s_Keeper* K= &GKeepers[i];
630 634
631 MUTEX_LOCK( &K->lock_); 635 MUTEX_LOCK( &K->lock_);
632 //++ K->count; 636 //++ K->count;
diff --git a/src/lanes.c b/src/lanes.c
index 6621735..e66342d 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.7.4"; 55char const* VERSION = "3.7.5";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -420,7 +420,8 @@ LUAG_FUNC( linda_send)
420 STACK_GROW(L, 1); 420 STACK_GROW(L, 1);
421 { 421 {
422 struct s_Keeper* K = keeper_acquire( linda); 422 struct s_Keeper* K = keeper_acquire( linda);
423 lua_State* KL = K->L; // need to do this for 'STACK_CHECK' 423 lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK'
424 if( KL == NULL) return 0;
424 STACK_CHECK( KL); 425 STACK_CHECK( KL);
425 for( ;;) 426 for( ;;)
426 { 427 {
@@ -584,6 +585,7 @@ LUAG_FUNC( linda_receive)
584 585
585 { 586 {
586 struct s_Keeper *K = keeper_acquire( linda); 587 struct s_Keeper *K = keeper_acquire( linda);
588 if( K == NULL) return 0;
587 for( ;;) 589 for( ;;)
588 { 590 {
589 // all arguments of receive() but the first are passed to the keeper's receive function 591 // all arguments of receive() but the first are passed to the keeper's receive function
@@ -690,6 +692,7 @@ LUAG_FUNC( linda_set)
690 { 692 {
691 int pushed; 693 int pushed;
692 struct s_Keeper *K = keeper_acquire( linda); 694 struct s_Keeper *K = keeper_acquire( linda);
695 if( K == NULL) return 0;
693 // no nil->sentinel toggling, we really clear the linda contents for the given key with a set() 696 // no nil->sentinel toggling, we really clear the linda contents for the given key with a set()
694 pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2); 697 pushed = keeper_call( K->L, KEEPER_API( set), L, linda, 2);
695 if( pushed >= 0) // no error? 698 if( pushed >= 0) // no error?
@@ -722,7 +725,7 @@ LUAG_FUNC( linda_set)
722 */ 725 */
723LUAG_FUNC( linda_count) 726LUAG_FUNC( linda_count)
724{ 727{
725 struct s_Linda *linda= lua_toLinda( L, 1); 728 struct s_Linda* linda = lua_toLinda( L, 1);
726 int pushed; 729 int pushed;
727 730
728 luaL_argcheck( L, linda, 1, "expected a linda object!"); 731 luaL_argcheck( L, linda, 1, "expected a linda object!");
@@ -730,7 +733,8 @@ LUAG_FUNC( linda_count)
730 check_key_types( L, 2, lua_gettop( L)); 733 check_key_types( L, 2, lua_gettop( L));
731 734
732 { 735 {
733 struct s_Keeper *K = keeper_acquire( linda); 736 struct s_Keeper* K = keeper_acquire( linda);
737 if( K == NULL) return 0;
734 pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2); 738 pushed = keeper_call( K->L, KEEPER_API( count), L, linda, 2);
735 keeper_release( K); 739 keeper_release( K);
736 if( pushed < 0) 740 if( pushed < 0)
@@ -758,14 +762,15 @@ LUAG_FUNC( linda_get)
758 check_key_types( L, 2, 2); 762 check_key_types( L, 2, 2);
759 763
760 { 764 {
761 struct s_Keeper *K = keeper_acquire( linda); 765 struct s_Keeper* K = keeper_acquire( linda);
766 if( K == NULL) return 0;
762 pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2); 767 pushed = keeper_call( K->L, KEEPER_API( get), L, linda, 2);
763 ASSERT_L( pushed==0 || pushed==1 ); 768 ASSERT_L( pushed == 0 || pushed == 1);
764 if( pushed > 0) 769 if( pushed > 0)
765 { 770 {
766 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0); 771 keeper_toggle_nil_sentinels( L, lua_gettop( L) - pushed, 0);
767 } 772 }
768 keeper_release(K); 773 keeper_release( K);
769 // must trigger error after keeper state has been released 774 // must trigger error after keeper state has been released
770 if( pushed < 0) 775 if( pushed < 0)
771 { 776 {
@@ -784,7 +789,8 @@ LUAG_FUNC( linda_get)
784*/ 789*/
785LUAG_FUNC( linda_limit) 790LUAG_FUNC( linda_limit)
786{ 791{
787 struct s_Linda* linda= lua_toLinda( L, 1 ); 792 struct s_Linda* linda= lua_toLinda( L, 1);
793 int pushed;
788 794
789 luaL_argcheck( L, linda, 1, "expected a linda object!"); 795 luaL_argcheck( L, linda, 1, "expected a linda object!");
790 // make sure we got a key and a limit 796 // make sure we got a key and a limit
@@ -796,7 +802,8 @@ LUAG_FUNC( linda_limit)
796 802
797 { 803 {
798 struct s_Keeper* K = keeper_acquire( linda); 804 struct s_Keeper* K = keeper_acquire( linda);
799 int pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2); 805 if( K == NULL) return 0;
806 pushed = keeper_call( K->L, KEEPER_API( limit), L, linda, 2);
800 ASSERT_L( pushed <= 0); // either error or no return values 807 ASSERT_L( pushed <= 0); // either error or no return values
801 keeper_release( K); 808 keeper_release( K);
802 // must trigger error after keeper state has been released 809 // must trigger error after keeper state has been released