concurrent-ruby-edge 0.1.0.pre2
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +284 -0
- data/lib/concurrent-edge.rb +11 -0
- data/lib/concurrent/actor.rb +98 -0
- data/lib/concurrent/actor/behaviour.rb +143 -0
- data/lib/concurrent/actor/behaviour/abstract.rb +51 -0
- data/lib/concurrent/actor/behaviour/awaits.rb +21 -0
- data/lib/concurrent/actor/behaviour/buffer.rb +56 -0
- data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +12 -0
- data/lib/concurrent/actor/behaviour/executes_context.rb +17 -0
- data/lib/concurrent/actor/behaviour/linking.rb +83 -0
- data/lib/concurrent/actor/behaviour/pausing.rb +123 -0
- data/lib/concurrent/actor/behaviour/removes_child.rb +16 -0
- data/lib/concurrent/actor/behaviour/sets_results.rb +37 -0
- data/lib/concurrent/actor/behaviour/supervising.rb +39 -0
- data/lib/concurrent/actor/behaviour/terminates_children.rb +14 -0
- data/lib/concurrent/actor/behaviour/termination.rb +74 -0
- data/lib/concurrent/actor/context.rb +167 -0
- data/lib/concurrent/actor/core.rb +220 -0
- data/lib/concurrent/actor/default_dead_letter_handler.rb +9 -0
- data/lib/concurrent/actor/envelope.rb +41 -0
- data/lib/concurrent/actor/errors.rb +27 -0
- data/lib/concurrent/actor/internal_delegations.rb +59 -0
- data/lib/concurrent/actor/public_delegations.rb +40 -0
- data/lib/concurrent/actor/reference.rb +106 -0
- data/lib/concurrent/actor/root.rb +37 -0
- data/lib/concurrent/actor/type_check.rb +48 -0
- data/lib/concurrent/actor/utils.rb +10 -0
- data/lib/concurrent/actor/utils/ad_hoc.rb +27 -0
- data/lib/concurrent/actor/utils/balancer.rb +43 -0
- data/lib/concurrent/actor/utils/broadcast.rb +52 -0
- data/lib/concurrent/actor/utils/pool.rb +54 -0
- data/lib/concurrent/agent.rb +289 -0
- data/lib/concurrent/channel.rb +6 -0
- data/lib/concurrent/channel/blocking_ring_buffer.rb +82 -0
- data/lib/concurrent/channel/buffered_channel.rb +87 -0
- data/lib/concurrent/channel/channel.rb +19 -0
- data/lib/concurrent/channel/ring_buffer.rb +65 -0
- data/lib/concurrent/channel/unbuffered_channel.rb +39 -0
- data/lib/concurrent/channel/waitable_list.rb +48 -0
- data/lib/concurrent/edge/atomic_markable_reference.rb +184 -0
- data/lib/concurrent/edge/future.rb +1226 -0
- data/lib/concurrent/edge/lock_free_stack.rb +85 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 21429b1dcafe35b79201be08fd02442171fc68fb
|
4
|
+
data.tar.gz: 2de92c445f74fbf670cb605e760b9a4c413597c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cb45d38d9f966ff005121fec47adc053349675ee7d018662e7b49c67a67fdd3c3bb603cca559d3b39c4243f62ff099905c72b320b2ada6b29d8d5fc00541df49
|
7
|
+
data.tar.gz: 2e1c9c51ec89bb08e32ced3883cf5fa8cf472bdf0a98616af1966e7929c2c018ee832b747262fff13831295aa381c67cf883f207f60c9dfa29355c504803563d
|
data/LICENSE.txt
ADDED
@@ -0,0 +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.
|
data/README.md
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
# Concurrent Ruby
|
2
|
+
[](http://badge.fury.io/rb/concurrent-ruby) [](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [](http://opensource.org/licenses/MIT) [](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
3
|
+
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<td align="left" valign="top">
|
7
|
+
<p>
|
8
|
+
Modern concurrency tools for Ruby. Inspired by
|
9
|
+
<a href="http://www.erlang.org/doc/reference_manual/processes.html">Erlang</a>,
|
10
|
+
<a href="http://clojure.org/concurrent_programming">Clojure</a>,
|
11
|
+
<a href="http://akka.io/">Scala</a>,
|
12
|
+
<a href="http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell">Haskell</a>,
|
13
|
+
<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>,
|
14
|
+
<a href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">C#</a>,
|
15
|
+
<a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html">Java</a>,
|
16
|
+
and classic concurrency patterns.
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
The design goals of this gem are:
|
20
|
+
<ul>
|
21
|
+
<li>Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why</li>
|
22
|
+
<li>Remain free of external gem dependencies</li>
|
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/ruby-concurrency/concurrent-ruby/master/doc/logo/concurrent-ruby-logo-300x300.png"/>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
</table>
|
37
|
+
|
38
|
+
### Supported Ruby versions
|
39
|
+
|
40
|
+
MRI 1.9.3, 2.0, 2.1, 2.2, JRuby (1.9 mode), and Rubinius 2.x are supported.
|
41
|
+
This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
|
42
|
+
|
43
|
+
## Features & Documentation
|
44
|
+
|
45
|
+
We have a roadmap guiding our work toward the [v1.0.0 release](https://github.com/ruby-concurrency/concurrent-ruby/wiki/v1.0-Roadmap).
|
46
|
+
|
47
|
+
The primary site for documentation is the automatically generated [API documentation](http://ruby-concurrency.github.io/concurrent-ruby/frames.html)
|
48
|
+
|
49
|
+
We also have a [mailing list](http://groups.google.com/group/concurrent-ruby).
|
50
|
+
|
51
|
+
This library contains a variety of concurrency abstractions at high and low levels. One of the high-level abstractions is likely to meet most common needs.
|
52
|
+
|
53
|
+
#### General-purpose Concurrency Abstractions
|
54
|
+
|
55
|
+
* [Async](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Async.html): A mixin module that provides simple asynchronous behavior to any standard class/object or object.
|
56
|
+
* [Atom](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Atom.html): A way to manage shared, synchronous, independent state.
|
57
|
+
* [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
|
58
|
+
* [Dataflow](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent.html#dataflow-class_method): Built on Futures, Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
|
59
|
+
* [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
|
60
|
+
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
|
61
|
+
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
|
62
|
+
|
63
|
+
#### Thread-safe Value Objects
|
64
|
+
|
65
|
+
* `Maybe` A thread-safe, immutable object representing an optional value, based on
|
66
|
+
[Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
|
67
|
+
* `Delay` Lazy evaluation of a block yielding an immutable result. Based on Clojure's
|
68
|
+
[delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html).
|
69
|
+
|
70
|
+
#### Thread-safe Structures
|
71
|
+
|
72
|
+
Derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
|
73
|
+
|
74
|
+
* `ImmutableStruct` Immutable struct where values are set at construction and cannot be changed later.
|
75
|
+
* `MutableStruct` Synchronized, mutable struct where values can be safely changed at any time.
|
76
|
+
* `SettableStruct` Synchronized, write-once struct where values can be set at most once, either at construction or any time thereafter.
|
77
|
+
|
78
|
+
#### Java-inspired ThreadPools and Other Executors
|
79
|
+
|
80
|
+
* See [ThreadPool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
|
81
|
+
|
82
|
+
#### Thread Synchronization Classes and Algorithms
|
83
|
+
|
84
|
+
* [CountdownLatch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html)
|
85
|
+
* [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html)
|
86
|
+
* [Event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html)
|
87
|
+
* [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html)
|
88
|
+
|
89
|
+
#### Thread-safe Variables
|
90
|
+
|
91
|
+
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html)
|
92
|
+
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html)
|
93
|
+
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html)
|
94
|
+
* [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
|
95
|
+
* [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
|
96
|
+
* [Thread-local variables](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html)
|
97
|
+
* [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar)
|
98
|
+
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html)
|
99
|
+
|
100
|
+
### Edge Features
|
101
|
+
|
102
|
+
These are available in the `concurrent-ruby-edge` companion gem, installed with `gem install concurrent-ruby-edge`.
|
103
|
+
|
104
|
+
These features are under active development and may change frequently. They are expected not to
|
105
|
+
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|
106
|
+
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.
|
107
|
+
|
108
|
+
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html):
|
109
|
+
Implements the Actor Model, where concurrent actors exchange messages.
|
110
|
+
* [new Future Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge.html) - new
|
111
|
+
unified implementation of Futures and Promises which combines Features of previous `Future`,
|
112
|
+
`Promise`, `IVar`, `Event`, `Probe`, `dataflow`, `Delay`, `TimerTask` into single framework. It uses extensively
|
113
|
+
new synchronization layer to make all the paths **lock-free** with exception of blocking threads on `#wait`.
|
114
|
+
It offers better performance and does not block threads when not required.
|
115
|
+
* [Agent](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Agent.html): A single atomic value that represents an identity.
|
116
|
+
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html):
|
117
|
+
Communicating Sequential Processes (CSP).
|
118
|
+
* [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
|
119
|
+
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
|
120
|
+
* [New Future Promise Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge.html) - new
|
121
|
+
unified implementation of Futures and Promises which combines Features of previous `Future`,
|
122
|
+
`Promise`, `IVar`, `Probe`, `dataflow`, `Delay`, `TimerTask` into single framework. It uses extensively
|
123
|
+
new synchronization layer to make all the paths lock-free with exception of blocking threads on `#wait`.
|
124
|
+
It offers better performance and does not block threads (exception being `#wait` and similar methods where it's
|
125
|
+
intended).
|
126
|
+
|
127
|
+
|
128
|
+
#### Statuses:
|
129
|
+
|
130
|
+
*Why is not in core?*
|
131
|
+
|
132
|
+
- **Actor** - partial documentation and tests, stability good.
|
133
|
+
- **Future/Promise Framework** - partial documentation and tests, stability good.
|
134
|
+
- **Agent** - incomplete behaviour compared to Clojure's model, stability good.
|
135
|
+
- **Channel** - missing documentation, stability good.
|
136
|
+
- **Exchanger** - known race issue.
|
137
|
+
- **LazyRegister** - missing documentation and tests.
|
138
|
+
|
139
|
+
## Usage
|
140
|
+
|
141
|
+
All abstractions within this gem can be loaded simply by requiring it:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
require 'concurrent'
|
145
|
+
```
|
146
|
+
|
147
|
+
To reduce the amount of code loaded at runtime, subsets of this gem can be required:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
require 'concurrent' # everything
|
151
|
+
|
152
|
+
# groups
|
153
|
+
|
154
|
+
require 'concurrent/atomics' # atomic and thread synchronization classes
|
155
|
+
require 'concurrent/executors' # Thread pools and other executors
|
156
|
+
|
157
|
+
# individual abstractions
|
158
|
+
|
159
|
+
require 'concurrent/async' # Concurrent::Async
|
160
|
+
require 'concurrent/atom' # Concurrent::Atom
|
161
|
+
require 'concurrent/dataflow' # Concurrent::dataflow
|
162
|
+
require 'concurrent/delay' # Concurrent::Delay
|
163
|
+
require 'concurrent/future' # Concurrent::Future
|
164
|
+
require 'concurrent/immutable_struct' # Concurrent::ImmutableStruct
|
165
|
+
require 'concurrent/ivar' # Concurrent::IVar
|
166
|
+
require 'concurrent/maybe' # Concurrent::Maybe
|
167
|
+
require 'concurrent/mutable_struct' # Concurrent::MutableStruct
|
168
|
+
require 'concurrent/mvar' # Concurrent::MVar
|
169
|
+
require 'concurrent/promise' # Concurrent::Promise
|
170
|
+
require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
|
171
|
+
require 'concurrent/settable_struct' # Concurrent::SettableStruct
|
172
|
+
require 'concurrent/timer_task' # Concurrent::TimerTask
|
173
|
+
require 'concurrent/tvar' # Concurrent::TVar
|
174
|
+
|
175
|
+
# experimental - available in `concurrent-ruby-edge` companion gem
|
176
|
+
|
177
|
+
require 'concurrent/actor' # Concurrent::Actor and supporting code
|
178
|
+
require 'concurrent/edge/future' # new Future Framework
|
179
|
+
require 'concurrent/agent' # Concurrent::Agent
|
180
|
+
require 'concurrent/channel ' # Concurrent::Channel and supporting code
|
181
|
+
require 'concurrent/exchanger' # Concurrent::Exchanger
|
182
|
+
require 'concurrent/lazy_register' # Concurrent::LazyRegister
|
183
|
+
```
|
184
|
+
|
185
|
+
If the library does not behave as expected, `Concurrent.use_stdlib_logger(Logger::DEBUG)` could help to reveal the problem.
|
186
|
+
|
187
|
+
## Installation
|
188
|
+
|
189
|
+
```shell
|
190
|
+
gem install concurrent-ruby
|
191
|
+
```
|
192
|
+
|
193
|
+
or add the following line to Gemfile:
|
194
|
+
|
195
|
+
```ruby
|
196
|
+
gem 'concurrent-ruby'
|
197
|
+
```
|
198
|
+
|
199
|
+
and run `bundle install` from your shell.
|
200
|
+
|
201
|
+
### C Extensions for MRI
|
202
|
+
|
203
|
+
Potential performance improvements may be achieved under MRI by installing optional C extensions.
|
204
|
+
To minimize installation errors the C extensions are available in the `concurrent-ruby-ext` extension
|
205
|
+
gem. `concurrent-ruby` and `concurrent-ruby-ext` are always released together with same version.
|
206
|
+
Simply install the extension gem too:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
gem install concurrent-ruby-ext
|
210
|
+
```
|
211
|
+
|
212
|
+
or add the following line to Gemfile:
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
gem 'concurrent-ruby-ext'
|
216
|
+
```
|
217
|
+
|
218
|
+
and run `bundle install` from your shell.
|
219
|
+
|
220
|
+
In code it is only necessary to
|
221
|
+
|
222
|
+
```ruby
|
223
|
+
require 'concurrent'
|
224
|
+
```
|
225
|
+
|
226
|
+
The `concurrent-ruby` gem will automatically detect the presence of the `concurrent-ruby-ext` gem
|
227
|
+
and load the appropriate C extensions.
|
228
|
+
|
229
|
+
#### Note For gem developers
|
230
|
+
|
231
|
+
No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users.
|
232
|
+
The best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
|
233
|
+
|
234
|
+
### Building
|
235
|
+
|
236
|
+
All published versions of this gem (core, extension, and several platform-specific packages) are compiled,
|
237
|
+
packaged, tested, and published using an open, [automated process](https://github.com/ruby-concurrency/rake-compiler-dev-box).
|
238
|
+
This process can also be used to create pre-compiled binaries of the extension gem for virtally
|
239
|
+
any platform. *Documentation is forthcoming...*
|
240
|
+
|
241
|
+
```
|
242
|
+
*MRI only*
|
243
|
+
bundle exec rake build:native # Build concurrent-ruby-ext-<version>-<platform>.gem into the pkg dir
|
244
|
+
bundle exec rake compile:extension # Compile extension
|
245
|
+
|
246
|
+
*JRuby only*
|
247
|
+
bundle exec rake build # Build JRuby-specific core gem (alias for `build:core`)
|
248
|
+
bundle exec rake build:core # Build concurrent-ruby-<version>-java.gem into the pkg directory
|
249
|
+
|
250
|
+
*All except JRuby*
|
251
|
+
bundle exec rake build # Build core and extension gems
|
252
|
+
bundle exec rake build:core # Build concurrent-ruby-<version>.gem into the pkg directory
|
253
|
+
bundle exec rake build:ext # Build concurrent-ruby-ext-<version>.gem into the pkg directory
|
254
|
+
|
255
|
+
*All*
|
256
|
+
bundle exec rake clean # Remove any temporary products
|
257
|
+
bundle exec rake clobber # Remove any generated file
|
258
|
+
bundle exec rake compile # Compile all the extensions
|
259
|
+
```
|
260
|
+
|
261
|
+
## Maintainers
|
262
|
+
|
263
|
+
* [Jerry D'Antonio](https://github.com/jdantonio)
|
264
|
+
* [Michele Della Torre](https://github.com/mighe)
|
265
|
+
* [Chris Seaton](https://github.com/chrisseaton)
|
266
|
+
* [Lucas Allan](https://github.com/lucasallan)
|
267
|
+
* [Petr Chalupa](https://github.com/pitr-ch)
|
268
|
+
* [Paweł Obrok](https://github.com/obrok)
|
269
|
+
|
270
|
+
## Contributing
|
271
|
+
|
272
|
+
1. Fork it
|
273
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
274
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
275
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
276
|
+
5. Create new Pull Request
|
277
|
+
|
278
|
+
## License and Copyright
|
279
|
+
|
280
|
+
*Concurrent Ruby* is free software released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
281
|
+
|
282
|
+
The *Concurrent Ruby* [logo](https://github.com/ruby-concurrency/concurrent-ruby/wiki/Logo)
|
283
|
+
was designed by [David Jones](https://twitter.com/zombyboy).
|
284
|
+
It is Copyright © 2014 [Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
require 'concurrent/actor'
|
4
|
+
require 'concurrent/agent'
|
5
|
+
require 'concurrent/channel'
|
6
|
+
require 'concurrent/exchanger'
|
7
|
+
require 'concurrent/lazy_register'
|
8
|
+
|
9
|
+
require 'concurrent/edge/future'
|
10
|
+
require 'concurrent/edge/lock_free_stack'
|
11
|
+
require 'concurrent/edge/atomic_markable_reference'
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'concurrent/configuration'
|
2
|
+
require 'concurrent/executor/serialized_execution'
|
3
|
+
require 'concurrent/synchronization'
|
4
|
+
require 'concurrent/edge/future'
|
5
|
+
|
6
|
+
module Concurrent
|
7
|
+
# TODO https://github.com/celluloid/celluloid/wiki/Supervision-Groups ?
|
8
|
+
# TODO Remote actors using DRb
|
9
|
+
# TODO un/become
|
10
|
+
# TODO supervision tree, pause children on error in parent, pause may need higher priority
|
11
|
+
# TODO more effective executor
|
12
|
+
|
13
|
+
# {include:file:doc/actor/main.md}
|
14
|
+
# @api Actor
|
15
|
+
# @!macro edge_warning
|
16
|
+
module Actor
|
17
|
+
|
18
|
+
require 'concurrent/actor/type_check'
|
19
|
+
require 'concurrent/actor/errors'
|
20
|
+
require 'concurrent/actor/public_delegations'
|
21
|
+
require 'concurrent/actor/internal_delegations'
|
22
|
+
require 'concurrent/actor/envelope'
|
23
|
+
require 'concurrent/actor/reference'
|
24
|
+
require 'concurrent/actor/core'
|
25
|
+
require 'concurrent/actor/behaviour'
|
26
|
+
require 'concurrent/actor/context'
|
27
|
+
|
28
|
+
require 'concurrent/actor/default_dead_letter_handler'
|
29
|
+
require 'concurrent/actor/root'
|
30
|
+
require 'concurrent/actor/utils'
|
31
|
+
|
32
|
+
# @return [Reference, nil] current executing actor if any
|
33
|
+
def self.current
|
34
|
+
Thread.current[:__current_actor__]
|
35
|
+
end
|
36
|
+
|
37
|
+
@root = Concurrent.delay do
|
38
|
+
Core.new(parent: nil, name: '/', class: Root, initialized: future = Concurrent.future).reference.tap do
|
39
|
+
future.wait!
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# A root actor, a default parent of all actors spawned outside an actor
|
44
|
+
def self.root
|
45
|
+
@root.value!
|
46
|
+
end
|
47
|
+
|
48
|
+
# Spawns a new actor. {Concurrent::Actor::AbstractContext.spawn} allows to omit class parameter.
|
49
|
+
# To see the list of avaliable options see {Core#initialize}
|
50
|
+
# @see Concurrent::Actor::AbstractContext.spawn
|
51
|
+
# @see Core#initialize
|
52
|
+
# @example by class and name
|
53
|
+
# Actor.spawn(AdHoc, :ping1) { -> message { message } }
|
54
|
+
#
|
55
|
+
# @example by option hash
|
56
|
+
# inc2 = Actor.spawn(class: AdHoc,
|
57
|
+
# name: 'increment by 2',
|
58
|
+
# args: [2],
|
59
|
+
# executor: Concurrent.global_io_executor) do |increment_by|
|
60
|
+
# lambda { |number| number + increment_by }
|
61
|
+
# end
|
62
|
+
# inc2.ask!(2) # => 4
|
63
|
+
#
|
64
|
+
# @param block for context_class instantiation
|
65
|
+
# @param args see {.to_spawn_options}
|
66
|
+
# @return [Reference] never the actual actor
|
67
|
+
def self.spawn(*args, &block)
|
68
|
+
if Actor.current
|
69
|
+
Core.new(to_spawn_options(*args).merge(parent: Actor.current), &block).reference
|
70
|
+
else
|
71
|
+
root.ask([:spawn, to_spawn_options(*args), block]).value!
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# as {.spawn} but it'll block until actor is initialized or it'll raise exception on error
|
76
|
+
def self.spawn!(*args, &block)
|
77
|
+
spawn(to_spawn_options(*args).merge(initialized: future = Concurrent.future), &block).tap { future.wait! }
|
78
|
+
end
|
79
|
+
|
80
|
+
# @overload to_spawn_options(context_class, name, *args)
|
81
|
+
# @param [AbstractContext] context_class to be spawned
|
82
|
+
# @param [String, Symbol] name of the instance, it's used to generate the
|
83
|
+
# {Core#path} of the actor
|
84
|
+
# @param args for context_class instantiation
|
85
|
+
# @overload to_spawn_options(opts)
|
86
|
+
# see {Core#initialize} opts
|
87
|
+
def self.to_spawn_options(*args)
|
88
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
89
|
+
args.first
|
90
|
+
else
|
91
|
+
{ class: args[0],
|
92
|
+
name: args[1],
|
93
|
+
args: args[2..-1] }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Concurrent
|
2
|
+
module Actor
|
3
|
+
|
4
|
+
# Actors have modular architecture, which is achieved by combining a light core with chain of
|
5
|
+
# behaviours. Each message or internal event propagates through the chain allowing the
|
6
|
+
# behaviours react based on their responsibility.
|
7
|
+
#
|
8
|
+
# - {Behaviour::Linking}:
|
9
|
+
#
|
10
|
+
# > {include:Actor::Behaviour::Linking}
|
11
|
+
#
|
12
|
+
# - {Behaviour::Awaits}:
|
13
|
+
#
|
14
|
+
# > {include:Actor::Behaviour::Awaits}
|
15
|
+
#
|
16
|
+
# - {Behaviour::Pausing}:
|
17
|
+
#
|
18
|
+
# > {include:Actor::Behaviour::Pausing}
|
19
|
+
#
|
20
|
+
# - {Behaviour::Supervising}:
|
21
|
+
#
|
22
|
+
# > {include:Actor::Behaviour::Supervising}
|
23
|
+
#
|
24
|
+
# - {Behaviour::Supervising}:
|
25
|
+
#
|
26
|
+
# > {include:Actor::Behaviour::Supervising}
|
27
|
+
#
|
28
|
+
# - {Behaviour::ExecutesContext}:
|
29
|
+
#
|
30
|
+
# > {include:Actor::Behaviour::ExecutesContext}
|
31
|
+
#
|
32
|
+
# - {Behaviour::ErrorsOnUnknownMessage}:
|
33
|
+
#
|
34
|
+
# > {include:Actor::Behaviour::ErrorsOnUnknownMessage}
|
35
|
+
#
|
36
|
+
# - {Behaviour::Termination}:
|
37
|
+
#
|
38
|
+
# > {include:Actor::Behaviour::Termination}
|
39
|
+
#
|
40
|
+
# - {Behaviour::TerminatesChildren}:
|
41
|
+
#
|
42
|
+
# > {include:Actor::Behaviour::TerminatesChildren}
|
43
|
+
#
|
44
|
+
# - {Behaviour::RemovesChild}:
|
45
|
+
#
|
46
|
+
# > {include:Actor::Behaviour::RemovesChild}
|
47
|
+
#
|
48
|
+
# If needed new behaviours can be added, or old one removed to get required behaviour.
|
49
|
+
#
|
50
|
+
# - {Context} uses
|
51
|
+
# {include:Actor::Behaviour.basic_behaviour_definition}
|
52
|
+
#
|
53
|
+
# - {RestartingContext} uses
|
54
|
+
# {include:Actor::Behaviour.restarting_behaviour_definition}
|
55
|
+
module Behaviour
|
56
|
+
MESSAGE_PROCESSED = Object.new
|
57
|
+
|
58
|
+
require 'concurrent/actor/behaviour/abstract'
|
59
|
+
require 'concurrent/actor/behaviour/awaits'
|
60
|
+
require 'concurrent/actor/behaviour/buffer'
|
61
|
+
require 'concurrent/actor/behaviour/errors_on_unknown_message'
|
62
|
+
require 'concurrent/actor/behaviour/executes_context'
|
63
|
+
require 'concurrent/actor/behaviour/linking'
|
64
|
+
require 'concurrent/actor/behaviour/pausing'
|
65
|
+
require 'concurrent/actor/behaviour/removes_child'
|
66
|
+
require 'concurrent/actor/behaviour/sets_results'
|
67
|
+
require 'concurrent/actor/behaviour/supervising'
|
68
|
+
require 'concurrent/actor/behaviour/termination'
|
69
|
+
require 'concurrent/actor/behaviour/terminates_children'
|
70
|
+
|
71
|
+
# Array of behaviours and their construction parameters.
|
72
|
+
#
|
73
|
+
# [[Behaviour::SetResults, :terminate!],
|
74
|
+
# [Behaviour::RemovesChild],
|
75
|
+
# [Behaviour::Termination],
|
76
|
+
# [Behaviour::TerminatesChildren],
|
77
|
+
# [Behaviour::Linking],
|
78
|
+
# [Behaviour::Awaits],
|
79
|
+
# [Behaviour::ExecutesContext],
|
80
|
+
# [Behaviour::ErrorsOnUnknownMessage]]
|
81
|
+
#
|
82
|
+
# @see '' its source code
|
83
|
+
def self.basic_behaviour_definition
|
84
|
+
[*base(:terminate!),
|
85
|
+
*linking,
|
86
|
+
*user_messages]
|
87
|
+
end
|
88
|
+
|
89
|
+
# Array of behaviours and their construction parameters.
|
90
|
+
#
|
91
|
+
# [[Behaviour::SetResults, :pause!],
|
92
|
+
# [Behaviour::RemovesChild],
|
93
|
+
# [Behaviour::Termination],
|
94
|
+
# [Behaviour::TerminatesChildren],
|
95
|
+
# [Behaviour::Linking],
|
96
|
+
# [Behaviour::Pausing],
|
97
|
+
# [Behaviour::Supervising, :reset!, :one_for_one],
|
98
|
+
# [Behaviour::Awaits],
|
99
|
+
# [Behaviour::ExecutesContext],
|
100
|
+
# [Behaviour::ErrorsOnUnknownMessage]]
|
101
|
+
#
|
102
|
+
# @see '' its source code
|
103
|
+
def self.restarting_behaviour_definition(handle = :reset!, strategy = :one_for_one)
|
104
|
+
[*base(:pause!),
|
105
|
+
*linking,
|
106
|
+
*supervised,
|
107
|
+
*supervising(handle, strategy),
|
108
|
+
*user_messages]
|
109
|
+
end
|
110
|
+
|
111
|
+
# @see '' its source code
|
112
|
+
def self.base(on_error)
|
113
|
+
[[SetResults, on_error],
|
114
|
+
# has to be before Termination to be able to remove children from terminated actor
|
115
|
+
RemovesChild,
|
116
|
+
Termination,
|
117
|
+
TerminatesChildren]
|
118
|
+
end
|
119
|
+
|
120
|
+
# @see '' its source code
|
121
|
+
def self.linking
|
122
|
+
[Linking]
|
123
|
+
end
|
124
|
+
|
125
|
+
# @see '' its source code
|
126
|
+
def self.supervised
|
127
|
+
[Pausing]
|
128
|
+
end
|
129
|
+
|
130
|
+
# @see '' its source code
|
131
|
+
def self.supervising(handle = :reset!, strategy = :one_for_one)
|
132
|
+
[[Behaviour::Supervising, handle, strategy]]
|
133
|
+
end
|
134
|
+
|
135
|
+
# @see '' its source code
|
136
|
+
def self.user_messages
|
137
|
+
[Awaits,
|
138
|
+
ExecutesContext,
|
139
|
+
ErrorsOnUnknownMessage]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|