concurrent-ruby 0.2.1 → 0.2.2

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -21
  3. data/README.md +276 -275
  4. data/lib/concurrent.rb +28 -28
  5. data/lib/concurrent/agent.rb +114 -114
  6. data/lib/concurrent/cached_thread_pool.rb +131 -131
  7. data/lib/concurrent/defer.rb +65 -65
  8. data/lib/concurrent/event.rb +60 -60
  9. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  10. data/lib/concurrent/executor.rb +96 -96
  11. data/lib/concurrent/fixed_thread_pool.rb +99 -99
  12. data/lib/concurrent/functions.rb +120 -120
  13. data/lib/concurrent/future.rb +42 -42
  14. data/lib/concurrent/global_thread_pool.rb +24 -16
  15. data/lib/concurrent/goroutine.rb +29 -29
  16. data/lib/concurrent/null_thread_pool.rb +22 -22
  17. data/lib/concurrent/obligation.rb +67 -67
  18. data/lib/concurrent/promise.rb +174 -174
  19. data/lib/concurrent/reactor.rb +166 -166
  20. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  21. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  22. data/lib/concurrent/supervisor.rb +105 -105
  23. data/lib/concurrent/thread_pool.rb +76 -76
  24. data/lib/concurrent/utilities.rb +32 -32
  25. data/lib/concurrent/version.rb +3 -3
  26. data/lib/concurrent_ruby.rb +1 -1
  27. data/md/agent.md +123 -123
  28. data/md/defer.md +174 -174
  29. data/md/event.md +32 -32
  30. data/md/executor.md +187 -187
  31. data/md/future.md +83 -83
  32. data/md/goroutine.md +52 -52
  33. data/md/obligation.md +32 -32
  34. data/md/promise.md +227 -227
  35. data/md/thread_pool.md +224 -224
  36. data/spec/concurrent/agent_spec.rb +390 -386
  37. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  38. data/spec/concurrent/defer_spec.rb +199 -195
  39. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  40. data/spec/concurrent/event_spec.rb +134 -134
  41. data/spec/concurrent/executor_spec.rb +200 -200
  42. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  43. data/spec/concurrent/functions_spec.rb +217 -217
  44. data/spec/concurrent/future_spec.rb +112 -108
  45. data/spec/concurrent/global_thread_pool_spec.rb +11 -38
  46. data/spec/concurrent/goroutine_spec.rb +67 -67
  47. data/spec/concurrent/null_thread_pool_spec.rb +57 -57
  48. data/spec/concurrent/obligation_shared.rb +132 -132
  49. data/spec/concurrent/promise_spec.rb +316 -312
  50. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  51. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  52. data/spec/concurrent/reactor_spec.rb +364 -364
  53. data/spec/concurrent/supervisor_spec.rb +269 -269
  54. data/spec/concurrent/thread_pool_shared.rb +204 -204
  55. data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
  56. data/spec/concurrent/utilities_spec.rb +74 -74
  57. data/spec/spec_helper.rb +32 -32
  58. metadata +17 -19
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b0cd24fc7583a5575559eacbeeddc5d23fdae43f
4
+ data.tar.gz: addd7382eda8182216f5d86b0c53a75030c49439
5
+ SHA512:
6
+ metadata.gz: 658d79b611fd7f572beeb73096b80addf9fab04ee8a06f75f914a3dd780dad86038519c5338d73fb540dd62d0683dce26c5c25b5419978bef79c5e72171e9052
7
+ data.tar.gz: fa5977a3f4bb3d1195f0aa4a00fc3fea84f86ee4d9d751d2c3d1916e6e94fe09daa74885016769e41d5640d7567cdc6d47e0bbd32cbdb8bf5546041a1bf9d3aa
data/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- Copyright (c) Jerry D'Antonio -- released under the MIT license.
2
-
3
- http://www.opensource.org/licenses/mit-license.php
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ Copyright (c) Jerry D'Antonio -- released under the MIT license.
2
+
3
+ http://www.opensource.org/licenses/mit-license.php
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,275 +1,276 @@
1
- # Concurrent Ruby [![Build Status](https://secure.travis-ci.org/jdantonio/concurrent-ruby.png)](https://travis-ci.org/jdantonio/concurrent-ruby?branch=master) [![Dependency Status](https://gemnasium.com/jdantonio/concurrent-ruby.png)](https://gemnasium.com/jdantonio/concurrent-ruby)
2
-
3
- Erlang, Clojure, and Go inspired concurrent programming tools for Ruby.
4
-
5
- ## Introduction
6
-
7
- The old-school "lock and synchronize" approach to concurrency is dead. The future of concurrency
8
- is asynchronous. Send out a bunch of independent [actors](http://en.wikipedia.org/wiki/Actor_model)
9
- to do your bidding and process the results when you are ready. Although the idea of the concurrent
10
- actor originated in the early 1970's it has only recently started catching on. Although there is
11
- no one "true" actor implementation (what *exactly* is "object oriented," what *exactly* is
12
- "concurrent programming"), many modern programming languages implement variations on the actor
13
- theme. This library implements a few of the most interesting and useful of those variations.
14
-
15
- Remember, *there is no silver bullet in concurrent programming.* Concurrency is hard. Very hard.
16
- These tools will help ease the burden, but at the end of the day it is essential that you
17
- *know what you are doing.*
18
-
19
- The project is hosted on the following sites:
20
-
21
- * [RubyGems project page](https://rubygems.org/gems/concurrent-ruby)
22
- * [Source code on GitHub](https://github.com/jdantonio/concurrent-ruby)
23
- * [YARD documentation on RubyDoc.info](http://rubydoc.info/github/jdantonio/concurrent-ruby/frames)
24
- * [Continuous integration on Travis-CI](https://travis-ci.org/jdantonio/concurrent-ruby)
25
- * [Dependency tracking on Gemnasium](https://gemnasium.com/jdantonio/concurrent-ruby)
26
- * [Follow me on Twitter](https://twitter.com/jerrydantonio)
27
-
28
- ### Goals
29
-
30
- My history with high-performance, highly-concurrent programming goes back to my days with C/C++.
31
- I have the same scars as everyone else doing that kind of work with those languages.
32
- I'm fascinated by modern concurrency patterns like [Actors](http://en.wikipedia.org/wiki/Actor_model),
33
- [Agents](http://doc.akka.io/docs/akka/snapshot/java/agents.html), and
34
- [Promises](http://promises-aplus.github.io/promises-spec/). I'm equally fascinated by languages
35
- with strong concurrency support like [Erlang](http://www.erlang.org/doc/getting_started/conc_prog.html),
36
- [Go](http://golang.org/doc/articles/concurrency_patterns.html), and
37
- [Clojure](http://clojure.org/concurrent_programming). My goal is to implement those patterns in Ruby.
38
- Specifically:
39
-
40
- * Stay true to the spirit of the languages providing inspiration
41
- * But implement in a way that makes sense for Ruby
42
- * Keep the semantics as idiomatic Ruby as possible
43
- * Support features that make sense in Ruby
44
- * Exclude features that don't make sense in Ruby
45
- * Keep everything small
46
- * Be as fast as reasonably possible
47
-
48
- ## Features (and Documentation)
49
-
50
- Several features from Erlang, Go, Clojure, Java, and JavaScript have been implemented thus far:
51
-
52
- * Clojure inspired [Agent](https://github.com/jdantonio/concurrent-ruby/blob/master/md/agent.md)
53
- * EventMachine inspired [Defer](https://github.com/jdantonio/concurrent-ruby/blob/master/md/defer.md)
54
- * Clojure inspired [Future](https://github.com/jdantonio/concurrent-ruby/blob/master/md/future.md)
55
- * Go inspired [Goroutine](https://github.com/jdantonio/concurrent-ruby/blob/master/md/goroutine.md)
56
- * JavaScript inspired [Promise](https://github.com/jdantonio/concurrent-ruby/blob/master/md/promise.md)
57
- * Java inspired [Thread Pools](https://github.com/jdantonio/concurrent-ruby/blob/master/md/thread_pool.md)
58
- * Scheduled task execution with the [Executor](https://github.com/jdantonio/concurrent-ruby/blob/master/md/executor.md) service
59
-
60
- ### Is it any good?
61
-
62
- [Yes](http://news.ycombinator.com/item?id=3067434)
63
-
64
- ### Supported Ruby versions
65
-
66
- MRI 1.9.2, 1.9.3, and 2.0. This library is pure Ruby and has minimal gem dependencies. It should be
67
- fully compatible with any Ruby interpreter that is 1.9.x compliant. I simply don't know enough
68
- about JRuby, Rubinius, or the others to fully support them. I can promise good karma and
69
- attribution on this page to anyone wishing to take responsibility for verifying compaitibility
70
- with any Ruby other than MRI.
71
-
72
- ### Install
73
-
74
- ```shell
75
- gem install concurrent-ruby
76
- ```
77
-
78
- or add the following line to Gemfile:
79
-
80
- ```ruby
81
- gem 'concurrent-ruby'
82
- ```
83
-
84
- and run `bundle install` from your shell.
85
-
86
- Once you've installed the gem you must `require` it in your project:
87
-
88
- ```ruby
89
- require 'concurrent'
90
- ```
91
-
92
- ### Kernel Methods
93
-
94
- Many Ruby developers consider it bad form to add function to the global (Kernel) namespace.
95
- I don't necessarily agree. If the function acts like a low-level feature of the language
96
- I think it is OK to add the method to the `Kernel` module. To support my personal programming
97
- style I have chosen to implement `Kernel` methods to instance many of the objects in this
98
- library. Out of respect for the larger Ruby community I have made these methods optional.
99
- They are not imported with the normal `require 'concurrent'` directive. To import these
100
- functions you must import the `concurrent/functions` library.
101
-
102
- ```ruby
103
- require 'concurrent'
104
- score = agent(10) #=> NoMethodError: undefined method `agent' for main:Object
105
-
106
- require 'concurrent/functions'
107
- score = agent(10) #=> #<Concurrent::Agent:0x35b2b28 ...
108
- score.value #=> 10
109
- ```
110
-
111
- ### Examples
112
-
113
- For complete examples, see the specific documentation linked above. Below are a few examples to whet your appetite.
114
-
115
- #### Goroutine (Go)
116
-
117
- ```ruby
118
- require 'concurrent'
119
-
120
- @expected = nil
121
- go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
122
- sleep(0.1)
123
- @expected #=> [3, 2, 1]
124
- ```
125
-
126
- #### Agent (Clojure)
127
-
128
- ```ruby
129
- require 'concurrent'
130
- require 'concurrent/functions'
131
-
132
- score = agent(10)
133
- score.value #=> 10
134
-
135
- score << proc{|current| current + 100 }
136
- sleep(0.1)
137
- score.value #=> 110
138
-
139
- score << proc{|current| current * 2 }
140
- sleep(0.1)
141
- deref score #=> 220
142
-
143
- score << proc{|current| current - 50 }
144
- sleep(0.1)
145
- score.value #=> 170
146
- ```
147
-
148
- #### Defer (EventMachine)
149
-
150
- ```ruby
151
- require 'concurrent'
152
- require 'concurrent/functions'
153
-
154
- Concurrent::Defer.new{ "Jerry D'Antonio" }.
155
- then{|result| puts "Hello, #{result}!" }.
156
- rescue{|ex| puts ex.message }.
157
- go
158
-
159
- #=> Hello, Jerry D'Antonio!
160
-
161
- operation = proc{ raise StandardError.new('Boom!') }
162
- callback = proc{|result| puts result }
163
- errorback = proc{|ex| puts ex.message }
164
- defer(operation, callback, errorback)
165
- sleep(0.1)
166
-
167
- #=> "Boom!"
168
- ```
169
-
170
- #### Future (Clojure)
171
-
172
- ```ruby
173
- require 'concurrent'
174
- require 'concurrent/functions'
175
-
176
- count = future{ sleep(1); 10 }
177
- count.state #=> :pending
178
- # do stuff...
179
- count.value #=> 10 (after blocking)
180
- deref count #=> 10
181
- ```
182
-
183
- #### Promise (JavaScript)
184
-
185
- ```ruby
186
- require 'concurrent'
187
- require 'concurrent/functions'
188
-
189
- p = promise("Jerry", "D'Antonio"){|a, b| "#{a} #{b}" }.
190
- then{|result| "Hello #{result}." }.
191
- rescue(StandardError){|ex| puts "Boom!" }.
192
- then{|result| "#{result} Would you like to play a game?"}
193
- sleep(1)
194
- p.value #=> "Hello Jerry D'Antonio. Would you like to play a game?"
195
- ```
196
-
197
- #### Thread Pools
198
-
199
- ```ruby
200
- require 'concurrent'
201
-
202
- pool = Concurrent::FixedThreadPool.new(10)
203
- @expected = 0
204
- pool.post{ sleep(0.5); @expected += 100 }
205
- pool.post{ sleep(0.5); @expected += 100 }
206
- pool.post{ sleep(0.5); @expected += 100 }
207
- @expected #=> nil
208
- sleep(1)
209
- @expected #=> 300
210
-
211
- pool = Concurrent::CachedThreadPool.new
212
- @expected = 0
213
- pool << proc{ sleep(0.5); @expected += 10 }
214
- pool << proc{ sleep(0.5); @expected += 10 }
215
- pool << proc{ sleep(0.5); @expected += 10 }
216
- @expected #=> 0
217
- sleep(1)
218
- @expected #=> 30
219
- ```
220
-
221
- #### Executor
222
-
223
- ```ruby
224
- require 'concurrent'
225
-
226
- ec = Concurrent::Executor.run('Foo'){ puts 'Boom!' }
227
-
228
- ec.name #=> "Foo"
229
- ec.execution_interval #=> 60 == Concurrent::Executor::EXECUTION_INTERVAL
230
- ec.timeout_interval #=> 30 == Concurrent::Executor::TIMEOUT_INTERVAL
231
- ec.status #=> "sleep"
232
-
233
- # wait 60 seconds...
234
- #=> 'Boom!'
235
- #=> ' INFO (2013-08-02 23:20:15) Foo: execution completed successfully'
236
-
237
- ec.kill #=> true
238
- ```
239
-
240
- ## Contributing
241
-
242
- 1. Fork it
243
- 2. Create your feature branch (`git checkout -b my-new-feature`)
244
- 3. Commit your changes (`git commit -am 'Add some feature'`)
245
- 4. Push to the branch (`git push origin my-new-feature`)
246
- 5. Create new Pull Request
247
-
248
- ## Copyright
249
-
250
- *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
251
- It is free software and may be redistributed under the terms specified in the LICENSE file.
252
-
253
- ## License
254
-
255
- Released under the MIT license.
256
-
257
- http://www.opensource.org/licenses/mit-license.php
258
-
259
- > Permission is hereby granted, free of charge, to any person obtaining a copy
260
- > of this software and associated documentation files (the "Software"), to deal
261
- > in the Software without restriction, including without limitation the rights
262
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
263
- > copies of the Software, and to permit persons to whom the Software is
264
- > furnished to do so, subject to the following conditions:
265
- >
266
- > The above copyright notice and this permission notice shall be included in
267
- > all copies or substantial portions of the Software.
268
- >
269
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
270
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
271
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
272
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
273
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
274
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
275
- > THE SOFTWARE.
1
+ # Concurrent Ruby [![Build Status](https://secure.travis-ci.org/jdantonio/concurrent-ruby.png)](https://travis-ci.org/jdantonio/concurrent-ruby?branch=master) [![Dependency Status](https://gemnasium.com/jdantonio/concurrent-ruby.png)](https://gemnasium.com/jdantonio/concurrent-ruby)
2
+
3
+ Modern concurrency tools including agents, futures, promises, thread pools, reactors, supervisors, and more.
4
+ Inspired by Erlang, Clojure, Go, JavaScript, actors, and classic concurrency patterns.
5
+
6
+ ## Introduction
7
+
8
+ The old-school "lock and synchronize" approach to concurrency is dead. The future of concurrency
9
+ is asynchronous. Send out a bunch of independent [actors](http://en.wikipedia.org/wiki/Actor_model)
10
+ to do your bidding and process the results when you are ready. Although the idea of the concurrent
11
+ actor originated in the early 1970's it has only recently started catching on. Although there is
12
+ no one "true" actor implementation (what *exactly* is "object oriented," what *exactly* is
13
+ "concurrent programming"), many modern programming languages implement variations on the actor
14
+ theme. This library implements a few of the most interesting and useful of those variations.
15
+
16
+ Remember, *there is no silver bullet in concurrent programming.* Concurrency is hard. Very hard.
17
+ These tools will help ease the burden, but at the end of the day it is essential that you
18
+ *know what you are doing.*
19
+
20
+ The project is hosted on the following sites:
21
+
22
+ * [RubyGems project page](https://rubygems.org/gems/concurrent-ruby)
23
+ * [Source code on GitHub](https://github.com/jdantonio/concurrent-ruby)
24
+ * [YARD documentation on RubyDoc.info](http://rubydoc.info/github/jdantonio/concurrent-ruby/frames)
25
+ * [Continuous integration on Travis-CI](https://travis-ci.org/jdantonio/concurrent-ruby)
26
+ * [Dependency tracking on Gemnasium](https://gemnasium.com/jdantonio/concurrent-ruby)
27
+ * [Follow me on Twitter](https://twitter.com/jerrydantonio)
28
+
29
+ ### Goals
30
+
31
+ My history with high-performance, highly-concurrent programming goes back to my days with C/C++.
32
+ I have the same scars as everyone else doing that kind of work with those languages.
33
+ I'm fascinated by modern concurrency patterns like [Actors](http://en.wikipedia.org/wiki/Actor_model),
34
+ [Agents](http://doc.akka.io/docs/akka/snapshot/java/agents.html), and
35
+ [Promises](http://promises-aplus.github.io/promises-spec/). I'm equally fascinated by languages
36
+ with strong concurrency support like [Erlang](http://www.erlang.org/doc/getting_started/conc_prog.html),
37
+ [Go](http://golang.org/doc/articles/concurrency_patterns.html), and
38
+ [Clojure](http://clojure.org/concurrent_programming). My goal is to implement those patterns in Ruby.
39
+ Specifically:
40
+
41
+ * Stay true to the spirit of the languages providing inspiration
42
+ * But implement in a way that makes sense for Ruby
43
+ * Keep the semantics as idiomatic Ruby as possible
44
+ * Support features that make sense in Ruby
45
+ * Exclude features that don't make sense in Ruby
46
+ * Keep everything small
47
+ * Be as fast as reasonably possible
48
+
49
+ ## Features (and Documentation)
50
+
51
+ Several features from Erlang, Go, Clojure, Java, and JavaScript have been implemented thus far:
52
+
53
+ * Clojure inspired [Agent](https://github.com/jdantonio/concurrent-ruby/blob/master/md/agent.md)
54
+ * EventMachine inspired [Defer](https://github.com/jdantonio/concurrent-ruby/blob/master/md/defer.md)
55
+ * Clojure inspired [Future](https://github.com/jdantonio/concurrent-ruby/blob/master/md/future.md)
56
+ * Go inspired [Goroutine](https://github.com/jdantonio/concurrent-ruby/blob/master/md/goroutine.md)
57
+ * JavaScript inspired [Promise](https://github.com/jdantonio/concurrent-ruby/blob/master/md/promise.md)
58
+ * Java inspired [Thread Pools](https://github.com/jdantonio/concurrent-ruby/blob/master/md/thread_pool.md)
59
+ * Scheduled task execution with the [Executor](https://github.com/jdantonio/concurrent-ruby/blob/master/md/executor.md) service
60
+
61
+ ### Is it any good?
62
+
63
+ [Yes](http://news.ycombinator.com/item?id=3067434)
64
+
65
+ ### Supported Ruby versions
66
+
67
+ MRI 1.9.2, 1.9.3, and 2.0. This library is pure Ruby and has minimal gem dependencies. It should be
68
+ fully compatible with any Ruby interpreter that is 1.9.x compliant. I simply don't know enough
69
+ about JRuby, Rubinius, or the others to fully support them. I can promise good karma and
70
+ attribution on this page to anyone wishing to take responsibility for verifying compaitibility
71
+ with any Ruby other than MRI.
72
+
73
+ ### Install
74
+
75
+ ```shell
76
+ gem install concurrent-ruby
77
+ ```
78
+
79
+ or add the following line to Gemfile:
80
+
81
+ ```ruby
82
+ gem 'concurrent-ruby'
83
+ ```
84
+
85
+ and run `bundle install` from your shell.
86
+
87
+ Once you've installed the gem you must `require` it in your project:
88
+
89
+ ```ruby
90
+ require 'concurrent'
91
+ ```
92
+
93
+ ### Kernel Methods
94
+
95
+ Many Ruby developers consider it bad form to add function to the global (Kernel) namespace.
96
+ I don't necessarily agree. If the function acts like a low-level feature of the language
97
+ I think it is OK to add the method to the `Kernel` module. To support my personal programming
98
+ style I have chosen to implement `Kernel` methods to instance many of the objects in this
99
+ library. Out of respect for the larger Ruby community I have made these methods optional.
100
+ They are not imported with the normal `require 'concurrent'` directive. To import these
101
+ functions you must import the `concurrent/functions` library.
102
+
103
+ ```ruby
104
+ require 'concurrent'
105
+ score = agent(10) #=> NoMethodError: undefined method `agent' for main:Object
106
+
107
+ require 'concurrent/functions'
108
+ score = agent(10) #=> #<Concurrent::Agent:0x35b2b28 ...
109
+ score.value #=> 10
110
+ ```
111
+
112
+ ### Examples
113
+
114
+ For complete examples, see the specific documentation linked above. Below are a few examples to whet your appetite.
115
+
116
+ #### Goroutine (Go)
117
+
118
+ ```ruby
119
+ require 'concurrent'
120
+
121
+ @expected = nil
122
+ go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
123
+ sleep(0.1)
124
+ @expected #=> [3, 2, 1]
125
+ ```
126
+
127
+ #### Agent (Clojure)
128
+
129
+ ```ruby
130
+ require 'concurrent'
131
+ require 'concurrent/functions'
132
+
133
+ score = agent(10)
134
+ score.value #=> 10
135
+
136
+ score << proc{|current| current + 100 }
137
+ sleep(0.1)
138
+ score.value #=> 110
139
+
140
+ score << proc{|current| current * 2 }
141
+ sleep(0.1)
142
+ deref score #=> 220
143
+
144
+ score << proc{|current| current - 50 }
145
+ sleep(0.1)
146
+ score.value #=> 170
147
+ ```
148
+
149
+ #### Defer (EventMachine)
150
+
151
+ ```ruby
152
+ require 'concurrent'
153
+ require 'concurrent/functions'
154
+
155
+ Concurrent::Defer.new{ "Jerry D'Antonio" }.
156
+ then{|result| puts "Hello, #{result}!" }.
157
+ rescue{|ex| puts ex.message }.
158
+ go
159
+
160
+ #=> Hello, Jerry D'Antonio!
161
+
162
+ operation = proc{ raise StandardError.new('Boom!') }
163
+ callback = proc{|result| puts result }
164
+ errorback = proc{|ex| puts ex.message }
165
+ defer(operation, callback, errorback)
166
+ sleep(0.1)
167
+
168
+ #=> "Boom!"
169
+ ```
170
+
171
+ #### Future (Clojure)
172
+
173
+ ```ruby
174
+ require 'concurrent'
175
+ require 'concurrent/functions'
176
+
177
+ count = future{ sleep(1); 10 }
178
+ count.state #=> :pending
179
+ # do stuff...
180
+ count.value #=> 10 (after blocking)
181
+ deref count #=> 10
182
+ ```
183
+
184
+ #### Promise (JavaScript)
185
+
186
+ ```ruby
187
+ require 'concurrent'
188
+ require 'concurrent/functions'
189
+
190
+ p = promise("Jerry", "D'Antonio"){|a, b| "#{a} #{b}" }.
191
+ then{|result| "Hello #{result}." }.
192
+ rescue(StandardError){|ex| puts "Boom!" }.
193
+ then{|result| "#{result} Would you like to play a game?"}
194
+ sleep(1)
195
+ p.value #=> "Hello Jerry D'Antonio. Would you like to play a game?"
196
+ ```
197
+
198
+ #### Thread Pools
199
+
200
+ ```ruby
201
+ require 'concurrent'
202
+
203
+ pool = Concurrent::FixedThreadPool.new(10)
204
+ @expected = 0
205
+ pool.post{ sleep(0.5); @expected += 100 }
206
+ pool.post{ sleep(0.5); @expected += 100 }
207
+ pool.post{ sleep(0.5); @expected += 100 }
208
+ @expected #=> nil
209
+ sleep(1)
210
+ @expected #=> 300
211
+
212
+ pool = Concurrent::CachedThreadPool.new
213
+ @expected = 0
214
+ pool << proc{ sleep(0.5); @expected += 10 }
215
+ pool << proc{ sleep(0.5); @expected += 10 }
216
+ pool << proc{ sleep(0.5); @expected += 10 }
217
+ @expected #=> 0
218
+ sleep(1)
219
+ @expected #=> 30
220
+ ```
221
+
222
+ #### Executor
223
+
224
+ ```ruby
225
+ require 'concurrent'
226
+
227
+ ec = Concurrent::Executor.run('Foo'){ puts 'Boom!' }
228
+
229
+ ec.name #=> "Foo"
230
+ ec.execution_interval #=> 60 == Concurrent::Executor::EXECUTION_INTERVAL
231
+ ec.timeout_interval #=> 30 == Concurrent::Executor::TIMEOUT_INTERVAL
232
+ ec.status #=> "sleep"
233
+
234
+ # wait 60 seconds...
235
+ #=> 'Boom!'
236
+ #=> ' INFO (2013-08-02 23:20:15) Foo: execution completed successfully'
237
+
238
+ ec.kill #=> true
239
+ ```
240
+
241
+ ## Contributing
242
+
243
+ 1. Fork it
244
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
245
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
246
+ 4. Push to the branch (`git push origin my-new-feature`)
247
+ 5. Create new Pull Request
248
+
249
+ ## Copyright
250
+
251
+ *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
252
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
253
+
254
+ ## License
255
+
256
+ Released under the MIT license.
257
+
258
+ http://www.opensource.org/licenses/mit-license.php
259
+
260
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
261
+ > of this software and associated documentation files (the "Software"), to deal
262
+ > in the Software without restriction, including without limitation the rights
263
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
264
+ > copies of the Software, and to permit persons to whom the Software is
265
+ > furnished to do so, subject to the following conditions:
266
+ >
267
+ > The above copyright notice and this permission notice shall be included in
268
+ > all copies or substantial portions of the Software.
269
+ >
270
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
271
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
272
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
273
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
274
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
275
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
276
+ > THE SOFTWARE.