diff options
Diffstat (limited to 'src/lanes.lua')
-rw-r--r-- | src/lanes.lua | 88 |
1 files changed, 53 insertions, 35 deletions
diff --git a/src/lanes.lua b/src/lanes.lua index 1286099..86dbe47 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -585,13 +585,25 @@ end | |||
585 | 585 | ||
586 | end -- settings.with_timers | 586 | end -- settings.with_timers |
587 | 587 | ||
588 | -- avoid pulling the whole core module as upvalue when cancel_error is enough | ||
589 | local cancel_error = assert( core.cancel_error) | ||
590 | |||
588 | ---=== Lock & atomic generators ===--- | 591 | ---=== Lock & atomic generators ===--- |
589 | 592 | ||
590 | -- These functions are just surface sugar, but make solutions easier to read. | 593 | -- These functions are just surface sugar, but make solutions easier to read. |
591 | -- Not many applications should even need explicit locks or atomic counters. | 594 | -- Not many applications should even need explicit locks or atomic counters. |
592 | 595 | ||
593 | -- | 596 | -- |
594 | -- lock_f= lanes.genlock( linda_h, key [,N_uint=1] ) | 597 | -- [true [, ...]= trues(uint) |
598 | -- | ||
599 | local function trues( n) | ||
600 | if n > 0 then | ||
601 | return true, trues( n - 1) | ||
602 | end | ||
603 | end | ||
604 | |||
605 | -- | ||
606 | -- lock_f = lanes.genlock( linda_h, key [,N_uint=1] ) | ||
595 | -- | 607 | -- |
596 | -- = lock_f( +M ) -- acquire M | 608 | -- = lock_f( +M ) -- acquire M |
597 | -- ...locked... | 609 | -- ...locked... |
@@ -602,16 +614,10 @@ end -- settings.with_timers | |||
602 | -- | 614 | -- |
603 | -- PUBLIC LANES API | 615 | -- PUBLIC LANES API |
604 | local genlock = function( linda, key, N) | 616 | local genlock = function( linda, key, N) |
605 | linda:set( key) -- clears existing data | 617 | -- clear existing data and set the limit |
606 | linda:limit( key, N) | 618 | N = N or 1 |
607 | 619 | if linda:set( key) == cancel_error or linda:limit( key, N) == cancel_error then | |
608 | -- | 620 | return cancel_error |
609 | -- [true [, ...]= trues(uint) | ||
610 | -- | ||
611 | local function trues( n) | ||
612 | if n > 0 then | ||
613 | return true, trues( n - 1) | ||
614 | end | ||
615 | end | 621 | end |
616 | 622 | ||
617 | -- use an optimized version for case N == 1 | 623 | -- use an optimized version for case N == 1 |
@@ -623,7 +629,8 @@ local genlock = function( linda, key, N) | |||
623 | return linda:send( timeout, key, true) -- suspends until been able to push them | 629 | return linda:send( timeout, key, true) -- suspends until been able to push them |
624 | else | 630 | else |
625 | local k = linda:receive( nil, key) | 631 | local k = linda:receive( nil, key) |
626 | return k and true or false | 632 | -- propagate cancel_error if we got it, else return true or false |
633 | return k and ((k ~= cancel_error) and true or k) or false | ||
627 | end | 634 | end |
628 | end | 635 | end |
629 | or | 636 | or |
@@ -634,34 +641,45 @@ local genlock = function( linda, key, N) | |||
634 | return linda:send( timeout, key, trues(M)) -- suspends until been able to push them | 641 | return linda:send( timeout, key, trues(M)) -- suspends until been able to push them |
635 | else | 642 | else |
636 | local k = linda:receive( nil, linda.batched, key, -M) | 643 | local k = linda:receive( nil, linda.batched, key, -M) |
637 | return k and true or false | 644 | -- propagate cancel_error if we got it, else return true or false |
645 | return k and ((k ~= cancel_error) and true or k) or false | ||
638 | end | 646 | end |
639 | end | 647 | end |
640 | end | 648 | end |
641 | 649 | ||
642 | 650 | ||
643 | -- | 651 | -- |
644 | -- atomic_f= lanes.genatomic( linda_h, key [,initial_num=0.0] ) | 652 | -- atomic_f = lanes.genatomic( linda_h, key [,initial_num=0.0]) |
645 | -- | 653 | -- |
646 | -- int= atomic_f( [diff_num=1.0] ) | 654 | -- int|cancel_error = atomic_f( [diff_num = 1.0]) |
647 | -- | 655 | -- |
648 | -- Returns an access function that allows atomic increment/decrement of the | 656 | -- Returns an access function that allows atomic increment/decrement of the |
649 | -- number in 'key'. | 657 | -- number in 'key'. |
650 | -- | 658 | -- |
651 | -- PUBLIC LANES API | 659 | -- PUBLIC LANES API |
652 | local function genatomic( linda, key, initial_val ) | 660 | local genatomic = function( linda, key, initial_val) |
653 | linda:limit(key,2) -- value [,true] | 661 | -- clears existing data (also queue). the slot may contain the stored value, and an additional boolean value |
654 | linda:set(key,initial_val or 0.0) -- clears existing data (also queue) | 662 | if linda:limit( key, 2) == cancel_error or linda:set( key, initial_val or 0.0) == cancel_error then |
655 | 663 | return cancel_error | |
656 | return | 664 | end |
657 | function(diff) | 665 | |
658 | -- 'nil' allows 'key' to be numeric | 666 | return function( diff) |
659 | linda:send( nil, key, true ) -- suspends until our 'true' is in | 667 | -- 'nil' allows 'key' to be numeric |
660 | local val= linda:get(key) + (diff or 1.0) | 668 | -- suspends until our 'true' is in |
661 | linda:set( key, val ) -- releases the lock, by emptying queue | 669 | if linda:send( nil, key, true) == cancel_error then |
662 | return val | 670 | return cancel_error |
663 | end | 671 | end |
664 | end | 672 | local val = linda:get( key) |
673 | if val ~= cancel_error then | ||
674 | val = val + (diff or 1.0) | ||
675 | -- set() releases the lock by emptying queue | ||
676 | if linda:set( key, val) == cancel_error then | ||
677 | val = cancel_error | ||
678 | end | ||
679 | end | ||
680 | return val | ||
681 | end | ||
682 | end | ||
665 | 683 | ||
666 | -- activate full interface | 684 | -- activate full interface |
667 | lanes.require = core.require | 685 | lanes.require = core.require |