File tree 2 files changed +23
-18
lines changed
2 files changed +23
-18
lines changed Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ Gem::Specification.new do |spec|
21
21
spec . test_files = Dir [ "test/**/*" , "spec/**/*" ]
22
22
spec . require_paths = [ "lib" ]
23
23
24
+ spec . add_runtime_dependency "atomic" , "~> 1.1"
24
25
spec . add_development_dependency "bundler" , "~> 1.3"
25
26
spec . add_development_dependency "rspec" , "~> 3.0"
26
27
spec . add_development_dependency "rake" , "~> 10.1"
Original file line number Diff line number Diff line change 1
1
require "forwardable"
2
- require "thread "
2
+ require "atomic "
3
3
4
4
require "hamster/core_ext/enumerable"
5
5
require "hamster/undefined"
@@ -686,9 +686,9 @@ class Stream
686
686
include List
687
687
688
688
def initialize ( &block )
689
- @block = block
690
- @lock = Mutex . new
691
- @size = nil
689
+ @target = block
690
+ @atomic = Atomic . new ( 0 ) # haven't yet run block
691
+ @size = nil
692
692
end
693
693
694
694
def_delegator :target , :head
@@ -705,22 +705,26 @@ def cached_size?
705
705
706
706
protected
707
707
708
- def vivify
709
- @lock . synchronize do
710
- unless @block . nil?
711
- @target = @block . call
712
- @block = nil
708
+ def target
709
+ if @atomic . get == 2 # target already realized?
710
+ @target
711
+ else
712
+ while true
713
+ # try to "claim" the right to run the block which realizes target
714
+ if @atomic . compare_and_swap ( 0 , 1 ) # full memory barrier here
715
+ @target = @target . call
716
+ @target = @target . target while @target . is_a? ( Stream )
717
+ @atomic . compare_and_swap ( 1 , 2 ) # another memory barrier
718
+ return @target
719
+ end
720
+ # we failed to "claim" it, another thread must be running it
721
+ if @atomic . get == 1 # another thread is running the block
722
+ next # spin
723
+ elsif @atomic . get == 2 # another thread finished the block
724
+ return @target
725
+ end
713
726
end
714
727
end
715
- @target
716
- end
717
-
718
- private
719
-
720
- def target
721
- list = vivify
722
- list = list . vivify while list . is_a? ( Stream )
723
- list
724
728
end
725
729
end
726
730
You can’t perform that action at this time.
0 commit comments