concurrent-ruby-edge 0.1.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +284 -0
  4. data/lib/concurrent-edge.rb +11 -0
  5. data/lib/concurrent/actor.rb +98 -0
  6. data/lib/concurrent/actor/behaviour.rb +143 -0
  7. data/lib/concurrent/actor/behaviour/abstract.rb +51 -0
  8. data/lib/concurrent/actor/behaviour/awaits.rb +21 -0
  9. data/lib/concurrent/actor/behaviour/buffer.rb +56 -0
  10. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +12 -0
  11. data/lib/concurrent/actor/behaviour/executes_context.rb +17 -0
  12. data/lib/concurrent/actor/behaviour/linking.rb +83 -0
  13. data/lib/concurrent/actor/behaviour/pausing.rb +123 -0
  14. data/lib/concurrent/actor/behaviour/removes_child.rb +16 -0
  15. data/lib/concurrent/actor/behaviour/sets_results.rb +37 -0
  16. data/lib/concurrent/actor/behaviour/supervising.rb +39 -0
  17. data/lib/concurrent/actor/behaviour/terminates_children.rb +14 -0
  18. data/lib/concurrent/actor/behaviour/termination.rb +74 -0
  19. data/lib/concurrent/actor/context.rb +167 -0
  20. data/lib/concurrent/actor/core.rb +220 -0
  21. data/lib/concurrent/actor/default_dead_letter_handler.rb +9 -0
  22. data/lib/concurrent/actor/envelope.rb +41 -0
  23. data/lib/concurrent/actor/errors.rb +27 -0
  24. data/lib/concurrent/actor/internal_delegations.rb +59 -0
  25. data/lib/concurrent/actor/public_delegations.rb +40 -0
  26. data/lib/concurrent/actor/reference.rb +106 -0
  27. data/lib/concurrent/actor/root.rb +37 -0
  28. data/lib/concurrent/actor/type_check.rb +48 -0
  29. data/lib/concurrent/actor/utils.rb +10 -0
  30. data/lib/concurrent/actor/utils/ad_hoc.rb +27 -0
  31. data/lib/concurrent/actor/utils/balancer.rb +43 -0
  32. data/lib/concurrent/actor/utils/broadcast.rb +52 -0
  33. data/lib/concurrent/actor/utils/pool.rb +54 -0
  34. data/lib/concurrent/agent.rb +289 -0
  35. data/lib/concurrent/channel.rb +6 -0
  36. data/lib/concurrent/channel/blocking_ring_buffer.rb +82 -0
  37. data/lib/concurrent/channel/buffered_channel.rb +87 -0
  38. data/lib/concurrent/channel/channel.rb +19 -0
  39. data/lib/concurrent/channel/ring_buffer.rb +65 -0
  40. data/lib/concurrent/channel/unbuffered_channel.rb +39 -0
  41. data/lib/concurrent/channel/waitable_list.rb +48 -0
  42. data/lib/concurrent/edge/atomic_markable_reference.rb +184 -0
  43. data/lib/concurrent/edge/future.rb +1226 -0
  44. data/lib/concurrent/edge/lock_free_stack.rb +85 -0
  45. 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
+ [![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby) [![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby) [![Code Climate](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby.svg)](https://codeclimate.com/github/ruby-concurrency/concurrent-ruby) [![Inline docs](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby.svg)](http://inch-ci.org/github/ruby-concurrency/concurrent-ruby) [![Dependency Status](https://gemnasium.com/ruby-concurrency/concurrent-ruby.svg)](https://gemnasium.com/ruby-concurrency/concurrent-ruby) [![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT) [![Gitter chat](http://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg)](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 &copy; 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