promise 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/AUTHORS +2 -0
  2. data/VERSION +1 -1
  3. data/lib/future.rb +29 -31
  4. data/lib/promise.rb +40 -35
  5. metadata +5 -5
data/AUTHORS CHANGED
@@ -1 +1,3 @@
1
1
  * Ben Lavender <blavender@gmail.com> (Lead developer)
2
+ * Arto Bendiken <arto.bendiken@gmail.com>
3
+ Special thanks to Marc-André Lafortune for some excellent code review
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -1,67 +1,65 @@
1
1
  require 'promise'
2
2
 
3
3
  ##
4
- # A delayed-execution result, optimistcally evaluated in a new Thread.
4
+ # A delayed-execution result, optimistically evaluated in a new thread.
5
+ #
5
6
  # @example
6
- # x = future { sleep 5; 1 + 2 }
7
- # # do stuff...
8
- # y = x * 2 # => 6. blocks unless 5 seconds has passed.
7
+ # x = future { sleep 5; 1 + 2 }
8
+ # # do stuff...
9
+ # y = x * 2 # => 6. blocks unless 5 seconds has passed.
9
10
  #
10
11
  class Future < defined?(BasicObject) ? BasicObject : Object
11
-
12
12
  instance_methods.each { |m| undef_method m unless m =~ /__/ } unless defined?(BasicObject)
13
13
 
14
14
  ##
15
- # Create a new future
15
+ # Creates a new future.
16
16
  #
17
- # @yield [] The block to evaluate optimistically
18
- # @return [Future]
19
- def initialize(block)
20
- @promise = promise &block
21
- @thread = ::Thread.new do
22
- @promise.force
23
- end
17
+ # @yield [] The block to evaluate optimistically.
18
+ # @see Kernel#future
19
+ def initialize(&block)
20
+ @promise = ::Promise.new(&block)
21
+ @thread = ::Thread.new { @promise.__force__ }
24
22
  end
25
23
 
26
24
  ##
27
25
  # The value of the future's evaluation. Blocks until result available.
28
26
  #
29
- # @return [Any]
27
+ # @return [Object]
30
28
  def __force__
31
- @thread.join
29
+ @thread.join if @thread
32
30
  @promise
33
31
  end
34
32
  alias_method :force, :__force__
35
33
 
36
34
  ##
37
- # Does this promise support the given method?
35
+ # Does this future support the given method?
38
36
  #
39
37
  # @param [Symbol]
40
- # @return [true, false]
38
+ # @return [Boolean]
41
39
  def respond_to?(method)
42
- (method == :force) || (method == :__force__) || (__force__.respond_to?(method))
40
+ :force.equal?(method) || :__force__.equal?(method) || __force__.respond_to?(method)
43
41
  end
44
42
 
45
- # @private
43
+ private
44
+
46
45
  def method_missing(method, *args, &block)
47
- @promise.send(method, *args, &block)
46
+ __force__.__send__(method, *args, &block)
48
47
  end
49
-
50
-
51
48
  end
52
49
 
53
-
54
50
  module Kernel
55
-
56
- # Create a new future
51
+ ##
52
+ # Creates a new future.
57
53
  #
58
54
  # @example Evaluate an operation in another thread
59
- # x = future { 3 + 3 }
60
- # @return [Future]
61
- # @yield [] A block to be optimistically evaluated in another thread
62
- # @yieldreturn [Any] The return value of the block will be the evaluated value of the future.
55
+ # x = future { 3 + 3 }
56
+ #
57
+ # @yield []
58
+ # A block to be optimistically evaluated in another thread.
59
+ # @yieldreturn [Object]
60
+ # The return value of the block will be the evaluated value of the future.
61
+ # @return [Future]
63
62
  def future(&block)
64
- Future.new(block)
63
+ Future.new(&block)
65
64
  end
66
-
67
65
  end
@@ -1,36 +1,38 @@
1
1
  ##
2
2
  # A delayed-execution promise. Promises are only executed once.
3
+ #
3
4
  # @example
4
- # x = promise { factorial 20 }
5
- # y = promise { fibonacci 10**6 }
6
- # a = x + 1 # => factorial 20 + 1 after factorial calculates
7
- # result = promise { a += y }
8
- # abort "" # whew, we never needed to calculate y
5
+ # x = promise { factorial 20 }
6
+ # y = promise { fibonacci 10**6 }
7
+ # a = x + 1 # => factorial 20 + 1 after factorial calculates
8
+ # result = promise { a += y }
9
+ # abort "" # whew, we never needed to calculate y
10
+ #
9
11
  # @example
10
- # y = 5
11
- # x = promise { y = y + 5 }
12
- # x + 5 # => 15
13
- # x + 5 # => 15
12
+ # y = 5
13
+ # x = promise { y = y + 5 }
14
+ # x + 5 # => 15
15
+ # x + 5 # => 15
16
+ #
14
17
  class Promise < defined?(BasicObject) ? BasicObject : ::Object
18
+ NOT_SET = ::Object.new.freeze
15
19
 
16
20
  instance_methods.each { |m| undef_method m unless m.to_s =~ /__/ }
17
21
 
18
- NOT_SET = ::Object.new.freeze
19
-
20
22
  ##
21
- # Create a new promise
23
+ # Creates a new promise.
22
24
  #
23
25
  # @example Lazily evaluate a database call
24
- # result = promise { @db.query("SELECT * FROM TABLE") }
25
- # @param [Proc] block
26
- # @return [Promise]
27
- # @see Kernel#promise
28
- def initialize(block)
26
+ # result = promise { @db.query("SELECT * FROM TABLE") }
27
+ #
28
+ # @yield [] The block to evaluate lazily.
29
+ # @see Kernel#promise
30
+ def initialize(&block)
29
31
  if block.arity > 0
30
32
  raise ArgumentError, "Cannot store a promise that requires an argument"
31
33
  end
32
- @block = block
33
- @mutex = ::Mutex.new
34
+ @block = block
35
+ @mutex = ::Mutex.new
34
36
  @result = NOT_SET
35
37
  @error = NOT_SET
36
38
  end
@@ -38,19 +40,19 @@ class Promise < defined?(BasicObject) ? BasicObject : ::Object
38
40
  ##
39
41
  # Force the evaluation of this promise immediately
40
42
  #
41
- # @return [Any]
43
+ # @return [Object]
42
44
  def __force__
43
45
  @mutex.synchronize do
44
- if @result == NOT_SET && @error == NOT_SET
46
+ if @result.equal?(NOT_SET) && @error.equal?(NOT_SET)
45
47
  begin
46
48
  @result = @block.call
47
49
  rescue ::Exception => e
48
50
  @error = e
49
51
  end
50
52
  end
51
- end if @result == NOT_SET && @error == NOT_SET
53
+ end if @result.equal?(NOT_SET) && @error.equal?(NOT_SET)
52
54
  # BasicObject won't send raise to Kernel
53
- @error.equal?(NOT_SET) ? @result : (::Kernel.raise @error)
55
+ @error.equal?(NOT_SET) ? @result : ::Kernel.raise(@error)
54
56
  end
55
57
  alias_method :force, :__force__
56
58
 
@@ -58,28 +60,31 @@ class Promise < defined?(BasicObject) ? BasicObject : ::Object
58
60
  # Does this promise support the given method?
59
61
  #
60
62
  # @param [Symbol]
61
- # @return [true, false]
63
+ # @return [Boolean]
62
64
  def respond_to?(method)
63
- (method == :force) || (method == :__force__) || (__force__.respond_to?(method))
65
+ :force.equal?(method) || :__force__.equal?(method) || __force__.respond_to?(method)
64
66
  end
65
67
 
68
+ private
69
+
66
70
  def method_missing(method, *args, &block)
67
- __force__
68
- @result.send(method, *args, &block)
71
+ __force__.__send__(method, *args, &block)
69
72
  end
70
73
  end
71
74
 
72
75
  module Kernel
73
-
74
- # Create a new promise
76
+ ##
77
+ # Creates a new promise.
75
78
  #
76
79
  # @example Lazily evaluate an arithmetic operation
77
- # x = promise { 3 + 3 }
78
- # @return [Promise]
79
- # @yield [] A block to be lazily evaluated
80
- # @yieldreturn [Any] The return value of the block will be the lazily evaluated value of the promise.
80
+ # x = promise { 3 + 3 }
81
+ #
82
+ # @yield []
83
+ # A block to be lazily evaluated.
84
+ # @yieldreturn [Object]
85
+ # The return value of the block will be the lazily evaluated value of the promise.
86
+ # @return [Promise]
81
87
  def promise(&block)
82
- Promise.new(block)
88
+ Promise.new(&block)
83
89
  end
84
-
85
90
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 0
9
- version: 0.2.0
8
+ - 1
9
+ version: 0.2.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Ben Lavender
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-22 00:00:00 -05:00
17
+ date: 2010-06-29 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -41,8 +41,8 @@ dependencies:
41
41
  segments:
42
42
  - 0
43
43
  - 5
44
- - 6
45
- version: 0.5.6
44
+ - 8
45
+ version: 0.5.8
46
46
  type: :development
47
47
  version_requirements: *id002
48
48
  description: " A glimpse of a promising future in which Ruby supports delayed execution.\n Provides global 'promise' and 'future' methods.\n"