promise 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"