1
1
# Concurrent Ruby
2
- [ ![ Gem Version] ( https://badge.fury.io/rb/concurrent-ruby.png )] ( http://badge.fury.io/rb/concurrent-ruby ) [ ![ Build Status] ( https://secure.travis-ci.org/jdantonio/concurrent-ruby.png )] ( https://travis-ci.org/jdantonio/concurrent-ruby?branch=master ) [ ![ Coverage Status] ( https://coveralls.io/repos/jdantonio/concurrent-ruby/badge.png )] ( https://coveralls.io/r/jdantonio/concurrent-ruby ) [ ![ Code Climate] ( https://codeclimate.com/github/jdantonio/concurrent-ruby.png )] ( https://codeclimate.com/github/jdantonio/concurrent-ruby ) [ ![ Dependency Status] ( https://gemnasium.com/jdantonio/concurrent-ruby.png )] ( https://gemnasium.com/jdantonio/concurrent-ruby )
2
+ [ ![ Gem Version] ( https://badge.fury.io/rb/concurrent-ruby.png )] ( http://badge.fury.io/rb/concurrent-ruby ) [ ![ Build Status] ( https://secure.travis-ci.org/jdantonio/concurrent-ruby.png )] ( https://travis-ci.org/jdantonio/concurrent-ruby?branch=master ) [ ![ Coverage Status] ( https://coveralls.io/repos/jdantonio/concurrent-ruby/badge.png )] ( https://coveralls.io/r/jdantonio/concurrent-ruby ) [ ![ Code Climate] ( https://codeclimate.com/github/jdantonio/concurrent-ruby.png )] ( https://codeclimate.com/github/jdantonio/concurrent-ruby ) [ ![ Inline docs ] ( http://inch-pages.github.io/github/jdantonio/concurrent-ruby.png )] ( http://inch-pages.github.io/github/jdantonio/concurrent-ruby ) [ ![ Dependency Status] ( https://gemnasium.com/jdantonio/concurrent-ruby.png )] ( https://gemnasium.com/jdantonio/concurrent-ruby )
3
3
4
4
*** NOTE:*** * A few API updates in v0.5.0 are not backward-compatible. Please see the [ release notes] ( https://github.com/jdantonio/concurrent-ruby/wiki/API-Updates-in-v0.5.0 ) .*
5
5
6
+ <table >
7
+ <tr >
8
+ <td align =" left " valign =" top " >
9
+ <p >
6
10
Modern concurrency tools for Ruby. Inspired by
7
- [ Erlang ] ( http://www.erlang.org/doc/reference_manual/processes.html ) ,
8
- [ Clojure ] ( http://clojure.org/concurrent_programming ) ,
9
- [ Scala ] ( http://www.scala-lang.org/api/current/index.html#scala.actors.Actor ) ,
10
- [ Haskell ] ( http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell ) ,
11
- [ F# ] ( http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx ) ,
12
- [ C# ] ( http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx ) ,
13
- [ Java ] ( http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html ) ,
11
+ < a href = " http://www.erlang.org/doc/reference_manual/processes.html " >Erlang</ a > ,
12
+ < a href = " http://clojure.org/concurrent_programming " >Clojure</ a > ,
13
+ < a href = " http://www.scala-lang.org/api/current/index.html#scala.actors.Actor " >Scala</ a > ,
14
+ < a href = " http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell " >Haskell</ a > ,
15
+ < a href = " http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx " >F#</ a > ,
16
+ < a href = " http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx " >C#</ a > ,
17
+ < a href = " http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html " >Java</ a > ,
14
18
and classic concurrency patterns.
15
-
19
+ </p >
20
+ <p >
16
21
The design goals of this gem are:
17
-
18
- * Stay true to the spirit of the languages providing inspiration
19
- * But implement in a way that makes sense for Ruby
20
- * Keep the semantics as idiomatic Ruby as possible
21
- * Support features that make sense in Ruby
22
- * Exclude features that don't make sense in Ruby
23
- * Be small, lean, and loosely coupled
22
+ <ul >
23
+ <li >Stay true to the spirit of the languages providing inspiration</li >
24
+ <li >But implement in a way that makes sense for Ruby</li >
25
+ <li >Keep the semantics as idiomatic Ruby as possible</li >
26
+ <li >Support features that make sense in Ruby</li >
27
+ <li >Exclude features that don't make sense in Ruby</li >
28
+ <li >Be small, lean, and loosely coupled</li >
29
+ </ul >
30
+ </p >
31
+ </td >
32
+ <td align =" right " valign =" top " >
33
+ <img src =" https://raw.githubusercontent.com/wiki/jdantonio/concurrent-ruby/logo/concurrent-ruby-logo-300x300.png " />
34
+ </td >
35
+ </tr >
36
+ </table >
24
37
25
38
## Features & Documentation
26
39
@@ -29,11 +42,13 @@ or the [API documentation](http://rubydoc.info/github/jdantonio/concurrent-ruby/
29
42
for more information or join our [ mailing list] ( http://groups.google.com/group/concurrent-ruby ) .
30
43
31
44
There are many concurrency abstractions in this library. These abstractions can be broadly categorized
32
- into several general categories :
45
+ into several general groups :
33
46
34
- * Asynchronous concurrency abstractions including [ Actor] ( https://github.com/jdantonio/concurrent-ruby/wiki/Actor ) ,
35
- [ Agent] ( https://github.com/jdantonio/concurrent-ruby/wiki/Agent ) , [ Channel] ( https://github.com/jdantonio/concurrent-ruby/wiki/Channel ) ,
36
- [ Future] ( https://github.com/jdantonio/concurrent-ruby/wiki/Future ) , [ Promise] ( https://github.com/jdantonio/concurrent-ruby/wiki/Promise ) ,
47
+ * Asynchronous concurrency abstractions including
48
+ [ Async] ( https://github.com/jdantonio/concurrent-ruby/wiki/Async ) ,
49
+ [ Agent] ( https://github.com/jdantonio/concurrent-ruby/wiki/Agent ) ,
50
+ [ Future] ( https://github.com/jdantonio/concurrent-ruby/wiki/Future ) ,
51
+ [ Promise] ( https://github.com/jdantonio/concurrent-ruby/wiki/Promise ) ,
37
52
[ ScheculedTask] ( https://github.com/jdantonio/concurrent-ruby/wiki/ScheduledTask ) ,
38
53
and [ TimerTask] ( https://github.com/jdantonio/concurrent-ruby/wiki/TimerTask )
39
54
* Erlang-inspired [ Supervisor] ( https://github.com/jdantonio/concurrent-ruby/wiki/Supervisor ) and other lifecycle classes/mixins
@@ -53,73 +68,67 @@ This gem adheres to the rules of [semantic versioning](http://semver.org/).
53
68
54
69
### Supported Ruby versions
55
70
56
- MRI 1.9.2, 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x. This library is pure Ruby and has no gem dependencies.
71
+ MRI 1.9.2, 1.9.3, 2.0, 2.1, JRuby (1.9 mode), and Rubinius 2.x.
72
+ This library is pure Ruby and has no gem dependencies.
57
73
It should be fully compatible with any Ruby interpreter that is 1.9.x compliant.
58
74
59
- ### Example
75
+ ### Examples
60
76
61
77
Many more code examples can be found in the documentation for each class (linked above).
62
78
This one simple example shows some of the power of this gem.
63
79
64
80
``` ruby
65
81
require ' concurrent'
66
- require ' faker'
67
-
68
- class EchoActor < Concurrent ::Actor
69
- def act (* message )
70
- puts " #{ message } handled by #{ self } "
82
+ require ' thread' # for Queue
83
+ require ' open-uri' # for open(uri)
84
+
85
+ class Ticker
86
+ def get_year_end_closing (symbol , year )
87
+ uri = " http://ichart.finance.yahoo.com/table.csv?s=#{ symbol } &a=11&b=01&c=#{ year } &d=11&e=31&f=#{ year } &g=m"
88
+ data = open (uri) {|f | f.collect{|line | line.strip } }
89
+ data[1 ].split(' ,' )[4 ].to_f
71
90
end
72
91
end
73
92
74
- mailbox, pool = EchoActor .pool(5 )
75
-
76
- timer_proc = proc do
77
- mailbox.post(Faker ::Company .bs)
78
- end
79
-
80
- t1 = Concurrent ::TimerTask .new (execution_interval: rand (5 )+ 1 , & timer_proc)
81
- t2 = Concurrent ::TimerTask .new (execution_interval: rand (5 )+ 1 , & timer_proc)
82
-
83
- overlord = Concurrent ::Supervisor .new
84
-
85
- overlord.add_worker(t1)
86
- overlord.add_worker(t2)
87
- pool.each{|actor | overlord.add_worker(actor)}
88
-
89
- overlord.run!
90
-
91
- # => ["mesh proactive platforms"] handled by #<EchoActor:0x007fa5ac18bdf8>
92
- # => ["maximize sticky portals"] handled by #<EchoActor:0x007fa5ac18bdd0>
93
- # => ["morph bleeding-edge markets"] handled by #<EchoActor:0x007fa5ac18bd80>
94
- # => ["engage clicks-and-mortar interfaces"] handled by #<EchoActor:0x007fa5ac18bd58>
95
- # => ["monetize transparent infrastructures"] handled by #<EchoActor:0x007fa5ac18bd30>
96
- # => ["morph sexy e-tailers"] handled by #<EchoActor:0x007fa5ac18bdf8>
97
- # => ["exploit dot-com models"] handled by #<EchoActor:0x007fa5ac18bdd0>
98
- # => ["incentivize virtual deliverables"] handled by #<EchoActor:0x007fa5ac18bd80>
99
- # => ["enhance B2B models"] handled by #<EchoActor:0x007fa5ac18bd58>
100
- # => ["envisioneer real-time architectures"] handled by #<EchoActor:0x007fa5ac18bd30>
101
-
102
- overlord.stop
93
+ # Future
94
+ price = Concurrent ::Future .execute{ Ticker .new .get_year_end_closing(' TWTR' , 2013 ) }
95
+ price.state # => :pending
96
+ sleep (1 ) # do other stuff
97
+ price.value # => 63.65
98
+ price.state # => :fulfilled
99
+
100
+ # Promise
101
+ prices = Concurrent ::Promise .new { puts Ticker .new .get_year_end_closing(' AAPL' , 2013 ) }.
102
+ then { puts Ticker .new .get_year_end_closing(' MSFT' , 2013 ) }.
103
+ then { puts Ticker .new .get_year_end_closing(' GOOG' , 2013 ) }.
104
+ then { puts Ticker .new .get_year_end_closing(' AMZN' , 2013 ) }.execute
105
+ prices.state # => :pending
106
+ sleep (1 ) # do other stuff
107
+ # => 561.02
108
+ # => 37.41
109
+ # => 1120.71
110
+ # => 398.79
111
+
112
+ # ScheduledTask
113
+ task = Concurrent ::ScheduledTask .execute(2 ){ Ticker .new .get_year_end_closing(' INTC' , 2013 ) }
114
+ task.state # => :pending
115
+ sleep (3 ) # do other stuff
116
+ task.value # => 25.96
117
+
118
+ # Async
119
+ ticker = Ticker .new
120
+ ticker.extend (Concurrent ::Async )
121
+ hpq = ticker.async.get_year_end_closing(' HPQ' , 2013 )
122
+ ibm = ticker.await.get_year_end_closing(' IBM' , 2013 )
123
+ hpq.value # => 27.98
124
+ ibm.value # => 187.57
103
125
```
104
126
105
- ### Disclaimer
106
-
107
- Remember, * there is no silver bullet in concurrent programming.* Concurrency is hard.
108
- These tools will help ease the burden, but at the end of the day it is essential that you
109
- * know what you are doing.*
110
-
111
- * Decouple business logic from concurrency logic
112
- * Test business logic separate from concurrency logic
113
- * Keep the intersection of business logic and concurrency and small as possible
114
- * Don't share mutable data unless absolutely necessary
115
- * Protect shared data as much as possible (prefer [ immutability] ( https://github.com/harukizaemon/hamster ) )
116
- * Don't mix Ruby's [ concurrency] ( http://ruby-doc.org/core-2.0.0/Thread.html )
117
- [ primitives] ( http://www.ruby-doc.org/core-2.0.0/Mutex.html ) with asynchronous concurrency libraries
118
-
119
127
## Contributors
120
128
121
129
* [ Michele Della Torre] ( https://github.com/mighe )
122
130
* [ Chris Seaton] ( https://github.com/chrisseaton )
131
+ * [ Lucas Allan] ( https://github.com/lucasallan )
123
132
* [ Giuseppe Capizzi] ( https://github.com/gcapizzi )
124
133
* [ Brian Shirai] ( https://github.com/brixen )
125
134
* [ Chip Miller] ( https://github.com/chip-miller )
@@ -138,3 +147,6 @@ These tools will help ease the burden, but at the end of the day it is essential
138
147
139
148
* Concurrent Ruby* is Copyright © ; 2013 [ Jerry D'Antonio] ( https://twitter.com/jerrydantonio ) .
140
149
It is free software released under the [ MIT License] ( http://www.opensource.org/licenses/MIT ) .
150
+
151
+ The * Concurrent Ruby* logo was designed by [ David Jones] ( https://twitter.com/zombyboy ) .
152
+ It is Copyright © ; 2014 Jerry D'Antonio. All Rights Reserved.
0 commit comments