concurrent-ruby 0.1.0 → 0.1.1.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +279 -224
  3. data/lib/concurrent.rb +27 -20
  4. data/lib/concurrent/agent.rb +106 -130
  5. data/lib/concurrent/cached_thread_pool.rb +130 -122
  6. data/lib/concurrent/defer.rb +67 -69
  7. data/lib/concurrent/drb_async_demux.rb +72 -0
  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 +87 -0
  11. data/lib/concurrent/fixed_thread_pool.rb +89 -89
  12. data/lib/concurrent/functions.rb +120 -0
  13. data/lib/concurrent/future.rb +52 -42
  14. data/lib/concurrent/global_thread_pool.rb +3 -3
  15. data/lib/concurrent/goroutine.rb +29 -25
  16. data/lib/concurrent/obligation.rb +67 -121
  17. data/lib/concurrent/promise.rb +172 -194
  18. data/lib/concurrent/reactor.rb +162 -0
  19. data/lib/concurrent/smart_mutex.rb +66 -0
  20. data/lib/concurrent/tcp_sync_demux.rb +96 -0
  21. data/lib/concurrent/thread_pool.rb +65 -61
  22. data/lib/concurrent/utilities.rb +34 -0
  23. data/lib/concurrent/version.rb +3 -3
  24. data/lib/concurrent_ruby.rb +1 -1
  25. data/md/agent.md +123 -123
  26. data/md/defer.md +174 -174
  27. data/md/event.md +32 -32
  28. data/md/executor.md +176 -0
  29. data/md/future.md +83 -83
  30. data/md/goroutine.md +52 -52
  31. data/md/obligation.md +32 -32
  32. data/md/promise.md +225 -225
  33. data/md/thread_pool.md +197 -197
  34. data/spec/concurrent/agent_spec.rb +376 -405
  35. data/spec/concurrent/cached_thread_pool_spec.rb +112 -112
  36. data/spec/concurrent/defer_spec.rb +209 -199
  37. data/spec/concurrent/event_machine_defer_proxy_spec.rb +250 -246
  38. data/spec/concurrent/event_spec.rb +134 -134
  39. data/spec/concurrent/executor_spec.rb +146 -0
  40. data/spec/concurrent/fixed_thread_pool_spec.rb +84 -84
  41. data/spec/concurrent/functions_spec.rb +57 -0
  42. data/spec/concurrent/future_spec.rb +125 -115
  43. data/spec/concurrent/goroutine_spec.rb +67 -52
  44. data/spec/concurrent/obligation_shared.rb +121 -121
  45. data/spec/concurrent/promise_spec.rb +299 -310
  46. data/spec/concurrent/smart_mutex_spec.rb +234 -0
  47. data/spec/concurrent/thread_pool_shared.rb +209 -209
  48. data/spec/concurrent/utilities_spec.rb +74 -0
  49. data/spec/spec_helper.rb +21 -19
  50. metadata +38 -14
  51. checksums.yaml +0 -7
@@ -1,32 +1,32 @@
1
- # Event
2
-
3
- TBD...
4
-
5
- ## Copyright
6
-
7
- *Concurrent Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
8
- It is free software and may be redistributed under the terms specified in the LICENSE file.
9
-
10
- ## License
11
-
12
- Released under the MIT license.
13
-
14
- http://www.opensource.org/licenses/mit-license.php
15
-
16
- > Permission is hereby granted, free of charge, to any person obtaining a copy
17
- > of this software and associated documentation files (the "Software"), to deal
18
- > in the Software without restriction, including without limitation the rights
19
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
- > copies of the Software, and to permit persons to whom the Software is
21
- > furnished to do so, subject to the following conditions:
22
- >
23
- > The above copyright notice and this permission notice shall be included in
24
- > all copies or substantial portions of the Software.
25
- >
26
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
- > THE SOFTWARE.
1
+ # Event
2
+
3
+ TBD...
4
+
5
+ ## Copyright
6
+
7
+ *Concurrent Ruby* is Copyright © 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
8
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
9
+
10
+ ## License
11
+
12
+ Released under the MIT license.
13
+
14
+ http://www.opensource.org/licenses/mit-license.php
15
+
16
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ > of this software and associated documentation files (the "Software"), to deal
18
+ > in the Software without restriction, including without limitation the rights
19
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ > copies of the Software, and to permit persons to whom the Software is
21
+ > furnished to do so, subject to the following conditions:
22
+ >
23
+ > The above copyright notice and this permission notice shall be included in
24
+ > all copies or substantial portions of the Software.
25
+ >
26
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
+ > THE SOFTWARE.
@@ -0,0 +1,176 @@
1
+ # Being of Sound Mind
2
+
3
+ A very common currency pattern is to run a thread that performs a task at regular
4
+ intervals. The thread that peforms the task sleeps for the given interval then
5
+ waked up and performs the task. Later, rinse, repeat... This pattern causes two
6
+ problems. First, it is difficult to test the business logic of the task becuse the
7
+ task itself is tightly couple with the threading. Second, an exception in the task
8
+ can cause the entire thread to abend. In a long-running application where the task
9
+ thread is intended to run for days/weeks/years a crashed task thread can pose a real
10
+ problem. The `Executor` class alleviates both problems.
11
+
12
+ When an executor is launched it starts a thread for monitoring the execution interval.
13
+ The executor thread does not perform the task, however. Instead, the executor
14
+ launches the task on a separat thread. The advantage of this approach is that if
15
+ the task crashes it will only kill the task thread, not the executor thread. The
16
+ executor thread can then log the success or failure of the task. The executor
17
+ can even be configured with a timeout value allowing it to kill a task that runs
18
+ to long and then log the error.
19
+
20
+ One other advantage of the `Executor` class is that it forces the bsiness logic to
21
+ be completely decoupled from the threading logic. The business logic can be tested
22
+ separately then passed to the an executor for scheduling and running.
23
+
24
+ Unlike some of the others concurrency objects in the library, executors do not
25
+ run on the global. In my experience the types of tasks that will benefit from
26
+ the `Executor` class tend to also be long running. For this reason they get their
27
+ own thread every time the task is executed.
28
+
29
+ ## ExecutionContext
30
+
31
+ When an executor is run the return value is an `ExecutionContext` object. An
32
+ `ExecutionContext` object has several attribute readers (`#name`, `#execution_interval`,
33
+ and `#timeout_interval`). It also provides several `Thread` operations which can
34
+ be performed against the internal thread. These include `#status`, `#join`, and
35
+ `kill`.
36
+
37
+ ## Custom Logging
38
+
39
+ An executor will write a log message to standard out at the completion of every
40
+ task run. When the task is successful the log message is tagged at the `:info`
41
+ level. When the task times out the log message is tagged at the `warn` level.
42
+ When the task fails tocomplete (most likely because of exception) the log
43
+ message is tagged at the `error` level.
44
+
45
+ The default logging behavior can be overridden by passing a `proc` to the executor
46
+ on creation. The block will be passes three (3) arguments every time it is run:
47
+ executor `name`, log `level`, and the log `msg` (message). The `proc` can do
48
+ whatever it wanst with these arguments.
49
+
50
+ ## Examples
51
+
52
+ A basic example:
53
+
54
+ ```ruby
55
+ require 'concurrent'
56
+
57
+ ec = Concurrent::Executor.run('Foo'){ puts 'Boom!' }
58
+
59
+ ec.name #=> "Foo"
60
+ ec.execution_interval #=> 60 == Concurrent::Executor::EXECUTION_INTERVAL
61
+ ec.timeout_interval #=> 30 == Concurrent::Executor::TIMEOUT_INTERVAL
62
+ ec.status #=> "sleep"
63
+
64
+ # wait 60 seconds...
65
+ #=> 'Boom!'
66
+ #=> ' INFO (2013-08-02 23:20:15) Foo: execution completed successfully'
67
+
68
+ ec.kill #=> true
69
+ ```
70
+
71
+ Both the execution_interval and the timeout_interval can be configured:
72
+
73
+ ```ruby
74
+ ec = Concurrent::Executor.run('Foo', execution_interval: 5, timeout_interval: 5) do
75
+ puts 'Boom!'
76
+ end
77
+
78
+ ec.execution_interval #=> 5
79
+ ec.timeout_interval #=> 5
80
+ ```
81
+
82
+ A simple example with timeout and task exception:
83
+
84
+ ```ruby
85
+ ec = Concurrent::Executor.run('Foo', execution_interval: 1, timeout_interval: 1){ sleep(10) }
86
+
87
+ #=> WARN (2013-08-02 23:45:26) Foo: execution timed out after 1 seconds
88
+ #=> WARN (2013-08-02 23:45:28) Foo: execution timed out after 1 seconds
89
+ #=> WARN (2013-08-02 23:45:30) Foo: execution timed out after 1 seconds
90
+
91
+ ec = Concurrent::Executor.run('Foo', execution_interval: 1){ raise StandardError }
92
+
93
+ #=> ERROR (2013-08-02 23:47:31) Foo: execution failed with error 'StandardError'
94
+ #=> ERROR (2013-08-02 23:47:32) Foo: execution failed with error 'StandardError'
95
+ #=> ERROR (2013-08-02 23:47:33) Foo: execution failed with error 'StandardError'
96
+ ```
97
+
98
+ For custom logging, simply provide a `proc` when creating an executor:
99
+
100
+ ```ruby
101
+ file_logger = proc do |name, level, msg|
102
+ open('executor.log', 'a') do |f|
103
+ f << ("%5s (%s) %s: %s\n" % [level.upcase, Time.now.strftime("%F %T"), name, msg])
104
+ end
105
+ end
106
+
107
+ ec = Concurrent::Executor.run('Foo', execution_interval: 5, logger: file_logger) do
108
+ puts 'Boom!'
109
+ end
110
+
111
+ # the log file contains
112
+ # INFO (2013-08-02 23:30:19) Foo: execution completed successfully
113
+ # INFO (2013-08-02 23:30:24) Foo: execution completed successfully
114
+ # INFO (2013-08-02 23:30:29) Foo: execution completed successfully
115
+ # INFO (2013-08-02 23:30:34) Foo: execution completed successfully
116
+ # INFO (2013-08-02 23:30:39) Foo: execution completed successfully
117
+ # INFO (2013-08-02 23:30:44) Foo: execution completed successfully
118
+ ```
119
+
120
+ It is also possible to access the default stdout logger from within a logger `proc`:
121
+
122
+ ```ruby
123
+ file_logger = proc do |name, level, msg|
124
+ Concurrent::Executor::STDOUT_LOGGER.call(name, level, msg)
125
+ open('executor.log', 'a') do |f|
126
+ f << ("%5s (%s) %s: %s\n" % [level.upcase, Time.now.strftime("%F %T"), name, msg])
127
+ end
128
+ end
129
+
130
+ ec = Concurrent::Executor.run('Foo', execution_interval: 5, logger: file_logger) do
131
+ puts 'Boom!'
132
+ end
133
+
134
+ # wait...
135
+
136
+ #=> Boom!
137
+ #=> INFO (2013-08-02 23:40:49) Foo: execution completed successfully
138
+ #=> Boom!
139
+ #=> INFO (2013-08-02 23:40:54) Foo: execution completed successfully
140
+ #=> Boom!
141
+ #=> INFO (2013-08-02 23:40:59) Foo: execution completed successfully
142
+
143
+ # and the log file contains
144
+ # INFO (2013-08-02 23:39:52) Foo: execution completed successfully
145
+ # INFO (2013-08-02 23:39:57) Foo: execution completed successfully
146
+ # INFO (2013-08-02 23:40:49) Foo: execution completed successfully
147
+ ```
148
+
149
+ ## Copyright
150
+
151
+ *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
152
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
153
+
154
+ ## License
155
+
156
+ Released under the MIT license.
157
+
158
+ http://www.opensource.org/licenses/mit-license.php
159
+
160
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
161
+ > of this software and associated documentation files (the "Software"), to deal
162
+ > in the Software without restriction, including without limitation the rights
163
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
164
+ > copies of the Software, and to permit persons to whom the Software is
165
+ > furnished to do so, subject to the following conditions:
166
+ >
167
+ > The above copyright notice and this permission notice shall be included in
168
+ > all copies or substantial portions of the Software.
169
+ >
170
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
172
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
173
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
174
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
175
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
176
+ > THE SOFTWARE.
@@ -1,83 +1,83 @@
1
- # We're Sending You Back to the Future!
2
-
3
- Futures are inspired by [Clojure's](http://clojure.org/) [future](http://clojuredocs.org/clojure_core/clojure.core/future) keyword.
4
- A future represents a promise to complete an action at some time in the future. The action is atomic and permanent.
5
- The idea behind a future is to send an action off for asynchronous operation, do other stuff, then return and
6
- retrieve the result of the async operation at a later time. Futures run on the global thread pool (see below).
7
-
8
- Futures have three possible states: *pending*, *rejected*, and *fulfilled*. When a future is created it is set
9
- to *pending* and will remain in that state until processing is complete. A completed future is either *rejected*,
10
- indicating that an exception was thrown during processing, or *fulfilled*, indicating succedd. If a future is
11
- *fulfilled* its `value` will be updated to reflect the result of the operation. If *rejected* the `reason` will
12
- be updated with a reference to the thrown exception. The predicate methods `pending?`, `rejected`, and `fulfilled?`
13
- can be called at any time to obtain the state of the future, as can the `state` method, which returns a symbol.
14
-
15
- Retrieving the value of a future is done through the `value` (alias: `deref`) method. Obtaining the value of
16
- a future is a potentially blocking operation. When a future is *rejected* a call to `value` will return `nil`
17
- immediately. When a future is *fulfilled* a call to `value` will immediately return the current value.
18
- When a future is *pending* a call to `value` will block until the future is either *rejected* or *fulfilled*.
19
- A *timeout* value can be passed to `value` to limit how long the call will block. If `nil` the call will
20
- block indefinitely. If `0` the call will not block. Any other integer or float value will indicate the
21
- maximum number of seconds to block.
22
-
23
- ## Examples
24
-
25
- A fulfilled example:
26
-
27
- ```ruby
28
- require 'concurrent'
29
-
30
- count = Concurrent::Future{ sleep(10); 10 }
31
- count.state #=> :pending
32
- count.pending? #=> true
33
-
34
- # do stuff...
35
-
36
- count.value(0) #=> nil (does not block)
37
-
38
- count.value #=> 10 (after blocking)
39
- count.state #=> :fulfilled
40
- count.fulfilled? #=> true
41
- deref count #=> 10
42
- ```
43
-
44
- A rejected example:
45
-
46
- ```ruby
47
- count = future{ sleep(10); raise StandardError.new("Boom!") }
48
- count.state #=> :pending
49
- pending?(count) #=> true
50
-
51
- deref(count) #=> nil (after blocking)
52
- rejected?(count) #=> true
53
- count.reason #=> #<StandardError: Boom!>
54
- ```
55
-
56
- ## Copyright
57
-
58
- *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
59
- It is free software and may be redistributed under the terms specified in the LICENSE file.
60
-
61
- ## License
62
-
63
- Released under the MIT license.
64
-
65
- http://www.opensource.org/licenses/mit-license.php
66
-
67
- > Permission is hereby granted, free of charge, to any person obtaining a copy
68
- > of this software and associated documentation files (the "Software"), to deal
69
- > in the Software without restriction, including without limitation the rights
70
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71
- > copies of the Software, and to permit persons to whom the Software is
72
- > furnished to do so, subject to the following conditions:
73
- >
74
- > The above copyright notice and this permission notice shall be included in
75
- > all copies or substantial portions of the Software.
76
- >
77
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
83
- > THE SOFTWARE.
1
+ # We're Sending You Back to the Future!
2
+
3
+ Futures are inspired by [Clojure's](http://clojure.org/) [future](http://clojuredocs.org/clojure_core/clojure.core/future) keyword.
4
+ A future represents a promise to complete an action at some time in the future. The action is atomic and permanent.
5
+ The idea behind a future is to send an action off for asynchronous operation, do other stuff, then return and
6
+ retrieve the result of the async operation at a later time. Futures run on the global thread pool (see below).
7
+
8
+ Futures have three possible states: *pending*, *rejected*, and *fulfilled*. When a future is created it is set
9
+ to *pending* and will remain in that state until processing is complete. A completed future is either *rejected*,
10
+ indicating that an exception was thrown during processing, or *fulfilled*, indicating succedd. If a future is
11
+ *fulfilled* its `value` will be updated to reflect the result of the operation. If *rejected* the `reason` will
12
+ be updated with a reference to the thrown exception. The predicate methods `pending?`, `rejected`, and `fulfilled?`
13
+ can be called at any time to obtain the state of the future, as can the `state` method, which returns a symbol.
14
+
15
+ Retrieving the value of a future is done through the `value` (alias: `deref`) method. Obtaining the value of
16
+ a future is a potentially blocking operation. When a future is *rejected* a call to `value` will return `nil`
17
+ immediately. When a future is *fulfilled* a call to `value` will immediately return the current value.
18
+ When a future is *pending* a call to `value` will block until the future is either *rejected* or *fulfilled*.
19
+ A *timeout* value can be passed to `value` to limit how long the call will block. If `nil` the call will
20
+ block indefinitely. If `0` the call will not block. Any other integer or float value will indicate the
21
+ maximum number of seconds to block.
22
+
23
+ ## Examples
24
+
25
+ A fulfilled example:
26
+
27
+ ```ruby
28
+ require 'concurrent'
29
+
30
+ count = Concurrent::Future{ sleep(10); 10 }
31
+ count.state #=> :pending
32
+ count.pending? #=> true
33
+
34
+ # do stuff...
35
+
36
+ count.value(0) #=> nil (does not block)
37
+
38
+ count.value #=> 10 (after blocking)
39
+ count.state #=> :fulfilled
40
+ count.fulfilled? #=> true
41
+ deref count #=> 10
42
+ ```
43
+
44
+ A rejected example:
45
+
46
+ ```ruby
47
+ count = future{ sleep(10); raise StandardError.new("Boom!") }
48
+ count.state #=> :pending
49
+ pending?(count) #=> true
50
+
51
+ deref(count) #=> nil (after blocking)
52
+ rejected?(count) #=> true
53
+ count.reason #=> #<StandardError: Boom!>
54
+ ```
55
+
56
+ ## Copyright
57
+
58
+ *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
59
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
60
+
61
+ ## License
62
+
63
+ Released under the MIT license.
64
+
65
+ http://www.opensource.org/licenses/mit-license.php
66
+
67
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
68
+ > of this software and associated documentation files (the "Software"), to deal
69
+ > in the Software without restriction, including without limitation the rights
70
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71
+ > copies of the Software, and to permit persons to whom the Software is
72
+ > furnished to do so, subject to the following conditions:
73
+ >
74
+ > The above copyright notice and this permission notice shall be included in
75
+ > all copies or substantial portions of the Software.
76
+ >
77
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
82
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
83
+ > THE SOFTWARE.
@@ -1,52 +1,52 @@
1
- # Go, Go, Gadget Goroutine!
2
-
3
- A goroutine is the simplest of the concurrency utilities in this library. It is inspired by
4
- [Go's](http://golang.org/) [goroutines](https://gobyexample.com/goroutines) and
5
- [Erlang's](http://www.erlang.org/) [spawn](http://erlangexamples.com/tag/spawn/) keyword. The
6
- `go` function is nothing more than a simple way to send a block to the global thread pool (see below)
7
- for processing.
8
-
9
- ## Examples
10
-
11
- ```ruby
12
- require 'concurrent'
13
-
14
- @expected = nil
15
-
16
- go(1, 2, 3){|a, b, c| sleep(1); @expected = [c, b, a] }
17
-
18
- sleep(0.1)
19
- @expected #=> nil
20
-
21
- sleep(2)
22
- @expected #=> [3, 2, 1]
23
- ```
24
-
25
- ## Copyright
26
-
27
- *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
28
- It is free software and may be redistributed under the terms specified in the LICENSE file.
29
-
30
- ## License
31
-
32
- Released under the MIT license.
33
-
34
- http://www.opensource.org/licenses/mit-license.php
35
-
36
- > Permission is hereby granted, free of charge, to any person obtaining a copy
37
- > of this software and associated documentation files (the "Software"), to deal
38
- > in the Software without restriction, including without limitation the rights
39
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
- > copies of the Software, and to permit persons to whom the Software is
41
- > furnished to do so, subject to the following conditions:
42
- >
43
- > The above copyright notice and this permission notice shall be included in
44
- > all copies or substantial portions of the Software.
45
- >
46
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52
- > THE SOFTWARE.
1
+ # Go, Go, Gadget Goroutine!
2
+
3
+ A goroutine is the simplest of the concurrency utilities in this library. It is inspired by
4
+ [Go's](http://golang.org/) [goroutines](https://gobyexample.com/goroutines) and
5
+ [Erlang's](http://www.erlang.org/) [spawn](http://erlangexamples.com/tag/spawn/) keyword. The
6
+ `go` function is nothing more than a simple way to send a block to the global thread pool (see below)
7
+ for processing.
8
+
9
+ ## Examples
10
+
11
+ ```ruby
12
+ require 'concurrent'
13
+
14
+ @expected = nil
15
+
16
+ go(1, 2, 3){|a, b, c| sleep(1); @expected = [c, b, a] }
17
+
18
+ sleep(0.1)
19
+ @expected #=> nil
20
+
21
+ sleep(2)
22
+ @expected #=> [3, 2, 1]
23
+ ```
24
+
25
+ ## Copyright
26
+
27
+ *Concurrent Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
28
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
29
+
30
+ ## License
31
+
32
+ Released under the MIT license.
33
+
34
+ http://www.opensource.org/licenses/mit-license.php
35
+
36
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ > of this software and associated documentation files (the "Software"), to deal
38
+ > in the Software without restriction, including without limitation the rights
39
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
+ > copies of the Software, and to permit persons to whom the Software is
41
+ > furnished to do so, subject to the following conditions:
42
+ >
43
+ > The above copyright notice and this permission notice shall be included in
44
+ > all copies or substantial portions of the Software.
45
+ >
46
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52
+ > THE SOFTWARE.