/
future.rb
65 lines (58 loc) · 1.53 KB
/
future.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
require 'promise'
##
# A delayed-execution result, optimistically evaluated in a new thread.
#
# @example
# x = future { sleep 5; 1 + 2 }
# # do stuff...
# y = x * 2 # => 6. blocks unless 5 seconds has passed.
#
class Future < defined?(BasicObject) ? BasicObject : Object
instance_methods.each { |m| undef_method m unless m =~ /^(__.*|object_id)$/ }
##
# Creates a new future.
#
# @yield [] The block to evaluate optimistically.
# @see Kernel#future
def initialize(&block)
@promise = ::Promise.new(&block)
@thread = ::Thread.new { @promise.__force__ }
end
##
# The value of the future's evaluation. Blocks until result available.
#
# @return [Object]
def __force__
@thread.join if @thread
@promise
end
alias_method :force, :__force__
##
# Does this future support the given method?
#
# @param [Symbol]
# @return [Boolean]
def respond_to?(method, include_all=false)
:force.equal?(method) || :__force__.equal?(method) || __force__.respond_to?(method, include_all)
end
private
def method_missing(method, *args, &block)
__force__.__send__(method, *args, &block)
end
end
module Kernel
##
# Creates a new future.
#
# @example Evaluate an operation in another thread
# x = future { 3 + 3 }
#
# @yield []
# A block to be optimistically evaluated in another thread.
# @yieldreturn [Object]
# The return value of the block will be the evaluated value of the future.
# @return [Future]
def future(&block)
Future.new(&block)
end
end