diff options
| author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 | 
|---|---|---|
| committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 | 
| commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
| tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rake/promise.rb | |
Fresh start
Diffstat (limited to 'jni/ruby/lib/rake/promise.rb')
| -rw-r--r-- | jni/ruby/lib/rake/promise.rb | 99 | 
1 files changed, 99 insertions, 0 deletions
diff --git a/jni/ruby/lib/rake/promise.rb b/jni/ruby/lib/rake/promise.rb new file mode 100644 index 0000000..31c4563 --- /dev/null +++ b/jni/ruby/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 +      @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  | 
