concurrent-ruby-edge 0.1.2 → 0.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e691a974bbd43a36db55136dfefc96376a18ee99
4
- data.tar.gz: c2fab3e02530312a7ed81244bbeead41cd616281
3
+ metadata.gz: 09cfa6d29b8c6ad451d4d5805fe16ff7fe490703
4
+ data.tar.gz: 721b15c9fa7a8c38e88c9d5f1e8597e0528386c6
5
5
  SHA512:
6
- metadata.gz: e00ec82a9a7e7a55ca5eab51e46eb3f412a45a4b38c76757348772adfdc72f8066f9b4a5412ed35949e3b7c8145d1d2bd1934d4f4b2cff2ef73922acb59214e8
7
- data.tar.gz: 22c85760d062d301affa2af1b4a4a841e8a1064e9f0600909a599a449b2cc0fc2e70f6db6da1d6fb716e45d5ad9e046d7b6532cf76c156c3734cd582cefa04ba
6
+ metadata.gz: ce588f1344ce16ab7c0d166bdc1f5c86c02c908083d7fcc10c7ead35a665af4325c1e9ccabfc925f289fdb15db1d68a4fff621d67b921b6b75f6115fc4ffc22b
7
+ data.tar.gz: 479a2bb45adde98a74aa5ced4fea11d1112ccedb64d07e5dc5783d07cf750d905888effd97d8108b3dc2b928f394055423aa5bc6b8343bc26647b62bf4422300
data/README.md CHANGED
@@ -47,7 +47,7 @@
47
47
 
48
48
  MRI 1.9.3, 2.0, 2.1, 2.2, JRuby (1.9 mode), and Rubinius 2.x are supported.
49
49
  This gem should be fully compatible with any interpreter that is compliant with Ruby 1.9.3 or newer.
50
- Java 8 is required for JRuby (Java 7 support is deprecated in version 0.9 and will be removed in 1.0).
50
+ Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs will be supported.
51
51
 
52
52
  ## Features & Documentation
53
53
 
@@ -62,54 +62,62 @@ This library contains a variety of concurrency abstractions at high and low leve
62
62
  #### General-purpose Concurrency Abstractions
63
63
 
64
64
  * [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.
65
- * [Atom](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Atom.html): A way to manage shared, synchronous, independent state.
66
65
  * [Future](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html): An asynchronous operation that produces a value.
67
66
  * [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.
68
67
  * [Promise](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promise.html): Similar to Futures, with more features.
69
68
  * [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ScheduledTask.html): Like a Future scheduled for a specific future time.
70
69
  * [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TimerTask.html): A Thread that periodically wakes up to perform work at regular intervals.
71
70
 
72
- #### Thread-safe Value Objects
71
+ #### Thread-safe Value Objects, Structures, and Collections
72
+
73
+ Collection classes that were originally part of the (deprecated) `thread_safe` gem:
74
+
75
+ * [Array](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Array.html) A thread-safe subclass of Ruby's standard [Array](http://ruby-doc.org/core-2.2.0/Array.html).
76
+ * [Hash](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Hash.html) A thread-safe subclass of Ruby's standard [Hash](http://ruby-doc.org/core-2.2.0/Hash.html).
77
+ * [Map](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Map.html) A hash-like object that should have much better performance characteristics, especially under high concurrency, than `Concurrent::Hash`.
78
+ * [Tuple](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Tuple.html) A fixed size array with volatile (synchronized, thread safe) getters/setters.
79
+
80
+ Value objects inspired by other languages:
73
81
 
74
- * `Maybe` A thread-safe, immutable object representing an optional value, based on
82
+ * [Atom](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Atom.html): A way to manage shared, synchronous, independent state.
83
+ * [Maybe](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Maybe.html) A thread-safe, immutable object representing an optional value, based on
75
84
  [Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
76
- * `Delay` Lazy evaluation of a block yielding an immutable result. Based on Clojure's
85
+ * [Delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html) Lazy evaluation of a block yielding an immutable result. Based on Clojure's
77
86
  [delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html).
78
87
 
79
- #### Thread-safe Structures
88
+ Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
89
+
90
+ * [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ImmutableStruct.html) Immutable struct where values are set at construction and cannot be changed later.
91
+ * [MutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutableStruct.html) Synchronized, mutable struct where values can be safely changed at any time.
92
+ * [SettableStruct](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/SettableStruct.html) Synchronized, write-once struct where values can be set at most once, either at construction or any time thereafter.
80
93
 
81
- Derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
94
+ Thread-safe variables:
82
95
 
83
- * `ImmutableStruct` Immutable struct where values are set at construction and cannot be changed later.
84
- * `MutableStruct` Synchronized, mutable struct where values can be safely changed at any time.
85
- * `SettableStruct` Synchronized, write-once struct where values can be set at most once, either at construction or any time thereafter.
96
+ * [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html) A boolean value that can be updated atomically.
97
+ * [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html) A numeric value that can be updated atomically.
98
+ * [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html) An object reference that may be updated atomically.
99
+ * [ThreadLocalVar](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html) A variable where the value is different for each thread.
86
100
 
87
101
  #### Java-inspired ThreadPools and Other Executors
88
102
 
89
- * See [ThreadPool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
103
+ * See the [thread pool](http://ruby-concurrency.github.io/concurrent-ruby/file.thread_pools.html) overview, which also contains a list of other Executors available.
90
104
 
91
105
  #### Thread Synchronization Classes and Algorithms
92
106
 
93
- * [CountdownLatch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html)
94
- * [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html)
95
- * [Event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html)
96
- * [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html)
97
-
98
- #### Thread-safe Variables
99
-
100
- * [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicBoolean.html)
101
- * [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html)
102
- * [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html)
103
- * [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
104
- * [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
105
- * [Thread-local variables](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadLocalVar.html)
106
- * [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar)
107
- * [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html)
108
- * [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReentrantReadWriteLock.html)
107
+ * [CountdownLatch](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CountDownLatch.html) A synchronization object that allows one thread to wait on multiple other threads.
108
+ * [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/CyclicBarrier.html) A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
109
+ * [Event](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Event.html) Old school kernel-style event.
110
+ * [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
111
+ * [I-Structure](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar) Similar to a "future" but can be manually assigned once, after which it becomes immutable.
112
+ * [M-Structure](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar) A synchronized single element container.
113
+ * [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReadWriteLock.html) A lock that supports multiple readers but only one writer.
114
+ * [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ReentrantReadWriteLock.html) A read/write lock with reentrant and upgrade features.
115
+ * [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Semaphore.html) A counting-based locking mechanism that uses permits.
116
+ * [Software transactional memory](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/TVar.html) (TVar) A transactional variable - a single-element container that is used as part of a transaction.
109
117
 
110
118
  ### Edge Features
111
119
 
112
- These are available in the `concurrent-ruby-edge` companion gem, installed with `gem install concurrent-ruby-edge`.
120
+ These are available in the `concurrent-ruby-edge` companion gem.
113
121
 
114
122
  These features are under active development and may change frequently. They are expected not to
115
123
  keep backward compatibility (there may also lack tests and documentation). Semantic versions will
@@ -125,10 +133,9 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
125
133
  * [Agent](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Agent.html): A single atomic value that represents an identity.
126
134
  * [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Channel.html):
127
135
  Communicating Sequential Processes (CSP).
128
- * [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
129
136
  * [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
130
- * [Atomic Markable Reference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/AtomicMarkableReference.html)
131
- * [LockFreeLinked Set](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeLinkedSet.html)
137
+ * [AtomicMarkableReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/AtomicMarkableReference.html)
138
+ * [LockFreeLinkedSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeLinkedSet.html)
132
139
  * [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeStack.html)
133
140
 
134
141
  #### Statuses:
@@ -139,52 +146,21 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
139
146
  - **Future/Promise Framework** - API changes; partial documentation and tests; stability good.
140
147
  - **Agent** - Incomplete behaviour compared to Clojure's models; stability good.
141
148
  - **Channel** - Missing documentation; limted features; stability good.
142
- - **Exchanger** - Known race condition requiring a new implementation.
143
149
  - **LazyRegister** - Missing documentation and tests.
144
150
  - **AtomicMarkableReference, LockFreeLinkedSet, LockFreeStack** - Needs real world battle testing
145
151
 
146
152
  ## Usage
147
153
 
148
- All abstractions within this gem can be loaded simply by requiring it:
154
+ Everything within this gem can be loaded simply by requiring it:
149
155
 
150
156
  ```ruby
151
157
  require 'concurrent'
152
158
  ```
153
159
 
154
- To reduce the amount of code loaded at runtime, subsets of this gem can be required:
160
+ To use the tools in the Edge gem it must be required separately:
155
161
 
156
162
  ```ruby
157
- require 'concurrent' # everything
158
-
159
- # groups
160
-
161
- require 'concurrent/atomics' # atomic and thread synchronization classes
162
- require 'concurrent/executors' # Thread pools and other executors
163
-
164
- # individual abstractions
165
-
166
- require 'concurrent/async' # Concurrent::Async
167
- require 'concurrent/atom' # Concurrent::Atom
168
- require 'concurrent/dataflow' # Concurrent::dataflow
169
- require 'concurrent/delay' # Concurrent::Delay
170
- require 'concurrent/future' # Concurrent::Future
171
- require 'concurrent/immutable_struct' # Concurrent::ImmutableStruct
172
- require 'concurrent/ivar' # Concurrent::IVar
173
- require 'concurrent/maybe' # Concurrent::Maybe
174
- require 'concurrent/mutable_struct' # Concurrent::MutableStruct
175
- require 'concurrent/mvar' # Concurrent::MVar
176
- require 'concurrent/promise' # Concurrent::Promise
177
- require 'concurrent/scheduled_task' # Concurrent::ScheduledTask
178
- require 'concurrent/settable_struct' # Concurrent::SettableStruct
179
- require 'concurrent/timer_task' # Concurrent::TimerTask
180
- require 'concurrent/tvar' # Concurrent::TVar
181
-
182
- # experimental - available in `concurrent-ruby-edge` companion gem
183
-
184
- require 'concurrent/actor' # Concurrent::Actor and supporting code
185
- require 'concurrent/edge/future' # new Future Framework
186
- require 'concurrent/agent' # Concurrent::Agent
187
- require 'concurrent/channel ' # Concurrent::Channel and supporting code
163
+ require 'concurrent-edge'
188
164
  ```
189
165
 
190
166
  If the library does not behave as expected, `Concurrent.use_stdlib_logger(Logger::DEBUG)` could help to reveal the problem.
@@ -203,6 +179,23 @@ gem 'concurrent-ruby'
203
179
 
204
180
  and run `bundle install` from your shell.
205
181
 
182
+ ### Edge Gem Installation
183
+
184
+ The Edge gem must be installed separately from the core gem:
185
+
186
+ ```shell
187
+ gem install concurrent-ruby-edge
188
+ ```
189
+
190
+ or add the following line to Gemfile:
191
+
192
+ ```ruby
193
+ gem 'concurrent-ruby-edge'
194
+ ```
195
+
196
+ and run `bundle install` from your shell.
197
+
198
+
206
199
  ### C Extensions for MRI
207
200
 
208
201
  Potential performance improvements may be achieved under MRI by installing optional C extensions.
@@ -240,7 +233,7 @@ The best practice is to depend on `concurrent-ruby` and let users to decide if t
240
233
 
241
234
  All published versions of this gem (core, extension, and several platform-specific packages) are compiled,
242
235
  packaged, tested, and published using an open, [automated process](https://github.com/ruby-concurrency/rake-compiler-dev-box).
243
- This process can also be used to create pre-compiled binaries of the extension gem for virtally
236
+ This process can also be used to create pre-compiled binaries of the extension gem for virtually
244
237
  any platform. *Documentation is forthcoming...*
245
238
 
246
239
  ```
@@ -272,11 +265,17 @@ bundle exec rake compile # Compile all the extensions
272
265
  ## Maintainers
273
266
 
274
267
  * [Jerry D'Antonio](https://github.com/jdantonio) (creator)
268
+ * [Petr Chalupa](https://github.com/pitr-ch)
275
269
  * [Michele Della Torre](https://github.com/mighe)
276
270
  * [Chris Seaton](https://github.com/chrisseaton)
277
- * [Lucas Allan](https://github.com/lucasallan)
278
- * [Petr Chalupa](https://github.com/pitr-ch)
279
271
  * [Paweł Obrok](https://github.com/obrok)
272
+ * [Lucas Allan](https://github.com/lucasallan)
273
+
274
+ ### Special Thanks
275
+
276
+ * [Brian Durand](https://github.com/bdurand) for the `ref` gem
277
+ * [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
278
+ * [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
280
279
 
281
280
  ## Contributing
282
281
 
@@ -85,7 +85,7 @@ module Concurrent
85
85
  # @overload to_spawn_options(opts)
86
86
  # see {Core#initialize} opts
87
87
  def self.to_spawn_options(*args)
88
- if args.size == 1 && args.first.is_a?(Hash)
88
+ if args.size == 1 && args.first.is_a?(::Hash)
89
89
  args.first
90
90
  else
91
91
  { class: args[0],
@@ -6,6 +6,7 @@ module Concurrent
6
6
  class Abstract
7
7
  include TypeCheck
8
8
  include InternalDelegations
9
+ include Concern::Logging
9
10
 
10
11
  attr_reader :core, :subsequent
11
12
 
@@ -41,7 +42,7 @@ module Concurrent
41
42
  def reject_envelope(envelope)
42
43
  envelope.reject! ActorTerminated.new(reference)
43
44
  dead_letter_routing << envelope unless envelope.future
44
- log(DEBUG) { "rejected #{envelope.message} from #{envelope.sender_path}"}
45
+ log DEBUG, "rejected #{envelope.message} from #{envelope.sender_path}"
45
46
  end
46
47
  end
47
48
  end
@@ -14,7 +14,7 @@ module Concurrent
14
14
  result = pass envelope
15
15
  if result != MESSAGE_PROCESSED && !envelope.future.nil?
16
16
  envelope.future.success result
17
- log(DEBUG) { "finished processing of #{envelope.message.inspect}"}
17
+ log DEBUG, "finished processing of #{envelope.message.inspect}"
18
18
  end
19
19
  nil
20
20
  rescue => error
@@ -24,6 +24,7 @@ module Concurrent
24
24
  class AbstractContext
25
25
  include TypeCheck
26
26
  include InternalDelegations
27
+ include Concern::Logging
27
28
 
28
29
  attr_reader :core
29
30
 
@@ -128,7 +129,7 @@ module Concurrent
128
129
  end
129
130
 
130
131
  def self.to_spawn_options(name_or_opts, *args)
131
- if name_or_opts.is_a? Hash
132
+ if name_or_opts.is_a? ::Hash
132
133
  if name_or_opts.key?(:class) && name_or_opts[:class] != self
133
134
  raise ArgumentError,
134
135
  ':class option is ignored when calling on context class, use Actor.spawn instead'
@@ -91,7 +91,7 @@ module Concurrent
91
91
  # @param [Envelope] envelope
92
92
  def on_envelope(envelope)
93
93
  schedule_execution do
94
- log(DEBUG) { "was #{envelope.future ? 'asked' : 'told'} #{envelope.message.inspect} by #{envelope.sender}" }
94
+ log DEBUG, "was #{envelope.future ? 'asked' : 'told'} #{envelope.message.inspect} by #{envelope.sender}"
95
95
  process_envelope envelope
96
96
  end
97
97
  nil
@@ -128,7 +128,7 @@ module Concurrent
128
128
  end
129
129
 
130
130
  def broadcast(public, event)
131
- log(DEBUG) { "event: #{event.inspect} (#{public ? 'public' : 'private'})" }
131
+ log DEBUG, "event: #{event.inspect} (#{public ? 'public' : 'private'})"
132
132
  @first_behaviour.on_event(public, event)
133
133
  end
134
134
 
@@ -164,7 +164,7 @@ module Concurrent
164
164
  private
165
165
 
166
166
  def ns_initialize(opts, &block)
167
- @mailbox = Array.new
167
+ @mailbox = ::Array.new
168
168
  @serialized_execution = SerializedExecution.new
169
169
  @children = Set.new
170
170
 
@@ -208,7 +208,7 @@ module Concurrent
208
208
  end
209
209
 
210
210
  def initialize_behaviours(opts)
211
- @behaviour_definition = (Type! opts[:behaviour_definition] || @context.behaviour_definition, Array).each do |(behaviour, _)|
211
+ @behaviour_definition = (Type! opts[:behaviour_definition] || @context.behaviour_definition, ::Array).each do |(behaviour, _)|
212
212
  Child! behaviour, Behaviour::Abstract
213
213
  end
214
214
  @behaviours = {}
@@ -2,7 +2,7 @@ module Concurrent
2
2
  module Actor
3
3
  class DefaultDeadLetterHandler < RestartingContext
4
4
  def on_message(dead_letter)
5
- log(INFO) { "got dead letter #{dead_letter.inspect}"}
5
+ log INFO, "got dead letter #{dead_letter.inspect}"
6
6
  end
7
7
  end
8
8
  end
@@ -2,7 +2,6 @@ module Concurrent
2
2
  module Actor
3
3
  module InternalDelegations
4
4
  include PublicDelegations
5
- include Logger::Severity
6
5
 
7
6
  # @see Core#children
8
7
  def children
@@ -14,7 +14,7 @@ module Concurrent
14
14
  # to allow spawning of new actors, spawn needs to be called inside the parent Actor
15
15
  def on_message(message)
16
16
  case
17
- when message.is_a?(Array) && message.first == :spawn
17
+ when message.is_a?(::Array) && message.first == :spawn
18
18
  Actor.spawn message[1], &message[2]
19
19
  when message == :dead_letter_routing
20
20
  @dead_letter_router
@@ -29,7 +29,7 @@ module Concurrent
29
29
  class Pool < RestartingContext
30
30
  def initialize(size, &worker_initializer)
31
31
  @balancer = Balancer.spawn name: :balancer, supervise: true
32
- @workers = Array.new(size, &worker_initializer)
32
+ @workers = ::Array.new(size, &worker_initializer)
33
33
  @workers.each do |worker|
34
34
  Type! worker, Reference
35
35
  @balancer << [:subscribe, worker]
@@ -1,10 +1,9 @@
1
- require 'thread'
2
1
  require 'concurrent/collection/copy_on_write_observer_set'
3
2
  require 'concurrent/concern/dereferenceable'
4
3
  require 'concurrent/concern/observable'
5
4
  require 'concurrent/concern/logging'
6
5
  require 'concurrent/executor/executor'
7
- require 'concurrent/concern/deprecation'
6
+ require 'concurrent/synchronization'
8
7
 
9
8
  module Concurrent
10
9
 
@@ -81,11 +80,10 @@ module Concurrent
81
80
  # @return [Fixnum] the maximum number of seconds before an update is cancelled
82
81
  #
83
82
  # @!macro edge_warning
84
- class Agent
83
+ class Agent < Synchronization::Object
85
84
  include Concern::Dereferenceable
86
85
  include Concern::Observable
87
86
  include Concern::Logging
88
- include Concern::Deprecation
89
87
 
90
88
  attr_reader :timeout, :io_executor, :fast_executor
91
89
 
@@ -95,15 +93,8 @@ module Concurrent
95
93
  #
96
94
  # @!macro executor_and_deref_options
97
95
  def initialize(initial, opts = {})
98
- @value = initial
99
- @rescuers = []
100
- @validator = Proc.new { |result| true }
101
- self.observers = Collection::CopyOnWriteObserverSet.new
102
- @serialized_execution = SerializedExecution.new
103
- @io_executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
104
- @fast_executor = Executor.executor_from_options(opts) || Concurrent.global_fast_executor
105
- init_mutex
106
- set_deref_options(opts)
96
+ super()
97
+ synchronize { ns_initialize(initial, opts) }
107
98
  end
108
99
 
109
100
  # Specifies a block fast to be performed when an update fast raises
@@ -129,9 +120,7 @@ module Concurrent
129
120
  # #=> puts "Pow!"
130
121
  def rescue(clazz = StandardError, &block)
131
122
  unless block.nil?
132
- mutex.synchronize do
133
- @rescuers << Rescuer.new(clazz, block)
134
- end
123
+ synchronize { @rescuers << Rescuer.new(clazz, block) }
135
124
  end
136
125
  self
137
126
  end
@@ -139,7 +128,7 @@ module Concurrent
139
128
  alias_method :catch, :rescue
140
129
  alias_method :on_error, :rescue
141
130
 
142
- # A block fast to be performed after every update to validate if the new
131
+ # A block task to be performed after every update to validate if the new
143
132
  # value is valid. If the new value is not valid then the current value is not
144
133
  # updated. If no validator is provided then all updates are considered valid.
145
134
  #
@@ -150,12 +139,7 @@ module Concurrent
150
139
  def validate(&block)
151
140
 
152
141
  unless block.nil?
153
- begin
154
- mutex.lock
155
- @validator = block
156
- ensure
157
- mutex.unlock
158
- end
142
+ synchronize { @validator = block }
159
143
  end
160
144
  self
161
145
  end
@@ -179,30 +163,13 @@ module Concurrent
179
163
  # Update the current value with the result of the given block fast,
180
164
  # block can do blocking calls
181
165
  #
182
- # @param [Fixnum, nil] timeout [DEPRECATED] maximum number of seconds before an update is cancelled
183
- #
184
166
  # @yield the fast to be performed with the current value in order to calculate
185
167
  # the new value
186
168
  # @yieldparam [Object] value the current value
187
169
  # @yieldreturn [Object] the new value
188
170
  # @return [true, nil] nil when no block is given
189
- def post_off(timeout = nil, &block)
190
- task = if timeout
191
- deprecated 'post_off with option timeout options is deprecated and will be removed'
192
- lambda do |value|
193
- future = Future.execute do
194
- block.call(value)
195
- end
196
- if future.wait(timeout)
197
- future.value!
198
- else
199
- raise Concurrent::TimeoutError
200
- end
201
- end
202
- else
203
- block
204
- end
205
- post_on(@io_executor, &task)
171
+ def post_off(&block)
172
+ post_on(@io_executor, &block)
206
173
  end
207
174
 
208
175
  # Update the current value with the result of the given block fast,
@@ -227,6 +194,20 @@ module Concurrent
227
194
  done.wait timeout
228
195
  end
229
196
 
197
+ protected
198
+
199
+ def ns_initialize(initial, opts)
200
+ init_mutex(self)
201
+ @value = initial
202
+ @rescuers = []
203
+ @validator = Proc.new { |result| true }
204
+ self.observers = Collection::CopyOnWriteObserverSet.new
205
+ @serialized_execution = SerializedExecution.new
206
+ @io_executor = Executor.executor_from_options(opts) || Concurrent.global_io_executor
207
+ @fast_executor = Executor.executor_from_options(opts) || Concurrent.global_fast_executor
208
+ set_deref_options(opts)
209
+ end
210
+
230
211
  private
231
212
 
232
213
  def post_on(executor, &block)
@@ -240,7 +221,7 @@ module Concurrent
240
221
 
241
222
  # @!visibility private
242
223
  def try_rescue(ex) # :nodoc:
243
- rescuer = mutex.synchronize do
224
+ rescuer = synchronize do
244
225
  @rescuers.find { |r| ex.is_a?(r.clazz) }
245
226
  end
246
227
  rescuer.block.call(ex) if rescuer
@@ -251,7 +232,7 @@ module Concurrent
251
232
 
252
233
  # @!visibility private
253
234
  def work(&handler) # :nodoc:
254
- validator, value = mutex.synchronize { [@validator, @value] }
235
+ validator, value = synchronize { [@validator, @value] }
255
236
 
256
237
  begin
257
238
  result = handler.call(value)
@@ -260,14 +241,11 @@ module Concurrent
260
241
  exception = ex
261
242
  end
262
243
 
263
- begin
264
- mutex.lock
265
- should_notify = if !exception && valid
266
- @value = result
267
- true
268
- end
269
- ensure
270
- mutex.unlock
244
+ should_notify = synchronize do
245
+ if !exception && valid
246
+ @value = result
247
+ true
248
+ end
271
249
  end
272
250
 
273
251
  if should_notify
@@ -1,3 +1,4 @@
1
+ require 'concurrent/synchronization'
1
2
  require 'concurrent/channel/waitable_list'
2
3
 
3
4
  module Concurrent
@@ -5,14 +6,11 @@ module Concurrent
5
6
 
6
7
  # @api Channel
7
8
  # @!macro edge_warning
8
- class BufferedChannel
9
+ class BufferedChannel < Synchronization::Object
9
10
 
10
11
  def initialize(size)
11
- @mutex = Mutex.new
12
- @buffer_condition = ConditionVariable.new
13
-
14
- @probe_set = WaitableList.new
15
- @buffer = RingBuffer.new(size)
12
+ super()
13
+ synchronize { ns_initialize(size) }
16
14
  end
17
15
 
18
16
  def probe_set_size
@@ -20,11 +18,11 @@ module Concurrent
20
18
  end
21
19
 
22
20
  def buffer_queue_size
23
- @mutex.synchronize { @buffer.count }
21
+ synchronize { @buffer.count }
24
22
  end
25
23
 
26
24
  def push(value)
27
- until set_probe_or_push_into_buffer(value)
25
+ until set_probe_or_ns_push_into_buffer(value)
28
26
  end
29
27
  end
30
28
 
@@ -35,15 +33,13 @@ module Concurrent
35
33
  end
36
34
 
37
35
  def select(probe)
38
- @mutex.synchronize do
39
-
36
+ synchronize do
40
37
  if @buffer.empty?
41
38
  @probe_set.put(probe)
42
39
  true
43
40
  else
44
- shift_buffer if probe.try_set([peek_buffer, self])
41
+ ns_shift_buffer if probe.try_set([ns_peek_buffer, self])
45
42
  end
46
-
47
43
  end
48
44
  end
49
45
 
@@ -51,37 +47,43 @@ module Concurrent
51
47
  @probe_set.delete(probe)
52
48
  end
53
49
 
50
+ protected
51
+
52
+ def ns_initialize(size)
53
+ @probe_set = WaitableList.new
54
+ @buffer = RingBuffer.new(size)
55
+ end
56
+
54
57
  private
55
58
 
56
- def push_into_buffer(value)
57
- @buffer_condition.wait(@mutex) while @buffer.full?
59
+ def ns_push_into_buffer(value)
60
+ ns_wait while @buffer.full?
58
61
  @buffer.offer value
59
- @buffer_condition.broadcast
62
+ ns_broadcast
60
63
  end
61
64
 
62
- def peek_buffer
63
- @buffer_condition.wait(@mutex) while @buffer.empty?
65
+ def ns_peek_buffer
66
+ ns_wait while @buffer.empty?
64
67
  @buffer.peek
65
68
  end
66
69
 
67
- def shift_buffer
68
- @buffer_condition.wait(@mutex) while @buffer.empty?
70
+ def ns_shift_buffer
71
+ ns_wait while @buffer.empty?
69
72
  result = @buffer.poll
70
- @buffer_condition.broadcast
73
+ ns_broadcast
71
74
  result
72
75
  end
73
76
 
74
- def set_probe_or_push_into_buffer(value)
75
- @mutex.synchronize do
77
+ def set_probe_or_ns_push_into_buffer(value)
78
+ synchronize do
76
79
  if @probe_set.empty?
77
- push_into_buffer(value)
80
+ ns_push_into_buffer(value)
78
81
  true
79
82
  else
80
83
  @probe_set.take.try_set([value, self])
81
84
  end
82
85
  end
83
86
  end
84
-
85
87
  end
86
88
  end
87
89
  end
@@ -8,7 +8,7 @@ module Concurrent
8
8
  class RingBuffer
9
9
 
10
10
  def initialize(capacity)
11
- @buffer = Array.new(capacity)
11
+ @buffer = ::Array.new(capacity)
12
12
  @first = @last = 0
13
13
  @count = 0
14
14
  end
@@ -174,7 +174,7 @@ module Concurrent
174
174
  end
175
175
 
176
176
  # Internal/private ImmutableArray for representing pairs
177
- class ImmutableArray < Array
177
+ class ImmutableArray < ::Array
178
178
  def self.new(*args)
179
179
  super(*args).freeze
180
180
  end
@@ -1,4 +1,5 @@
1
1
  require 'concurrent' # TODO do not require whole concurrent gem
2
+ require 'concurrent/concern/deprecation'
2
3
  require 'concurrent/edge/lock_free_stack'
3
4
 
4
5
 
@@ -602,7 +603,7 @@ module Concurrent
602
603
  def exception(*args)
603
604
  raise 'obligation is not failed' unless failed?
604
605
  reason = @State.get.reason
605
- if reason.is_a?(Array)
606
+ if reason.is_a?(::Array)
606
607
  reason.each { |e| log ERROR, 'Edge::Future', e }
607
608
  Concurrent::Error.new 'multiple exceptions, inspect log'
608
609
  else
@@ -1014,7 +1015,7 @@ module Concurrent
1014
1015
  private
1015
1016
 
1016
1017
  def initialize_blocked_by(blocked_by_futures)
1017
- @BlockedBy = Array(blocked_by_futures)
1018
+ @BlockedBy = [blocked_by_futures].flatten
1018
1019
  end
1019
1020
 
1020
1021
  def clear_blocked_by!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby-edge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-11-04 00:00:00.000000000 Z
13
+ date: 2015-08-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: concurrent-ruby
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: 0.9.2
21
+ version: 1.0.0.pre1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: 0.9.2
28
+ version: 1.0.0.pre1
29
29
  description: |
30
30
  These features are under active development and may change frequently. They are expected not to
31
31
  keep backward compatibility (there may also lack tests and documentation). Semantic versions will
@@ -100,9 +100,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
100
  version: 1.9.3
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  requirements:
103
- - - ">="
103
+ - - ">"
104
104
  - !ruby/object:Gem::Version
105
- version: '0'
105
+ version: 1.3.1
106
106
  requirements: []
107
107
  rubyforge_project:
108
108
  rubygems_version: 2.4.8