Skip to content

Commit eb554dd

Browse files
committed
Moved more docs from the wiki to yardoc.
1 parent 6ecabb4 commit eb554dd

20 files changed

+452
-32
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</p>
3131
</td>
3232
<td align="right" valign="top">
33-
<img src="https://raw.githubusercontent.com/wiki/ruby-concurrency/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png"/>
33+
<img src="https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/doc/logo/concurrent-ruby-logo-300x300.png"/>
3434
</td>
3535
</tr>
3636
</table>

doc/future.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
`Future` is inspired by [Clojure's](http://clojure.org/) [future](http://clojuredocs.org/clojure_core/clojure.core/future) function. A future represents a promise to complete an action at some time in the future. The action is atomic and permanent. The idea behind a future is to send an operation for asynchronous completion, do other stuff, then return and retrieve the result of the async operation at a later time. `Future`s run on the global thread pool.
2+
3+
```cucumber
4+
Feature:
5+
As a highly responsive Ruby application
6+
I want long-running tasks on a separate thread
7+
So I can perform other tasks without waiting
8+
```
9+
10+
`Future`s have four possible states: *:unscheduled*, *:pending*, *:rejected*, and *:fulfilled*. When a `Future` is created it is set to *:unscheduled*. Once the `#execute` method is called the state becomes *:pending* and will remain in that state until processing is complete. A completed `Future` is either *:rejected*, indicating that an exception was thrown during processing, or *:fulfilled*, indicating success. If a `Future` is *:fulfilled* its `#value` will be updated to reflect the result of the operation. If *:rejected* the `reason` will be updated with a reference to the thrown exception. The predicate methods `#unscheduled?`, `#pending?`, `#rejected?`, and `#fulfilled?` can be called at any time to obtain the state of the `Future`, as can the `#state` method, which returns a symbol.
11+
12+
Retrieving the value of a `Future` is done through the `#value` (alias: `#deref`) method. Obtaining the value of a `Future` is a potentially blocking operation. When a `Future` is *:rejected* a call to `#value` will return `nil` immediately. When a `Future` is *:fulfilled* a call to `#value` will immediately return the current value. When a `Future` is *:pending* a call to `#value` will block until the `Future` is either *:rejected* or *:fulfilled*. A *timeout* value can be passed to `#value` to limit how long the call will block. If `nil` the call will block indefinitely. If `0` the call will not block. Any other integer or float value will indicate the maximum number of seconds to block.
13+
14+
The constructor can also be given zero or more processing options. Currently the only supported options are those recognized by the [Dereferenceable](Dereferenceable) module.
15+
16+
The `Future` class also includes the behavior of the Ruby standard library [Observable](http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html) module, but does so in a thread-safe way. On fulfillment or rejection all observers will be notified according to the normal `Observable` behavior. The observer callback function will be called with three parameters: the `Time` of fulfillment/rejection, the final `value`, and the final `reason`. Observers added after fulfillment/rejection will still be notified as normal. The notification will occur on the global thread pool.
17+
18+
### Examples
19+
20+
A fulfilled example:
21+
22+
```ruby
23+
require 'concurrent'
24+
25+
count = Concurrent::Future.new{ sleep(10); 10 }.execute
26+
count.state #=> :pending
27+
count.pending? #=> true
28+
29+
# do stuff...
30+
31+
count.value(0) #=> nil (does not block)
32+
33+
count.value #=> 10 (after blocking)
34+
count.state #=> :fulfilled
35+
count.fulfilled? #=> true
36+
count.value #=> 10
37+
```
38+
39+
A rejected example:
40+
41+
```ruby
42+
count = Concurrent::Future.execute{ sleep(10); raise StandardError.new("Boom!") }
43+
count.state #=> :pending
44+
count.pending? #=> true
45+
46+
count.value #=> nil (after blocking)
47+
count.rejected? #=> true
48+
count.reason #=> #<StandardError: Boom!>
49+
```
50+
51+
An example with observation:
52+
53+
```ruby
54+
class Ticker
55+
Stock = Struct.new(:symbol, :name, :exchange)
56+
57+
def update(time, value, reason)
58+
ticker = value.collect do |symbol|
59+
Stock.new(symbol['symbol'], symbol['name'], symbol['exch'])
60+
end
61+
62+
output = ticker.join("\n")
63+
print "#{output}\n"
64+
end
65+
end
66+
67+
yahoo = Finance.new('YAHOO')
68+
future = Concurrent::Future.new { yahoo.update.suggested_symbols }
69+
future.add_observer(Ticker.new)
70+
future.execute
71+
72+
# do important stuff...
73+
74+
#>> #<struct Ticker::Stock symbol="YHOO", name="Yahoo! Inc.", exchange="NMS">
75+
#>> #<struct Ticker::Stock symbol="YHO.DE", name="Yahoo! Inc.", exchange="GER">
76+
#>> #<struct Ticker::Stock symbol="YAHOY", name="Yahoo Japan Corporation", exchange="PNK">
77+
#>> #<struct Ticker::Stock symbol="YAHOF", name="YAHOO JAPAN CORP", exchange="PNK">
78+
#>> #<struct Ticker::Stock symbol="YOJ.SG", name="YAHOO JAPAN", exchange="STU">
79+
#>> #<struct Ticker::Stock symbol="YHO.SG", name="YAHOO", exchange="STU">
80+
#>> #<struct Ticker::Stock symbol="YHOO.BA", name="Yahoo! Inc.", exchange="BUE">
81+
#>> #<struct Ticker::Stock symbol="YHO.DU", name="YAHOO", exchange="DUS">
82+
#>> #<struct Ticker::Stock symbol="YHO.HM", name="YAHOO", exchange="HAM">
83+
#>> #<struct Ticker::Stock symbol="YHO.BE", name="YAHOO", exchange="BER">
84+
```
110 KB
Loading
107 KB
Loading
120 KB
Loading
115 KB
Loading
89.5 KB
Loading

doc/images/tvar/ruby-absolute.png

99.9 KB
Loading

doc/images/tvar/ruby-scalability.png

94.2 KB
Loading
25.9 KB
Loading

0 commit comments

Comments
 (0)