concurrent-ruby 1.1.3 → 1.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -0
- data/Gemfile +11 -8
- data/{LICENSE.md → LICENSE.txt} +18 -20
- data/README.md +42 -7
- data/Rakefile +50 -48
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +9 -8
- data/lib/{concurrent-ruby.rb → concurrent-ruby/concurrent-ruby.rb} +0 -0
- data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +9 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +23 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_reference.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +57 -40
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +13 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +17 -23
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +16 -12
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +15 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +20 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +13 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +12 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +348 -117
- data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +5 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +13 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +46 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/truffleruby_object.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/data_structures.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -0
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- metadata +129 -129
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/utility/at_exit.rb +0 -97
- data/lib/concurrent/version.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3db57904f9a4906ae01e04d1873aa824992ed1b4258d2b2523ba5ea0ca86b17f
|
4
|
+
data.tar.gz: d8bfd56f2c29b311e528754ee1db476ecbb6387ac7f05a63bb5e395877379452
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b76f7f31795dce80951ea7b5231d919aa28384d04fe6591c43e310774450f16b074ce5536ef218fd2475f5413cdf0c9409bc1d3542b19b78146cc5375c30a603
|
7
|
+
data.tar.gz: 9bb9d431f6995bdec6e7ed6c6323f72ac0cc713d71072115c0dfcefb6ccb42c8b5b703bf34049071bebf4e0686dce2e28cc44865329884785eae8a6a2eabd060
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,56 @@
|
|
1
1
|
## Current
|
2
2
|
|
3
|
+
## Release v1.1.7 (6 August 2020)
|
4
|
+
|
5
|
+
concurrent-ruby:
|
6
|
+
|
7
|
+
* (#879) Consider falsy value on `Concurrent::Map#compute_if_absent` for fast non-blocking path
|
8
|
+
* (#876) Reset Async queue on forking, makes Async fork-safe
|
9
|
+
* (#856) Avoid running problematic code in RubyThreadLocalVar on MRI that occasionally results in segfault
|
10
|
+
* (#853) Introduce ThreadPoolExecutor without a Queue
|
11
|
+
|
12
|
+
## Release v1.1.6, edge v0.6.0 (10 Feb 2020)
|
13
|
+
|
14
|
+
concurrent-ruby:
|
15
|
+
|
16
|
+
* (#841) Concurrent.disable_at_exit_handlers! is no longer needed and was deprecated.
|
17
|
+
* (#841) AbstractExecutorService#auto_terminate= was deprecated and has no effect.
|
18
|
+
Set :auto_terminate option instead when executor is initialized.
|
19
|
+
|
20
|
+
## Release v1.1.6.pre1, edge v0.6.0.pre1 (26 Jan 2020)
|
21
|
+
|
22
|
+
concurrent-ruby:
|
23
|
+
|
24
|
+
* (#828) Allow to name executors, the name is also used to name their threads
|
25
|
+
* (#838) Implement #dup and #clone for structs
|
26
|
+
* (#821) Safer finalizers for thread local variables
|
27
|
+
* Documentation fixes
|
28
|
+
* (#814) Use Ruby's Etc.nprocessors if available
|
29
|
+
* (#812) Fix directory structure not to mess with packaging tools
|
30
|
+
* (#840) Fix termination of pools on JRuby
|
31
|
+
|
32
|
+
concurrent-ruby-edge:
|
33
|
+
|
34
|
+
* Add WrappingExecutor (#830)
|
35
|
+
|
36
|
+
## Release v1.1.5, edge v0.5.0 (10 Mar 2019)
|
37
|
+
|
38
|
+
concurrent-ruby:
|
39
|
+
|
40
|
+
* fix potential leak of context on JRuby and Java 7
|
41
|
+
|
42
|
+
concurrent-ruby-edge:
|
43
|
+
|
44
|
+
* Add finalized Concurrent::Cancellation
|
45
|
+
* Add finalized Concurrent::Throttle
|
46
|
+
* Add finalized Concurrent::Promises::Channel
|
47
|
+
* Add new Concurrent::ErlangActor
|
48
|
+
|
49
|
+
## Release v1.1.4 (14 Dec 2018)
|
50
|
+
|
51
|
+
* (#780) Remove java_alias of 'submit' method of Runnable to let executor service work on java 11
|
52
|
+
* (#776) Fix NameError on defining a struct with a name which is already taken in an ancestor
|
53
|
+
|
3
54
|
## Release v1.1.3 (7 Nov 2018)
|
4
55
|
|
5
56
|
* (#775) fix partial require of the gem (although not officially supported)
|
data/Gemfile
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__
|
3
|
+
require File.join(File.dirname(__FILE__), 'lib/concurrent-ruby/concurrent/version')
|
4
|
+
require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby-edge/concurrent/edge/version')
|
5
|
+
require File.join(File.dirname(__FILE__ ), 'lib/concurrent-ruby/concurrent/utility/engine')
|
4
6
|
|
5
7
|
no_path = ENV['NO_PATH']
|
6
8
|
options = no_path ? {} : { path: '.' }
|
@@ -10,27 +12,28 @@ gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options
|
|
10
12
|
gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
|
11
13
|
|
12
14
|
group :development do
|
13
|
-
gem 'rake', '~> 12.0'
|
14
|
-
gem 'rake-compiler', '~> 1.0'
|
15
|
-
gem 'rake-compiler-dock', '~>
|
15
|
+
gem 'rake', (Concurrent.ruby_version :<, 2, 2, 0) ? '~> 12.0' : '~> 13.0'
|
16
|
+
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
|
17
|
+
gem 'rake-compiler-dock', '~> 1.0'
|
16
18
|
gem 'pry', '~> 0.11', platforms: :mri
|
17
19
|
end
|
18
20
|
|
19
21
|
group :documentation, optional: true do
|
20
|
-
gem 'yard', '~> 0.9.0', :
|
22
|
+
gem 'yard', '~> 0.9.0', require: false
|
21
23
|
gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
|
22
|
-
gem 'md-ruby-eval', '~> 0.
|
24
|
+
gem 'md-ruby-eval', '~> 0.6'
|
23
25
|
end
|
24
26
|
|
25
27
|
group :testing do
|
26
28
|
gem 'rspec', '~> 3.7'
|
27
29
|
gem 'timecop', '~> 0.7.4'
|
30
|
+
gem 'sigdump', require: false
|
28
31
|
end
|
29
32
|
|
30
33
|
# made opt-in since it will not install on jruby 1.7
|
31
34
|
group :coverage, optional: !ENV['COVERAGE'] do
|
32
|
-
gem 'simplecov', '~> 0.
|
33
|
-
gem 'coveralls', '~> 0.8.2', :
|
35
|
+
gem 'simplecov', '~> 0.16.0', require: false
|
36
|
+
gem 'coveralls', '~> 0.8.2', require: false
|
34
37
|
end
|
35
38
|
|
36
39
|
group :benchmarks, optional: true do
|
data/{LICENSE.md → LICENSE.txt}
RENAMED
@@ -1,23 +1,21 @@
|
|
1
|
-
```
|
2
1
|
Copyright (c) Jerry D'Antonio -- released under the MIT license.
|
3
2
|
|
4
|
-
http://www.opensource.org/licenses/mit-license.php
|
3
|
+
http://www.opensource.org/licenses/mit-license.php
|
5
4
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
-
of this software and associated documentation files (the "Software"), to deal
|
8
|
-
in the Software without restriction, including without limitation the rights
|
9
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
-
copies of the Software, and to permit persons to whom the Software is
|
11
|
-
furnished to do so, subject to the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be included in
|
14
|
-
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
|
23
|
-
```
|
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 all
|
13
|
+
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 THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -42,8 +42,8 @@ appreciate your help. Would you like to contribute? Great! Have a look at
|
|
42
42
|
## Thread Safety
|
43
43
|
|
44
44
|
*Concurrent Ruby makes one of the strongest thread safety guarantees of any Ruby concurrency
|
45
|
-
library, providing consistent behavior and guarantees on all
|
46
|
-
(MRI/CRuby, JRuby,
|
45
|
+
library, providing consistent behavior and guarantees on all four of the main Ruby interpreters
|
46
|
+
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).*
|
47
47
|
|
48
48
|
Every abstraction in this library is thread safe. Specific thread safety guarantees are documented
|
49
49
|
with each abstraction.
|
@@ -59,7 +59,7 @@ Concurrent Ruby is also the only Ruby library which provides a full suite of thr
|
|
59
59
|
immutable variable types and data structures.
|
60
60
|
|
61
61
|
We've also initiated discussion to document [memory model](docs-source/synchronization.md) of Ruby which
|
62
|
-
would provide consistent behaviour and guarantees on all
|
62
|
+
would provide consistent behaviour and guarantees on all four of the main Ruby interpreters
|
63
63
|
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).
|
64
64
|
|
65
65
|
## Features & Documentation
|
@@ -105,9 +105,9 @@ We also have a [IRC (gitter)](https://gitter.im/ruby-concurrency/concurrent-ruby
|
|
105
105
|
Collection classes that were originally part of the (deprecated) `thread_safe` gem:
|
106
106
|
|
107
107
|
* [Array](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Array.html) A thread-safe
|
108
|
-
subclass of Ruby's standard [Array](http://ruby-doc.org/core
|
108
|
+
subclass of Ruby's standard [Array](http://ruby-doc.org/core/Array.html).
|
109
109
|
* [Hash](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Hash.html) A thread-safe
|
110
|
-
subclass of Ruby's standard [Hash](http://ruby-doc.org/core
|
110
|
+
subclass of Ruby's standard [Hash](http://ruby-doc.org/core/Hash.html).
|
111
111
|
* [Set](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Set.html) A thread-safe
|
112
112
|
subclass of Ruby's standard [Set](http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html).
|
113
113
|
* [Map](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Map.html) A hash-like object
|
@@ -122,7 +122,7 @@ Value objects inspired by other languages:
|
|
122
122
|
immutable object representing an optional value, based on
|
123
123
|
[Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
|
124
124
|
|
125
|
-
Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core
|
125
|
+
Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core/Struct.html):
|
126
126
|
|
127
127
|
* [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ImmutableStruct.html)
|
128
128
|
Immutable struct where values are set at construction and cannot be changed later.
|
@@ -224,6 +224,38 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
|
|
224
224
|
*Status: will be moved to core soon.*
|
225
225
|
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LockFreeStack.html)
|
226
226
|
*Status: missing documentation and tests.*
|
227
|
+
* [Promises::Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises/Channel.html)
|
228
|
+
A first in first out channel that accepts messages with push family of methods and returns
|
229
|
+
messages with pop family of methods.
|
230
|
+
Pop and push operations can be represented as futures, see `#pop_op` and `#push_op`.
|
231
|
+
The capacity of the channel can be limited to support back pressure, use capacity option in `#initialize`.
|
232
|
+
`#pop` method blocks ans `#pop_op` returns pending future if there is no message in the channel.
|
233
|
+
If the capacity is limited the `#push` method blocks and `#push_op` returns pending future.
|
234
|
+
* [Cancellation](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html)
|
235
|
+
The Cancellation abstraction provides cooperative cancellation.
|
236
|
+
|
237
|
+
The standard methods `Thread#raise` of `Thread#kill` available in Ruby
|
238
|
+
are very dangerous (see linked the blog posts bellow).
|
239
|
+
Therefore concurrent-ruby provides an alternative.
|
240
|
+
|
241
|
+
* <https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/>
|
242
|
+
* <http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/>
|
243
|
+
* <http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html>
|
244
|
+
|
245
|
+
It provides an object which represents a task which can be executed,
|
246
|
+
the task has to get the reference to the object and periodically cooperatively check that it is not cancelled.
|
247
|
+
Good practices to make tasks cancellable:
|
248
|
+
* check cancellation every cycle of a loop which does significant work,
|
249
|
+
* do all blocking actions in a loop with a timeout then on timeout check cancellation
|
250
|
+
and if ok block again with the timeout
|
251
|
+
* [Throttle](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Throttle.html)
|
252
|
+
A tool managing concurrency level of tasks.
|
253
|
+
* [ErlangActor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ErlangActor.html)
|
254
|
+
Actor implementation which precisely matches Erlang actor behaviour.
|
255
|
+
Requires at least Ruby 2.1 otherwise it's not loaded.
|
256
|
+
* [WrappingExecutor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/WrappingExecutor.html)
|
257
|
+
A delegating executor which modifies each task before the task is given to
|
258
|
+
the target executor it delegates to.
|
227
259
|
|
228
260
|
## Supported Ruby versions
|
229
261
|
|
@@ -339,11 +371,14 @@ and to the past maintainers
|
|
339
371
|
* [Paweł Obrok](https://github.com/obrok)
|
340
372
|
* [Lucas Allan](https://github.com/lucasallan)
|
341
373
|
|
374
|
+
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
|
375
|
+
["Enhancing Ruby’s concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
|
376
|
+
|
342
377
|
## License and Copyright
|
343
378
|
|
344
379
|
*Concurrent Ruby* is free software released under the
|
345
380
|
[MIT License](http://www.opensource.org/licenses/MIT).
|
346
381
|
|
347
|
-
The *Concurrent Ruby* [logo](https://
|
382
|
+
The *Concurrent Ruby* [logo](https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png) was
|
348
383
|
designed by [David Jones](https://twitter.com/zombyboy). It is Copyright © 2014
|
349
384
|
[Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.
|
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require_relative 'lib/concurrent/
|
4
|
-
require_relative 'lib/concurrent/utility/engine'
|
1
|
+
require_relative 'lib/concurrent-ruby/concurrent/version'
|
2
|
+
require_relative 'lib/concurrent-ruby-edge/concurrent/edge/version'
|
3
|
+
require_relative 'lib/concurrent-ruby/concurrent/utility/engine'
|
5
4
|
|
6
5
|
if Concurrent.ruby_version :<, 2, 0, 0
|
7
6
|
# @!visibility private
|
@@ -18,31 +17,11 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.
|
|
18
17
|
|
19
18
|
require 'rake/javaextensiontask'
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
class ConcurrentRubyJavaExtensionTask < Rake::JavaExtensionTask
|
24
|
-
def java_classpath_arg(*args)
|
25
|
-
jruby_cpath = nil
|
26
|
-
if RUBY_PLATFORM =~ /java/
|
27
|
-
begin
|
28
|
-
cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR)
|
29
|
-
cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR)
|
30
|
-
jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR)
|
31
|
-
rescue => e
|
32
|
-
end
|
33
|
-
end
|
34
|
-
unless jruby_cpath
|
35
|
-
jruby_cpath = JRUBY_JAR_PATH
|
36
|
-
raise "#{jruby_cpath} does not exist" unless File.exist? jruby_cpath
|
37
|
-
end
|
38
|
-
jruby_cpath += File::PATH_SEPARATOR + args.join(File::PATH_SEPARATOR) unless args.empty?
|
39
|
-
jruby_cpath ? "-cp \"#{jruby_cpath}\"" : ""
|
40
|
-
end
|
41
|
-
end
|
20
|
+
ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && !Concurrent.on_jruby?
|
42
21
|
|
43
|
-
|
22
|
+
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
44
23
|
ext.ext_dir = 'ext/concurrent-ruby'
|
45
|
-
ext.lib_dir = 'lib/concurrent'
|
24
|
+
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
46
25
|
end
|
47
26
|
|
48
27
|
unless Concurrent.on_jruby?
|
@@ -50,7 +29,7 @@ unless Concurrent.on_jruby?
|
|
50
29
|
|
51
30
|
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
|
52
31
|
ext.ext_dir = 'ext/concurrent-ruby-ext'
|
53
|
-
ext.lib_dir = 'lib/concurrent'
|
32
|
+
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
54
33
|
ext.source_pattern = '*.{c,h}'
|
55
34
|
|
56
35
|
ext.cross_compile = true
|
@@ -63,10 +42,14 @@ namespace :repackage do
|
|
63
42
|
desc '* with Windows fat distributions'
|
64
43
|
task :all do
|
65
44
|
Dir.chdir(__dir__) do
|
45
|
+
# store gems in vendor cache for docker
|
66
46
|
sh 'bundle package'
|
67
|
-
|
68
|
-
|
69
|
-
|
47
|
+
|
48
|
+
# build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
|
49
|
+
Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
|
50
|
+
|
51
|
+
# build all gem files
|
52
|
+
RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
|
70
53
|
end
|
71
54
|
end
|
72
55
|
end
|
@@ -78,7 +61,7 @@ Gem::PackageTask.new(core_gemspec) {} if core_gemspec
|
|
78
61
|
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby?
|
79
62
|
Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
|
80
63
|
|
81
|
-
CLEAN.include('lib/concurrent/2.*', 'lib/concurrent/*.jar')
|
64
|
+
CLEAN.include('lib/concurrent-ruby/concurrent/2.*', 'lib/concurrent-ruby/concurrent/*.jar')
|
82
65
|
|
83
66
|
begin
|
84
67
|
require 'rspec'
|
@@ -86,15 +69,14 @@ begin
|
|
86
69
|
|
87
70
|
RSpec::Core::RakeTask.new(:spec)
|
88
71
|
|
89
|
-
options = %w[ --color
|
90
|
-
--backtrace
|
91
|
-
--seed 1
|
92
|
-
--format documentation
|
93
|
-
--tag ~notravis ]
|
94
|
-
|
95
72
|
namespace :spec do
|
96
73
|
desc '* Configured for ci'
|
97
74
|
RSpec::Core::RakeTask.new(:ci) do |t|
|
75
|
+
options = %w[ --color
|
76
|
+
--backtrace
|
77
|
+
--order defined
|
78
|
+
--format documentation
|
79
|
+
--tag ~notravis ]
|
98
80
|
t.rspec_opts = [*options].join(' ')
|
99
81
|
end
|
100
82
|
|
@@ -119,7 +101,7 @@ rescue LoadError => e
|
|
119
101
|
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
|
120
102
|
end
|
121
103
|
|
122
|
-
current_yard_version_name = Concurrent::VERSION
|
104
|
+
current_yard_version_name = Concurrent::VERSION
|
123
105
|
|
124
106
|
begin
|
125
107
|
require 'yard'
|
@@ -169,22 +151,34 @@ begin
|
|
169
151
|
end
|
170
152
|
|
171
153
|
define_yard_task = -> name do
|
154
|
+
output_dir = "docs/#{name}"
|
155
|
+
|
156
|
+
removal_name = "remove.#{name}"
|
157
|
+
task removal_name do
|
158
|
+
Dir.chdir __dir__ do
|
159
|
+
FileUtils.rm_rf output_dir
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
172
163
|
desc "* of #{name} into subdir #{name}"
|
173
164
|
YARD::Rake::YardocTask.new(name) do |yard|
|
174
165
|
yard.options.push(
|
175
|
-
'--output-dir',
|
166
|
+
'--output-dir', output_dir,
|
176
167
|
'--main', 'tmp/README.md',
|
177
168
|
*common_yard_options)
|
178
|
-
yard.files = ['./lib/**/*.rb',
|
179
|
-
'./lib-edge/**/*.rb',
|
169
|
+
yard.files = ['./lib/concurrent-ruby/**/*.rb',
|
170
|
+
'./lib/concurrent-ruby-edge/**/*.rb',
|
180
171
|
'./ext/concurrent_ruby_ext/**/*.c',
|
181
172
|
'-',
|
182
173
|
'docs-source/thread_pools.md',
|
183
174
|
'docs-source/promises.out.md',
|
184
|
-
'
|
175
|
+
'docs-source/medium-example.out.rb',
|
176
|
+
'LICENSE.txt',
|
185
177
|
'CHANGELOG.md']
|
186
178
|
end
|
187
|
-
Rake::Task[name].prerequisites.push
|
179
|
+
Rake::Task[name].prerequisites.push removal_name,
|
180
|
+
# 'yard:eval_md',
|
181
|
+
'yard:update_readme'
|
188
182
|
end
|
189
183
|
|
190
184
|
define_yard_task.call current_yard_version_name
|
@@ -207,7 +201,15 @@ begin
|
|
207
201
|
begin
|
208
202
|
FileUtils.cp_r 'docs', 'docs-copy', verbose: true
|
209
203
|
Rake::Task["yard:#{name}"].invoke
|
210
|
-
sh 'diff -r docs/ docs-copy/'
|
204
|
+
sh 'diff -r docs/ docs-copy/' do |ok, res|
|
205
|
+
unless ok
|
206
|
+
begin
|
207
|
+
STDOUT.puts 'Command failed. Continue? (y/n)'
|
208
|
+
input = STDIN.gets.strip.downcase
|
209
|
+
end until %w(y n).include?(input)
|
210
|
+
exit 1 if input == 'n'
|
211
|
+
end
|
212
|
+
end
|
211
213
|
ensure
|
212
214
|
FileUtils.rm_rf 'docs-copy', verbose: true
|
213
215
|
end
|
@@ -230,8 +232,8 @@ task :release => ['release:checks', 'release:build', 'release:test', 'release:pu
|
|
230
232
|
namespace :release do
|
231
233
|
# Depends on environment of @pitr-ch
|
232
234
|
|
233
|
-
mri_version = '2.5
|
234
|
-
jruby_version = 'jruby-9.
|
235
|
+
mri_version = '2.6.5'
|
236
|
+
jruby_version = 'jruby-9.2.9.0'
|
235
237
|
|
236
238
|
task :checks => "yard:#{current_yard_version_name}:uptodate" do
|
237
239
|
Dir.chdir(__dir__) do
|
@@ -259,7 +261,7 @@ namespace :release do
|
|
259
261
|
end
|
260
262
|
|
261
263
|
desc '* build all *.gem files necessary for release'
|
262
|
-
task :build => 'repackage:all'
|
264
|
+
task :build => [:clobber, 'repackage:all']
|
263
265
|
|
264
266
|
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
|
265
267
|
task :test do
|
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
|
|
23
23
|
public class SynchronizationLibrary implements Library {
|
24
24
|
|
25
25
|
private static final Unsafe UNSAFE = loadUnsafe();
|
26
|
+
private static final boolean FULL_FENCE = supportsFences();
|
26
27
|
|
27
28
|
private static Unsafe loadUnsafe() {
|
28
29
|
try {
|
@@ -140,17 +141,17 @@ public class SynchronizationLibrary implements Library {
|
|
140
141
|
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
|
141
142
|
// on volatile fields. any volatile field could have been used but using the thread context is an
|
142
143
|
// attempt to avoid code elimination.
|
143
|
-
private static volatile
|
144
|
+
private static volatile int volatileField;
|
144
145
|
|
145
146
|
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
|
146
147
|
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject self) {
|
147
148
|
// Prevent reordering of ivar writes with publication of this instance
|
148
|
-
if (!
|
149
|
+
if (!FULL_FENCE) {
|
149
150
|
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
|
150
151
|
// If it's eliminated it'll cause problems only on non-x86 platforms.
|
151
152
|
// http://shipilev.net/blog/2014/jmm-pragmatics/#_happens_before_test_your_understanding
|
152
|
-
final
|
153
|
-
|
153
|
+
final int volatileRead = volatileField;
|
154
|
+
volatileField = context.getLine();
|
154
155
|
} else {
|
155
156
|
UNSAFE.fullFence();
|
156
157
|
}
|
@@ -163,9 +164,9 @@ public class SynchronizationLibrary implements Library {
|
|
163
164
|
IRubyObject self,
|
164
165
|
IRubyObject name) {
|
165
166
|
// Ensure we ses latest value with loadFence
|
166
|
-
if (!
|
167
|
+
if (!FULL_FENCE) {
|
167
168
|
// piggybacking on volatile read, simulating loadFence
|
168
|
-
final
|
169
|
+
final int volatileRead = volatileField;
|
169
170
|
return ((RubyBasicObject) self).instance_variable_get(context, name);
|
170
171
|
} else {
|
171
172
|
UNSAFE.loadFence();
|
@@ -180,10 +181,10 @@ public class SynchronizationLibrary implements Library {
|
|
180
181
|
IRubyObject name,
|
181
182
|
IRubyObject value) {
|
182
183
|
// Ensure we make last update visible
|
183
|
-
if (!
|
184
|
+
if (!FULL_FENCE) {
|
184
185
|
// piggybacking on volatile write, simulating storeFence
|
185
186
|
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
|
186
|
-
|
187
|
+
volatileField = context.getLine();
|
187
188
|
return result;
|
188
189
|
} else {
|
189
190
|
// JRuby uses StampedVariableAccessor which calls fullFence
|