class Salus::Future

Constants

Cancel

Public Class Methods

finalizer(thread) click to toggle source

@private

# File lib/salus/thread/future.rb, line 46
def self.finalizer(thread)
  proc {
    if thread.weakref_alive?
      if thread.is_a? Thread
        thread.raise Cancel
      else
        thread.terminate! Cancel
      end
    end
  }
end
new(pool = nil, &block) click to toggle source

Create a future with the passed block and optionally using the passed pool.

# File lib/salus/thread/future.rb, line 23
def initialize(pool = nil, &block)
  raise ArgumentError, 'no block given' unless block

  @mutex = Mutex.new

  task = proc {
    begin
      deliver block.call
      notify_and_delete_observers(Time.now, @value, nil)
    rescue Exception => e
      @exception = e
      notify_and_delete_observers(Time.now, nil, e)
      log DEBUG, @exception
      deliver nil
    end
  }

  @thread = pool ? pool.process(&task) : Thread.new(&task)

  ObjectSpace.define_finalizer self, self.class.finalizer(WeakRef.new(@thread))
end

Public Instance Methods

!(timeout = nil)
Alias for: value!
cancel() click to toggle source

Cancel the future, {#value} will yield a Cancel exception

# File lib/salus/thread/future.rb, line 82
def cancel
  return self if delivered?

  @mutex.synchronize {
    if @thread.is_a? Thread
      @thread.raise Cancel
    else
      @thread.terminate! Cancel
    end

    @exception = Cancel.new
  }

  self
end
cancelled?() click to toggle source

Check if the future has been cancelled

# File lib/salus/thread/future.rb, line 99
def cancelled?
  @mutex.synchronize {
    @exception.is_a? Cancel
  }
end
delivered?() click to toggle source

Check if the future has been called.

# File lib/salus/thread/future.rb, line 73
def delivered?
  @mutex.synchronize {
    instance_variable_defined? :@value
  }
end
Also aliased as: realized?
exception() click to toggle source

Return the raised exception.

# File lib/salus/thread/future.rb, line 66
def exception
  @mutex.synchronize {
    @exception
  }
end
exception?() click to toggle source

Check if an exception has been raised.

# File lib/salus/thread/future.rb, line 59
def exception?
  @mutex.synchronize {
    instance_variable_defined? :@exception
  }
end
realized?()
Alias for: delivered?
value(timeout = nil) click to toggle source

Get the value of the future, if it's not finished running this call will block.

In case the block raises an exception, it will be raised, the exception is cached and will be raised every time you access the value.

An optional timeout can be passed which will return nil if nothing has been delivered.

# File lib/salus/thread/future.rb, line 112
def value(timeout = nil)
  raise @exception if exception?

  return @value if delivered?

  @mutex.synchronize {
    cond.wait(@mutex, *timeout)
  }

  if exception?
    raise @exception
  elsif delivered?
    return @value
  end
end
Also aliased as: ~
value!(timeout = nil) click to toggle source

Do the same as {#value}, but return nil in case of exception.

# File lib/salus/thread/future.rb, line 131
def value!(timeout = nil)
  begin
    value(timeout)
  rescue Exception
    nil
  end
end
Also aliased as: !
~(timeout = nil)
Alias for: value

Private Instance Methods

cond() click to toggle source
# File lib/salus/thread/future.rb, line 146
def cond
  @cond ||= ConditionVariable.new
end
cond?() click to toggle source
# File lib/salus/thread/future.rb, line 142
def cond?
  instance_variable_defined? :@cond
end
deliver(value) click to toggle source
# File lib/salus/thread/future.rb, line 150
def deliver (value)
  return if delivered?

  @mutex.synchronize {
    @value = value

    cond.broadcast if cond?
  }

  self
end