diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-15 21:59:37 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-15 21:59:37 +0000 |
commit | 9c66bad9f3d522d50d4a45ef8a3a92abbf93229f (patch) | |
tree | 8fc1ae219e41bdd711442b1d35149da4f45dfa8a /lib/rake/promise.rb | |
parent | bfc95c6e1639edc909338ef4d20d990caf6f630e (diff) | |
download | ruby-9c66bad9f3d522d50d4a45ef8a3a92abbf93229f.tar.gz |
* lib/rake*: Updated to rake 0.9.3
* test/rake*: ditto
* bin/rake: ditto
* NEWS: ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37664 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rake/promise.rb')
-rw-r--r-- | lib/rake/promise.rb | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/rake/promise.rb b/lib/rake/promise.rb new file mode 100644 index 0000000000..3258b91139 --- /dev/null +++ b/lib/rake/promise.rb @@ -0,0 +1,99 @@ +module Rake + + # A Promise object represents a promise to do work (a chore) in the + # future. The promise is created with a block and a list of + # arguments for the block. Calling value will return the value of + # the promised chore. + # + # Used by ThreadPool. + # + class Promise # :nodoc: all + NOT_SET = Object.new.freeze # :nodoc: + + attr_accessor :recorder + + # Create a promise to do the chore specified by the block. + def initialize(args, &block) + @mutex = Mutex.new + @result = NOT_SET + @error = NOT_SET + @args = args.collect { |a| begin; a.dup; rescue; a; end } + @block = block + end + + # Return the value of this promise. + # + # If the promised chore is not yet complete, then do the work + # synchronously. We will wait. + def value + unless complete? + stat :sleeping_on, :item_id => object_id + @mutex.synchronize do + stat :has_lock_on, :item_id => object_id + chore + stat :releasing_lock_on, :item_id => object_id + end + end + error? ? raise(@error) : @result + end + + # If no one else is working this promise, go ahead and do the chore. + def work + stat :attempting_lock_on, :item_id => object_id + if @mutex.try_lock + stat :has_lock_on, :item_id => object_id + chore + stat :releasing_lock_on, :item_id => object_id + @mutex.unlock + else + stat :bailed_on, :item_id => object_id + end + end + + private + + # Perform the chore promised + def chore + if complete? + stat :found_completed, :item_id => object_id + return + end + stat :will_execute, :item_id => object_id + begin + @result = @block.call(*@args) + rescue Exception => e + @error = e + end + stat :did_execute, :item_id => object_id + discard + end + + # Do we have a result for the promise + def result? + ! @result.equal?(NOT_SET) + end + + # Did the promise throw an error + def error? + ! @error.equal?(NOT_SET) + end + + # Are we done with the promise + def complete? + result? || error? + end + + # free up these items for the GC + def discard + @args = nil + @block = nil + end + + # Record execution statistics if there is a recorder + def stat(*args) + @recorder.call(*args) if @recorder + end + + end + +end |