concurrent-ruby 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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.