concurrent-ruby 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -12
- data/README.md +28 -38
- data/lib/concurrent/atom.rb +1 -0
- data/lib/concurrent/atomic/atomic_fixnum.rb +4 -0
- data/lib/concurrent/atomic/atomic_reference.rb +7 -0
- data/lib/concurrent/atomic/ruby_thread_local_var.rb +20 -16
- data/lib/concurrent/atomic/thread_local_var.rb +6 -6
- data/lib/concurrent/atomic_reference/jruby+truffle.rb +2 -1
- data/lib/concurrent/collection/map/non_concurrent_map_backend.rb +1 -0
- data/lib/concurrent/configuration.rb +56 -21
- data/lib/concurrent/errors.rb +24 -1
- data/lib/concurrent/synchronization/condition.rb +0 -1
- data/lib/concurrent/synchronization/lock.rb +0 -1
- data/lib/concurrent/synchronization/object.rb +2 -2
- data/lib/concurrent/synchronization/rbx_object.rb +1 -0
- data/lib/concurrent/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f2057bba5c491730f2195150ad50cf4d2602143
|
4
|
+
data.tar.gz: ae0f81c1ca1b860e59d751df021389fac61ad736
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ad27004cc16860bbd15debd5a3ad1b0da3fb3ee2d568f9db428d4eef434ae5e2444548754775ce22dbc820636591e41ce0324a2475acf2e7eb8e9e4bb2e7927
|
7
|
+
data.tar.gz: f6e90a9735aa4ce2bade9754ea15bce067035644658980f24196c9e6cac5b3d9415cb3e0f42206192c58989c3cdebe5fc4b31b978fb4e546dd7fc34f0049da63
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## Current Release v1.0.4 (27 Dec 2016)
|
2
|
+
|
3
|
+
concurrent-ruby:
|
4
|
+
|
5
|
+
* Nothing
|
6
|
+
|
7
|
+
concurrent-ruby-edge:
|
8
|
+
|
9
|
+
* New promises' API renamed, lots of improvements, edge bumped to 0.3.0
|
10
|
+
* **Incompatible** with previous 0.2.3 version
|
11
|
+
* see https://github.com/ruby-concurrency/concurrent-ruby/pull/522
|
12
|
+
|
13
|
+
## Release v1.0.3 (17 Dec 2016)
|
14
|
+
|
1
15
|
* Trigger execution of flattened delayed futures
|
2
16
|
* Avoid forking for processor_count if possible
|
3
17
|
* Semaphore Mutex and JRuby parity
|
@@ -12,14 +26,14 @@
|
|
12
26
|
* Fixes format-security error when compiling ruby_193_compatible.h
|
13
27
|
* Concurrent::Atom#swap fixed: reraise the exceptions from block
|
14
28
|
|
15
|
-
##
|
29
|
+
## Release v1.0.2 (2 May 2016)
|
16
30
|
|
17
31
|
* Fix bug with `Concurrent::Map` MRI backend `#inspect` method
|
18
32
|
* Fix bug with `Concurrent::Map` MRI backend using `Hash#value?`
|
19
33
|
* Improved documentation and examples
|
20
34
|
* Minor updates to Edge
|
21
35
|
|
22
|
-
|
36
|
+
## Release v1.0.1 (27 February 2016)
|
23
37
|
|
24
38
|
* Fix "uninitialized constant Concurrent::ReentrantReadWriteLock" error.
|
25
39
|
* Better handling of `autoload` vs. `require`.
|
@@ -32,7 +46,7 @@
|
|
32
46
|
* Improved documentation.
|
33
47
|
* Updated README and CONTRIBUTING.
|
34
48
|
|
35
|
-
|
49
|
+
## Release v1.0.0 (13 November 2015)
|
36
50
|
|
37
51
|
* Rename `attr_volatile_with_cas` to `attr_atomic`
|
38
52
|
* Add `clear_each` to `LockFreeStack`
|
@@ -80,7 +94,7 @@
|
|
80
94
|
* Many improved tests
|
81
95
|
* Some internal reorganization
|
82
96
|
|
83
|
-
|
97
|
+
## Release v0.9.1 (09 August 2015)
|
84
98
|
|
85
99
|
* Fixed a Rubiniux bug in synchronization object
|
86
100
|
* Fixed all interpreter warnings (except circular references)
|
@@ -94,7 +108,7 @@
|
|
94
108
|
* `ThreadLocalVar#bind` method is now public
|
95
109
|
* Refactored many tests
|
96
110
|
|
97
|
-
|
111
|
+
## Release v0.9.0 (10 July 2015)
|
98
112
|
|
99
113
|
* Updated `AtomicReference`
|
100
114
|
- `AtomicReference#try_update` now simply returns instead of raising exception
|
@@ -193,14 +207,14 @@
|
|
193
207
|
* Removed brute-force killing of threads in tests
|
194
208
|
* Fixed a thread pool bug when the operating system cannot allocate more threads
|
195
209
|
|
196
|
-
|
210
|
+
## Release v0.8.0 (25 January 2015)
|
197
211
|
|
198
212
|
* C extension for MRI have been extracted into the `concurrent-ruby-ext` companion gem.
|
199
213
|
Please see the README for more detail.
|
200
214
|
* Better variable isolation in `Promise` and `Future` via an `:args` option
|
201
215
|
* Continued to update intermittently failing tests
|
202
216
|
|
203
|
-
|
217
|
+
## Release v0.7.2 (24 January 2015)
|
204
218
|
|
205
219
|
* New `Semaphore` class based on [java.util.concurrent.Semaphore](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html)
|
206
220
|
* New `Promise.all?` and `Promise.any?` class methods
|
@@ -217,7 +231,7 @@
|
|
217
231
|
* Tests now run on new Travis build environment
|
218
232
|
* Multiple documentation updates
|
219
233
|
|
220
|
-
|
234
|
+
## Release v0.7.1 (4 December 2014)
|
221
235
|
|
222
236
|
Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/issues/142) for more information on the next planned release.
|
223
237
|
|
@@ -238,7 +252,7 @@ Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/iss
|
|
238
252
|
* Removed confusing warning when not using native extenstions
|
239
253
|
* Improved documentation
|
240
254
|
|
241
|
-
|
255
|
+
## Release v0.7.0 (13 August 2014)
|
242
256
|
|
243
257
|
* Merge the [atomic](https://github.com/ruby-concurrency/atomic) gem
|
244
258
|
- Pure Ruby `MutexAtomic` atomic reference class
|
@@ -271,14 +285,14 @@ Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/iss
|
|
271
285
|
* Removed deprecated `Actor` class
|
272
286
|
* Better support for Rubinius
|
273
287
|
|
274
|
-
|
288
|
+
## Release v0.6.1 (14 June 2014)
|
275
289
|
|
276
290
|
* Many improvements to `Concurrent::Actress`
|
277
291
|
* Bug fixes to `Concurrent::RubyThreadPoolExecutor`
|
278
292
|
* Fixed several brittle tests
|
279
293
|
* Moved documentation to http://ruby-concurrency.github.io/concurrent-ruby/frames.html
|
280
294
|
|
281
|
-
|
295
|
+
## Release v0.6.0 (25 May 2014)
|
282
296
|
|
283
297
|
* Added `Concurrent::Observable` to encapsulate our thread safe observer sets
|
284
298
|
* Improvements to new `Channel`
|
@@ -317,7 +331,7 @@ Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/iss
|
|
317
331
|
* First implementation of [new, high-performance](https://github.com/ruby-concurrency/concurrent-ruby/pull/49) `Channel`
|
318
332
|
* `Actor` is deprecated in favor of new experimental actor implementation [#73](https://github.com/ruby-concurrency/concurrent-ruby/pull/73). To avoid namespace collision it is living in `Actress` namespace until `Actor` is removed in next release.
|
319
333
|
|
320
|
-
|
334
|
+
## Release v0.5.0
|
321
335
|
|
322
336
|
This is the most significant release of this gem since its inception. This release includes many improvements and optimizations. It also includes several bug fixes. The major areas of focus for this release were:
|
323
337
|
|
data/README.md
CHANGED
@@ -9,39 +9,28 @@
|
|
9
9
|
[![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
|
10
10
|
[![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-devs%20%26%20users-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
<li>Support features that make sense in Ruby</li>
|
35
|
-
<li>Exclude features that don't make sense in Ruby</li>
|
36
|
-
<li>Be small, lean, and loosely coupled</li>
|
37
|
-
</ul>
|
38
|
-
</p>
|
39
|
-
</td>
|
40
|
-
<td align="right" valign="top">
|
41
|
-
<img src="https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/doc/logo/concurrent-ruby-logo-300x300.png"/>
|
42
|
-
</td>
|
43
|
-
</tr>
|
44
|
-
</table>
|
12
|
+
Modern concurrency tools for Ruby. Inspired by
|
13
|
+
[Erlang](http://www.erlang.org/doc/reference_manual/processes.html),
|
14
|
+
[Clojure](http://clojure.org/concurrent_programming),
|
15
|
+
[Scala](http://akka.io/),
|
16
|
+
[Haskell](http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell),
|
17
|
+
[F#](http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx),
|
18
|
+
[C#](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx),
|
19
|
+
[Java](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html),
|
20
|
+
and classic concurrency patterns.
|
21
|
+
|
22
|
+
<img src="https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/doc/logo/concurrent-ruby-logo-300x300.png" align="right" style="margin-left: 20px;" />
|
23
|
+
|
24
|
+
The design goals of this gem are:
|
25
|
+
|
26
|
+
* Be an 'unopinionated' toolbox that provides useful utilities without debating which is better or why
|
27
|
+
* Remain free of external gem dependencies
|
28
|
+
* Stay true to the spirit of the languages providing inspiration
|
29
|
+
* But implement in a way that makes sense for Ruby
|
30
|
+
* Keep the semantics as idiomatic Ruby as possible
|
31
|
+
* Support features that make sense in Ruby
|
32
|
+
* Exclude features that don't make sense in Ruby
|
33
|
+
* Be small, lean, and loosely coupled
|
45
34
|
|
46
35
|
### Supported Ruby versions
|
47
36
|
|
@@ -127,13 +116,13 @@ These features are under active development and may change frequently. They are
|
|
127
116
|
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
|
128
117
|
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when final.
|
129
118
|
|
130
|
-
* [
|
131
|
-
Implements the Actor Model, where concurrent actors exchange messages.
|
132
|
-
* [New Future Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/FutureShortcuts.html):
|
119
|
+
* [Promises Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promises.html):
|
133
120
|
Unified implementation of futures and promises which combines features of previous `Future`,
|
134
121
|
`Promise`, `IVar`, `Event`, `dataflow`, `Delay`, and `TimerTask` into a single framework. It extensively uses the
|
135
122
|
new synchronization layer to make all the features **non-blocking** and **lock-free**, with the exception of obviously blocking
|
136
123
|
operations like `#wait`, `#value`. It also offers better performance.
|
124
|
+
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html):
|
125
|
+
Implements the Actor Model, where concurrent actors exchange messages.
|
137
126
|
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/Channel.html):
|
138
127
|
Communicating Sequential Processes ([CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)).
|
139
128
|
Functionally equivalent to Go [channels](https://tour.golang.org/concurrency/2) with additional
|
@@ -141,15 +130,16 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
|
|
141
130
|
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
|
142
131
|
* [AtomicMarkableReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/AtomicMarkableReference.html)
|
143
132
|
* [LockFreeLinkedSet](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge/LockFreeLinkedSet.html)
|
144
|
-
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/
|
133
|
+
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LockFreeStack.html)
|
145
134
|
|
146
135
|
#### Statuses:
|
147
136
|
|
148
137
|
*Why are these not in core?*
|
149
138
|
|
139
|
+
- **Promises Framework** - They are being finalized to be able to be moved to core. They'll deprecate old
|
140
|
+
implementation.
|
150
141
|
- **Actor** - Partial documentation and tests; depends on new future/promise framework; stability is good.
|
151
142
|
- **Channel** - Brand new implementation; partial documentation and tests; stability is good.
|
152
|
-
- **Future/Promise Framework** - API changes; partial documentation and tests; stability is good.
|
153
143
|
- **LazyRegister** - Missing documentation and tests.
|
154
144
|
- **AtomicMarkableReference, LockFreeLinkedSet, LockFreeStack** - Need real world battle testing.
|
155
145
|
|
data/lib/concurrent/atom.rb
CHANGED
@@ -37,6 +37,7 @@ require 'concurrent/synchronization'
|
|
37
37
|
# *coordinated*, *synchronous*, change of *many* stated. Used when multiple
|
38
38
|
# value must change together, in an all-or-nothing transaction.
|
39
39
|
|
40
|
+
|
40
41
|
module Concurrent
|
41
42
|
|
42
43
|
# Atoms provide a way to manage shared, synchronous, independent state.
|
@@ -129,5 +129,9 @@ module Concurrent
|
|
129
129
|
#
|
130
130
|
# @!macro atomic_fixnum_public_api
|
131
131
|
class AtomicFixnum < AtomicFixnumImplementation
|
132
|
+
# @return [String] Short string representation.
|
133
|
+
def to_s
|
134
|
+
format '<#%s:0x%x value:%s>', self.class, object_id << 1, get
|
135
|
+
end
|
132
136
|
end
|
133
137
|
end
|
@@ -40,3 +40,10 @@ else
|
|
40
40
|
class Concurrent::AtomicReference < Concurrent::MutexAtomicReference
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
class Concurrent::AtomicReference
|
45
|
+
# @return [String] Short string representation.
|
46
|
+
def to_s
|
47
|
+
format '<#%s:0x%x value:%s>', self.class, object_id << 1, get
|
48
|
+
end
|
49
|
+
end
|
@@ -29,8 +29,8 @@ module Concurrent
|
|
29
29
|
# array, so we don't leak memory
|
30
30
|
|
31
31
|
# @!visibility private
|
32
|
-
FREE
|
33
|
-
LOCK
|
32
|
+
FREE = []
|
33
|
+
LOCK = Mutex.new
|
34
34
|
ARRAYS = {} # used as a hash set
|
35
35
|
@@next = 0
|
36
36
|
private_constant :FREE, :LOCK, :ARRAYS
|
@@ -72,9 +72,9 @@ module Concurrent
|
|
72
72
|
def allocate_storage
|
73
73
|
@index = LOCK.synchronize do
|
74
74
|
FREE.pop || begin
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
result = @@next
|
76
|
+
@@next += 1
|
77
|
+
result
|
78
78
|
end
|
79
79
|
end
|
80
80
|
ObjectSpace.define_finalizer(self, self.class.threadlocal_finalizer(@index))
|
@@ -83,13 +83,15 @@ module Concurrent
|
|
83
83
|
# @!visibility private
|
84
84
|
def self.threadlocal_finalizer(index)
|
85
85
|
proc do
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
86
|
+
Thread.new do # avoid error: can't be called from trap context
|
87
|
+
LOCK.synchronize do
|
88
|
+
FREE.push(index)
|
89
|
+
# The cost of GC'ing a TLV is linear in the number of threads using TLVs
|
90
|
+
# But that is natural! More threads means more storage is used per TLV
|
91
|
+
# So naturally more CPU time is required to free more storage
|
92
|
+
ARRAYS.each_value do |array|
|
93
|
+
array[index] = nil
|
94
|
+
end
|
93
95
|
end
|
94
96
|
end
|
95
97
|
end
|
@@ -98,10 +100,12 @@ module Concurrent
|
|
98
100
|
# @!visibility private
|
99
101
|
def self.thread_finalizer(array)
|
100
102
|
proc do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
Thread.new do # avoid error: can't be called from trap context
|
104
|
+
LOCK.synchronize do
|
105
|
+
# The thread which used this thread-local array is now gone
|
106
|
+
# So don't hold onto a reference to the array (thus blocking GC)
|
107
|
+
ARRAYS.delete(array.object_id)
|
108
|
+
end
|
105
109
|
end
|
106
110
|
end
|
107
111
|
end
|
@@ -11,7 +11,7 @@ module Concurrent
|
|
11
11
|
# Creates a thread local variable.
|
12
12
|
#
|
13
13
|
# @param [Object] default the default value when otherwise unset
|
14
|
-
# @param [Proc]
|
14
|
+
# @param [Proc] default_block Optional block that gets called to obtain the
|
15
15
|
# default value for each thread
|
16
16
|
|
17
17
|
# @!macro [new] thread_local_var_method_get
|
@@ -72,28 +72,28 @@ module Concurrent
|
|
72
72
|
# the current thread will ever see that change.
|
73
73
|
#
|
74
74
|
# @!macro thread_safe_variable_comparison
|
75
|
-
#
|
75
|
+
#
|
76
76
|
# @example
|
77
77
|
# v = ThreadLocalVar.new(14)
|
78
78
|
# v.value #=> 14
|
79
79
|
# v.value = 2
|
80
80
|
# v.value #=> 2
|
81
|
-
#
|
81
|
+
#
|
82
82
|
# @example
|
83
83
|
# v = ThreadLocalVar.new(14)
|
84
|
-
#
|
84
|
+
#
|
85
85
|
# t1 = Thread.new do
|
86
86
|
# v.value #=> 14
|
87
87
|
# v.value = 1
|
88
88
|
# v.value #=> 1
|
89
89
|
# end
|
90
|
-
#
|
90
|
+
#
|
91
91
|
# t2 = Thread.new do
|
92
92
|
# v.value #=> 14
|
93
93
|
# v.value = 2
|
94
94
|
# v.value #=> 2
|
95
95
|
# end
|
96
|
-
#
|
96
|
+
#
|
97
97
|
# v.value #=> 14
|
98
98
|
#
|
99
99
|
# @see https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html Java ThreadLocal
|
@@ -1 +1,2 @@
|
|
1
|
-
require '
|
1
|
+
require 'atomic'
|
2
|
+
require 'concurrent/atomic_reference/rbx'
|
@@ -10,11 +10,43 @@ require 'concurrent/utility/processor_counter'
|
|
10
10
|
module Concurrent
|
11
11
|
extend Concern::Logging
|
12
12
|
|
13
|
-
autoload :Options,
|
14
|
-
autoload :TimerSet,
|
13
|
+
autoload :Options, 'concurrent/options'
|
14
|
+
autoload :TimerSet, 'concurrent/executor/timer_set'
|
15
15
|
autoload :ThreadPoolExecutor, 'concurrent/executor/thread_pool_executor'
|
16
16
|
|
17
17
|
# @return [Logger] Logger with provided level and output.
|
18
|
+
def self.create_simple_logger(level = Logger::FATAL, output = $stderr)
|
19
|
+
# TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking
|
20
|
+
lambda do |severity, progname, message = nil, &block|
|
21
|
+
return false if severity < level
|
22
|
+
|
23
|
+
message = block ? block.call : message
|
24
|
+
formatted_message = case message
|
25
|
+
when String
|
26
|
+
message
|
27
|
+
when Exception
|
28
|
+
format "%s (%s)\n%s",
|
29
|
+
message.message, message.class, (message.backtrace || []).join("\n")
|
30
|
+
else
|
31
|
+
message.inspect
|
32
|
+
end
|
33
|
+
|
34
|
+
output.print format "[%s] %5s -- %s: %s\n",
|
35
|
+
Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'),
|
36
|
+
Logger::SEV_LABEL[severity],
|
37
|
+
progname,
|
38
|
+
formatted_message
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Use logger created by #create_simple_logger to log concurrent-ruby messages.
|
44
|
+
def self.use_simple_logger(level = Logger::FATAL, output = $stderr)
|
45
|
+
Concurrent.global_logger = create_simple_logger level, output
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Logger] Logger with provided level and output.
|
49
|
+
# @deprecated
|
18
50
|
def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr)
|
19
51
|
logger = Logger.new(output)
|
20
52
|
logger.level = level
|
@@ -24,32 +56,35 @@ module Concurrent
|
|
24
56
|
msg
|
25
57
|
when Exception
|
26
58
|
format "%s (%s)\n%s",
|
27
|
-
|
59
|
+
msg.message, msg.class, (msg.backtrace || []).join("\n")
|
28
60
|
else
|
29
61
|
msg.inspect
|
30
62
|
end
|
31
63
|
format "[%s] %5s -- %s: %s\n",
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
64
|
+
datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
|
65
|
+
severity,
|
66
|
+
progname,
|
67
|
+
formatted_message
|
36
68
|
end
|
37
69
|
|
38
70
|
lambda do |loglevel, progname, message = nil, &block|
|
39
|
-
|
71
|
+
logger.add loglevel, message, progname, &block
|
40
72
|
end
|
41
73
|
end
|
42
74
|
|
43
75
|
# Use logger created by #create_stdlib_logger to log concurrent-ruby messages.
|
76
|
+
# @deprecated
|
44
77
|
def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr)
|
45
78
|
Concurrent.global_logger = create_stdlib_logger level, output
|
46
79
|
end
|
47
80
|
|
81
|
+
# TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods
|
82
|
+
|
48
83
|
# Suppresses all output when used for logging.
|
49
84
|
NULL_LOGGER = lambda { |level, progname, message = nil, &block| }
|
50
85
|
|
51
86
|
# @!visibility private
|
52
|
-
GLOBAL_LOGGER = AtomicReference.new(
|
87
|
+
GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN))
|
53
88
|
private_constant :GLOBAL_LOGGER
|
54
89
|
|
55
90
|
def self.global_logger
|
@@ -131,23 +166,23 @@ module Concurrent
|
|
131
166
|
|
132
167
|
def self.new_fast_executor(opts = {})
|
133
168
|
FixedThreadPool.new(
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
169
|
+
[2, Concurrent.processor_count].max,
|
170
|
+
auto_terminate: opts.fetch(:auto_terminate, true),
|
171
|
+
idletime: 60, # 1 minute
|
172
|
+
max_queue: 0, # unlimited
|
173
|
+
fallback_policy: :abort # shouldn't matter -- 0 max queue
|
139
174
|
)
|
140
175
|
end
|
141
176
|
|
142
177
|
def self.new_io_executor(opts = {})
|
143
178
|
ThreadPoolExecutor.new(
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
179
|
+
min_threads: [2, Concurrent.processor_count].max,
|
180
|
+
max_threads: ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE,
|
181
|
+
# max_threads: 1000,
|
182
|
+
auto_terminate: opts.fetch(:auto_terminate, true),
|
183
|
+
idletime: 60, # 1 minute
|
184
|
+
max_queue: 0, # unlimited
|
185
|
+
fallback_policy: :abort # shouldn't matter -- 0 max queue
|
151
186
|
)
|
152
187
|
end
|
153
188
|
end
|
data/lib/concurrent/errors.rb
CHANGED
@@ -30,7 +30,18 @@ module Concurrent
|
|
30
30
|
|
31
31
|
# Raised when an attempt is made to modify an immutable object
|
32
32
|
# (such as an `IVar`) after its final state has been set.
|
33
|
-
MultipleAssignmentError
|
33
|
+
class MultipleAssignmentError < Error
|
34
|
+
attr_reader :inspection_data
|
35
|
+
|
36
|
+
def initialize(message = nil, inspection_data = nil)
|
37
|
+
@inspection_data = inspection_data
|
38
|
+
super message
|
39
|
+
end
|
40
|
+
|
41
|
+
def inspect
|
42
|
+
format '%s %s>', super[0..-2], @inspection_data.inspect
|
43
|
+
end
|
44
|
+
end
|
34
45
|
|
35
46
|
# Raised by an `Executor` when it is unable to process a given task,
|
36
47
|
# possibly because of a reject policy or other internal error.
|
@@ -43,4 +54,16 @@ module Concurrent
|
|
43
54
|
# Raised when an operation times out.
|
44
55
|
TimeoutError = Class.new(Error)
|
45
56
|
|
57
|
+
# Aggregates multiple exceptions.
|
58
|
+
class MultipleErrors < Error
|
59
|
+
attr_reader :errors
|
60
|
+
|
61
|
+
def initialize(errors, message = "#{errors.size} errors")
|
62
|
+
@errors = errors
|
63
|
+
super [*message,
|
64
|
+
*errors.map { |e| [format('%s (%s)', e.message, e.class), *e.backtrace] }.flatten(1)
|
65
|
+
].join("\n")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
46
69
|
end
|
@@ -70,8 +70,8 @@ module Concurrent
|
|
70
70
|
# any instance variables with CamelCase names and isn't {.safe_initialization?}.
|
71
71
|
def self.ensure_safe_initialization_when_final_fields_are_present
|
72
72
|
Object.class_eval do
|
73
|
-
def self.new(*)
|
74
|
-
object = super
|
73
|
+
def self.new(*args, &block)
|
74
|
+
object = super(*args, &block)
|
75
75
|
ensure
|
76
76
|
has_final_field = object.instance_variables.any? { |v| v.to_s =~ /^@[A-Z]/ }
|
77
77
|
if has_final_field && !safe_initialization?
|
data/lib/concurrent/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concurrent-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
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: 2016-12-
|
13
|
+
date: 2016-12-27 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: |
|
16
16
|
Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
|