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.
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