Class: FutureResource

Inherits:
Object
  • Object
show all
Defined in:
lib/future-resource.rb,
lib/future-resource/version.rb

Overview

future-resource allows you to wait on a final value being set for a placeholder, which may occur asynchronously.

Examples:

false printed first, followed by a delay before :foo is printed

fr = FutureResource.new

Thread.new do
  sleep 10
  fr.resource = :foo
end

p fr.set_yet?
p fr.resource

Author:

  • Ben Langfeld

  • Jay Phillips

Defined Under Namespace

Classes: ResourceAlreadySetException, Terminated

Constant Summary collapse

VERSION =
"1.1.0"

Instance Method Summary collapse

Constructor Details

#initialize(blocker = nil) ⇒ FutureResource

Create a new FutureResource.


26
27
28
29
30
# File 'lib/future-resource.rb', line 26

def initialize(blocker = nil)
  @resource_lock          = Monitor.new
  @resource_value_blocker = blocker || @resource_lock.new_cond
  @terminated             = false
end

Instance Method Details

#resource(timeout = nil) ⇒ Object

Returns the value of a specific resource, optionally waiting for `timeout` seconds before raising a Timeout::Error exception, or raising a FutureResource::Terminated exception if the attempt to read the resource is terminated early by another thread. When called on an unset resource without a timeout, raises a deadlock.

Parameters:

  • timeout (Integer) (defaults to: nil)

    number of seconds to wait for the resource to become ready

Returns:

  • (Object)

Raises:

  • (Timeout::Error)

    if timeout expires and resource is not ready

  • (FutureResource::Terminated)

    if the attempt to read the resource is terminated by another thread


63
64
65
66
67
68
69
70
71
# File 'lib/future-resource.rb', line 63

def resource(timeout = nil)
  Timeout::timeout timeout do
    @resource_lock.synchronize do
      @resource_value_blocker.wait unless set_yet? or terminated?
      raise Terminated if terminated?
      @resource
    end
  end
end

#resource=(resource) ⇒ Object

Sets the value for the resource, making it available for all waiting and following reads. Resource values can only be set once. Calling this method on a terminated resource is ineffective.

Parameters:

  • resource (Object)

    any value to be set for the resource

Raises:

  • (FutureResource::ResourceAlreadySet)

    if resource is already set


82
83
84
85
86
# File 'lib/future-resource.rb', line 82

def resource=(resource)
  set_or_terminate do
    @resource = resource
  end
end

#set_yet?Boolean

Checks if the value of the resource placeholder has been set yet.

Returns:

  • (Boolean)

37
38
39
# File 'lib/future-resource.rb', line 37

def set_yet?
  !!@resource_lock.synchronize { defined? @resource }
end

#terminateObject

Terminates the attempt to read the resource early, causing those waiting and any following reads to raise a FutureResource::Terminated exception. Subsequently calling this method again is ineffective.

Raises:

  • (FutureResource::ResourceAlreadySet)

    if resource is already set


95
96
97
98
99
# File 'lib/future-resource.rb', line 95

def terminate
  set_or_terminate do
    @terminated = true
  end
end

#terminated?Boolean

Checks if the attempt to read the resource has been terminated.

Returns:

  • (Boolean)

46
47
48
# File 'lib/future-resource.rb', line 46

def terminated?
  !!@resource_lock.synchronize { @terminated }
end