Class: Ccrpc::Promise

Inherits:
Object
  • Object
show all
Defined in:
lib/ccrpc/lazy.rb

Overview

A promise is just a magic object that springs to life when it is actually used for the first time, running the provided block and assuming the identity of the resulting object.

This impersonation isn’t perfect – a promise wrapping nil or false will still be considered true by Ruby – but it’s good enough for most purposes. If you do need to unwrap the result object for some reason (e.g. for truth testing or for simple efficiency), you may do so via Kernel.demand.

Formally, a promise is a placeholder for the result of a deferred computation.

Constant Summary collapse

DIVERGES =

create this once here, rather than creating a proc object for every evaluation

lambda {|promise| raise DivergenceError.new }

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&computation) ⇒ Promise

:nodoc:



55
56
57
58
59
# File 'lib/ccrpc/lazy.rb', line 55

def initialize( &computation ) #:nodoc:
  @mutex = Mutex.new
  @computation = computation
  @exception = nil
end

Class Method Details

.demand(promise) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/ccrpc/lazy.rb', line 127

def self.demand( promise )
  if promise.respond_to? :__result__
    promise.__result__
  else # not really a promise
    promise
  end
end

Instance Method Details

#__result__Object

:nodoc:



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ccrpc/lazy.rb', line 68

def __result__ #:nodoc:
  @mutex.synchronize do
    if @computation
      raise @exception if @exception

      computation = @computation
      @computation = DIVERGES # trap divergence due to over-eager recursion

      begin
        @result = Promise.demand( computation.call( self ) )
        @computation = nil
      rescue DivergenceError => exception
        @exception = exception
        raise
      rescue Exception => exception
        # handle exceptions
        @exception = LazyException.new( exception )
        raise @exception
      end
    end

    @result
  end
end

#inspectObject

:nodoc:



93
94
95
96
97
98
99
100
101
# File 'lib/ccrpc/lazy.rb', line 93

def inspect #:nodoc:
  @mutex.synchronize do
    if @computation
      "#<#{ __class__ } computation=#{ @computation.inspect }>"
    else
      @result.inspect
    end
  end
end

#marshal_dumpObject



103
104
105
106
# File 'lib/ccrpc/lazy.rb', line 103

def marshal_dump
  __result__
  Marshal.dump( [ @exception, @result ] )
end

#marshal_load(str) ⇒ Object



108
109
110
111
112
# File 'lib/ccrpc/lazy.rb', line 108

def marshal_load( str )
  @mutex = Mutex.new
  ( @exception, @result ) = Marshal.load( str )
  @computation = DIVERGES if @exception
end

#respond_to?(message, include_all = false) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
# File 'lib/ccrpc/lazy.rb', line 114

def respond_to?( message, include_all=false ) #:nodoc:
  message = message.to_sym
  message == :__result__ or
  message == :inspect or
  message == :marshal_dump or
  message == :marshal_load or
  __result__.respond_to?(message, include_all)
end