concurrent-ruby 1.1.6 → 1.1.7

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
  SHA256:
3
- metadata.gz: 649de1a5e5c7c82652bd6ad21496f2c1061d7c75517271d8ca30c3ceb9c49038
4
- data.tar.gz: 6274d2cd2dcda660a1e34436547eca26d6c74d03e9a527d7ce5d1a9f3f72f4be
3
+ metadata.gz: 3db57904f9a4906ae01e04d1873aa824992ed1b4258d2b2523ba5ea0ca86b17f
4
+ data.tar.gz: d8bfd56f2c29b311e528754ee1db476ecbb6387ac7f05a63bb5e395877379452
5
5
  SHA512:
6
- metadata.gz: 2adbf28bdf7034295709496964e8e70d22f59bf058bf18ca005c2ce536627160538de6c510ea1f39893de0ad90b2fb50d6f35c848c97f58bd8f71ff8d9e57fc2
7
- data.tar.gz: 1cbc384488e0f70d19d742e54c34dbd7abfaffe89f75230b2f5b80d2ae4d161b731666ce6b64e8f5adeb561b6d32191ce6bd679e05d6bd9eec91b869ee379b2f
6
+ metadata.gz: b76f7f31795dce80951ea7b5231d919aa28384d04fe6591c43e310774450f16b074ce5536ef218fd2475f5413cdf0c9409bc1d3542b19b78146cc5375c30a603
7
+ data.tar.gz: 9bb9d431f6995bdec6e7ed6c6323f72ac0cc713d71072115c0dfcefb6ccb42c8b5b703bf34049071bebf4e0686dce2e28cc44865329884785eae8a6a2eabd060
@@ -1,5 +1,14 @@
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
+
3
12
  ## Release v1.1.6, edge v0.6.0 (10 Feb 2020)
4
13
 
5
14
  concurrent-ruby:
data/Gemfile CHANGED
@@ -14,7 +14,7 @@ gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
14
14
  group :development do
15
15
  gem 'rake', (Concurrent.ruby_version :<, 2, 2, 0) ? '~> 12.0' : '~> 13.0'
16
16
  gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
17
- gem 'rake-compiler-dock', '~> 0.7.0'
17
+ gem 'rake-compiler-dock', '~> 1.0'
18
18
  gem 'pry', '~> 0.11', platforms: :mri
19
19
  end
20
20
 
@@ -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
- all copies or substantial portions of the Software.
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
- THE SOFTWARE.
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
@@ -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-2.2.0/Array.html).
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-2.2.0/Hash.html).
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-2.2.0/Struct.html):
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.
data/Rakefile CHANGED
@@ -173,7 +173,7 @@ begin
173
173
  'docs-source/thread_pools.md',
174
174
  'docs-source/promises.out.md',
175
175
  'docs-source/medium-example.out.rb',
176
- 'LICENSE.md',
176
+ 'LICENSE.txt',
177
177
  'CHANGELOG.md']
178
178
  end
179
179
  Rake::Task[name].prerequisites.push removal_name,
@@ -16,7 +16,7 @@ module Concurrent
16
16
  # operation therefore when two `+=` operations are executed concurrently updates
17
17
  # may be lost. Use `#concat` instead.
18
18
  #
19
- # @see http://ruby-doc.org/core-2.2.0/Array.html Ruby standard library `Array`
19
+ # @see http://ruby-doc.org/core/Array.html Ruby standard library `Array`
20
20
 
21
21
  # @!macro internal_implementation_note
22
22
  ArrayImplementation = case
@@ -58,26 +58,6 @@ module Concurrent
58
58
  # end
59
59
  # ```
60
60
  #
61
- # When defining a constructor it is critical that the first line be a call to
62
- # `super` with no arguments. The `super` method initializes the background
63
- # thread and other asynchronous components.
64
- #
65
- # ```
66
- # class BackgroundLogger
67
- # include Concurrent::Async
68
- #
69
- # def initialize(level)
70
- # super()
71
- # @logger = Logger.new(STDOUT)
72
- # @logger.level = level
73
- # end
74
- #
75
- # def info(msg)
76
- # @logger.info(msg)
77
- # end
78
- # end
79
- # ```
80
- #
81
61
  # Mixing this module into a class provides each object two proxy methods:
82
62
  # `async` and `await`. These methods are thread safe with respect to the
83
63
  # enclosing object. The former proxy allows methods to be called
@@ -309,6 +289,7 @@ module Concurrent
309
289
  @delegate = delegate
310
290
  @queue = []
311
291
  @executor = Concurrent.global_io_executor
292
+ @ruby_pid = $$
312
293
  end
313
294
 
314
295
  # Delegates method calls to the wrapped object.
@@ -326,6 +307,7 @@ module Concurrent
326
307
 
327
308
  ivar = Concurrent::IVar.new
328
309
  synchronize do
310
+ reset_if_forked
329
311
  @queue.push [ivar, method, args, block]
330
312
  @executor.post { perform } if @queue.length == 1
331
313
  end
@@ -361,6 +343,13 @@ module Concurrent
361
343
  end
362
344
  end
363
345
  end
346
+
347
+ def reset_if_forked
348
+ if $$ != @ruby_pid
349
+ @queue.clear
350
+ @ruby_pid = $$
351
+ end
352
+ end
364
353
  end
365
354
  private_constant :AsyncDelegator
366
355
 
@@ -28,38 +28,27 @@ module Concurrent
28
28
  # But when a Thread is GC'd, we need to drop the reference to its thread-local
29
29
  # array, so we don't leak memory
30
30
 
31
- # @!visibility private
32
- FREE = []
33
- LOCK = Mutex.new
34
- ARRAYS = {} # used as a hash set
35
- # noinspection RubyClassVariableUsageInspection
36
- @@next = 0
37
- QUEUE = Queue.new
38
- THREAD = Thread.new do
39
- while true
40
- method, i = QUEUE.pop
41
- case method
42
- when :thread_local_finalizer
43
- LOCK.synchronize do
44
- FREE.push(i)
45
- # The cost of GC'ing a TLV is linear in the number of threads using TLVs
46
- # But that is natural! More threads means more storage is used per TLV
47
- # So naturally more CPU time is required to free more storage
48
- ARRAYS.each_value do |array|
49
- array[i] = nil
50
- end
51
- end
52
- when :thread_finalizer
53
- LOCK.synchronize do
54
- # The thread which used this thread-local array is now gone
55
- # So don't hold onto a reference to the array (thus blocking GC)
56
- ARRAYS.delete(i)
57
- end
58
- end
31
+ FREE = []
32
+ LOCK = Mutex.new
33
+ THREAD_LOCAL_ARRAYS = {} # used as a hash set
34
+
35
+ # synchronize when not on MRI
36
+ # on MRI using lock in finalizer leads to "can't be called from trap context" error
37
+ # so the code is carefully written to be tread-safe on MRI relying on GIL
38
+
39
+ if Concurrent.on_cruby?
40
+ # @!visibility private
41
+ def self.semi_sync(&block)
42
+ block.call
43
+ end
44
+ else
45
+ # @!visibility private
46
+ def self.semi_sync(&block)
47
+ LOCK.synchronize(&block)
59
48
  end
60
49
  end
61
50
 
62
- private_constant :FREE, :LOCK, :ARRAYS, :QUEUE, :THREAD
51
+ private_constant :FREE, :LOCK, :THREAD_LOCAL_ARRAYS
63
52
 
64
53
  # @!macro thread_local_var_method_get
65
54
  def value
@@ -85,7 +74,7 @@ module Concurrent
85
74
  # Using Ruby's built-in thread-local storage is faster
86
75
  unless (array = get_threadlocal_array(me))
87
76
  array = set_threadlocal_array([], me)
88
- LOCK.synchronize { ARRAYS[array.object_id] = array }
77
+ self.class.semi_sync { THREAD_LOCAL_ARRAYS[array.object_id] = array }
89
78
  ObjectSpace.define_finalizer(me, self.class.thread_finalizer(array.object_id))
90
79
  end
91
80
  array[@index] = (value.nil? ? NULL : value)
@@ -95,32 +84,50 @@ module Concurrent
95
84
  protected
96
85
 
97
86
  # @!visibility private
98
- # noinspection RubyClassVariableUsageInspection
99
87
  def allocate_storage
100
- @index = LOCK.synchronize do
101
- FREE.pop || begin
102
- result = @@next
103
- @@next += 1
104
- result
105
- end
106
- end
88
+ @index = FREE.pop || next_index
89
+
107
90
  ObjectSpace.define_finalizer(self, self.class.thread_local_finalizer(@index))
108
91
  end
109
92
 
110
93
  # @!visibility private
111
94
  def self.thread_local_finalizer(index)
112
- # avoid error: can't be called from trap context
113
- proc { QUEUE.push [:thread_local_finalizer, index] }
95
+ proc do
96
+ semi_sync do
97
+ # The cost of GC'ing a TLV is linear in the number of threads using TLVs
98
+ # But that is natural! More threads means more storage is used per TLV
99
+ # So naturally more CPU time is required to free more storage
100
+ THREAD_LOCAL_ARRAYS.each_value { |array| array[index] = nil }
101
+ # free index has to be published after the arrays are cleared
102
+ FREE.push(index)
103
+ end
104
+ end
114
105
  end
115
106
 
116
107
  # @!visibility private
117
108
  def self.thread_finalizer(id)
118
- # avoid error: can't be called from trap context
119
- proc { QUEUE.push [:thread_finalizer, id] }
109
+ proc do
110
+ semi_sync do
111
+ # The thread which used this thread-local array is now gone
112
+ # So don't hold onto a reference to the array (thus blocking GC)
113
+ THREAD_LOCAL_ARRAYS.delete(id)
114
+ end
115
+ end
120
116
  end
121
117
 
122
118
  private
123
119
 
120
+ # noinspection RubyClassVariableUsageInspection
121
+ @@next = 0
122
+ # noinspection RubyClassVariableUsageInspection
123
+ def next_index
124
+ LOCK.synchronize do
125
+ result = @@next
126
+ @@next += 1
127
+ result
128
+ end
129
+ end
130
+
124
131
  if Thread.instance_methods.include?(:thread_variable_get)
125
132
 
126
133
  def get_threadlocal_array(thread = Thread.current)
@@ -19,7 +19,7 @@ module Concurrent
19
19
  end
20
20
 
21
21
  def compute_if_absent(key)
22
- if stored_value = _get(key) # fast non-blocking path for the most likely case
22
+ if NULL != (stored_value = @backend.fetch(key, NULL)) # fast non-blocking path for the most likely case
23
23
  stored_value
24
24
  else
25
25
  @write_lock.synchronize { super }
@@ -16,6 +16,9 @@ module Concurrent
16
16
  # Default maximum number of seconds a thread in the pool may remain idle
17
17
  # before being reclaimed.
18
18
 
19
+ # @!macro thread_pool_executor_constant_default_synchronous
20
+ # Default value of the :synchronous option.
21
+
19
22
  # @!macro thread_pool_executor_attr_reader_max_length
20
23
  # The maximum number of threads that may be created in the pool.
21
24
  # @return [Integer] The maximum number of threads that may be created in the pool.
@@ -40,6 +43,10 @@ module Concurrent
40
43
  # The number of seconds that a thread may be idle before being reclaimed.
41
44
  # @return [Integer] The number of seconds that a thread may be idle before being reclaimed.
42
45
 
46
+ # @!macro thread_pool_executor_attr_reader_synchronous
47
+ # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue.
48
+ # @return [true, false]
49
+
43
50
  # @!macro thread_pool_executor_attr_reader_max_queue
44
51
  # The maximum number of tasks that may be waiting in the work queue at any one time.
45
52
  # When the queue size reaches `max_queue` subsequent tasks will be rejected in
@@ -21,12 +21,18 @@ if Concurrent.on_jruby?
21
21
  # @!macro thread_pool_executor_constant_default_thread_timeout
22
22
  DEFAULT_THREAD_IDLETIMEOUT = 60
23
23
 
24
+ # @!macro thread_pool_executor_constant_default_synchronous
25
+ DEFAULT_SYNCHRONOUS = false
26
+
24
27
  # @!macro thread_pool_executor_attr_reader_max_length
25
28
  attr_reader :max_length
26
29
 
27
30
  # @!macro thread_pool_executor_attr_reader_max_queue
28
31
  attr_reader :max_queue
29
32
 
33
+ # @!macro thread_pool_executor_attr_reader_synchronous
34
+ attr_reader :synchronous
35
+
30
36
  # @!macro thread_pool_executor_method_initialize
31
37
  def initialize(opts = {})
32
38
  super(opts)
@@ -94,8 +100,10 @@ if Concurrent.on_jruby?
94
100
  max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
95
101
  idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
96
102
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
103
+ @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
97
104
  @fallback_policy = opts.fetch(:fallback_policy, :abort)
98
105
 
106
+ raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
99
107
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE
100
108
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE
101
109
  raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE
@@ -103,7 +111,11 @@ if Concurrent.on_jruby?
103
111
  raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy)
104
112
 
105
113
  if @max_queue == 0
106
- queue = java.util.concurrent.LinkedBlockingQueue.new
114
+ if @synchronous
115
+ queue = java.util.concurrent.SynchronousQueue.new
116
+ else
117
+ queue = java.util.concurrent.LinkedBlockingQueue.new
118
+ end
107
119
  else
108
120
  queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue)
109
121
  end
@@ -23,6 +23,9 @@ module Concurrent
23
23
  # @!macro thread_pool_executor_constant_default_thread_timeout
24
24
  DEFAULT_THREAD_IDLETIMEOUT = 60
25
25
 
26
+ # @!macro thread_pool_executor_constant_default_synchronous
27
+ DEFAULT_SYNCHRONOUS = false
28
+
26
29
  # @!macro thread_pool_executor_attr_reader_max_length
27
30
  attr_reader :max_length
28
31
 
@@ -35,6 +38,9 @@ module Concurrent
35
38
  # @!macro thread_pool_executor_attr_reader_max_queue
36
39
  attr_reader :max_queue
37
40
 
41
+ # @!macro thread_pool_executor_attr_reader_synchronous
42
+ attr_reader :synchronous
43
+
38
44
  # @!macro thread_pool_executor_method_initialize
39
45
  def initialize(opts = {})
40
46
  super(opts)
@@ -114,9 +120,11 @@ module Concurrent
114
120
  @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
115
121
  @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
116
122
  @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
123
+ @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS)
117
124
  @fallback_policy = opts.fetch(:fallback_policy, :abort)
118
- raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
119
125
 
126
+ raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0
127
+ raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy)
120
128
  raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE
121
129
  raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE
122
130
  raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE
@@ -201,6 +209,8 @@ module Concurrent
201
209
  #
202
210
  # @!visibility private
203
211
  def ns_enqueue(*args, &task)
212
+ return false if @synchronous
213
+
204
214
  if !ns_limited_queue? || @queue.size < @max_queue
205
215
  @queue << [task, args]
206
216
  true
@@ -73,7 +73,8 @@ module Concurrent
73
73
  # @option opts [Symbol] :fallback_policy (:abort) the policy for handling new
74
74
  # tasks that are received when the queue size has reached
75
75
  # `max_queue` or the executor has shut down
76
- #
76
+ # @option opts [Boolean] :synchronous (DEFAULT_SYNCHRONOUS) whether or not a value of 0
77
+ # for :max_queue means the queue must perform direct hand-off rather than unbounded.
77
78
  # @raise [ArgumentError] if `:max_threads` is less than one
78
79
  # @raise [ArgumentError] if `:min_threads` is less than zero
79
80
  # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified
@@ -10,7 +10,7 @@ module Concurrent
10
10
  # or writing at a time. This includes iteration methods like `#each`,
11
11
  # which takes the lock repeatedly when reading an item.
12
12
  #
13
- # @see http://ruby-doc.org/core-2.2.0/Hash.html Ruby standard library `Hash`
13
+ # @see http://ruby-doc.org/core/Hash.html Ruby standard library `Hash`
14
14
 
15
15
  # @!macro internal_implementation_note
16
16
  HashImplementation = case
@@ -5,7 +5,7 @@ module Concurrent
5
5
 
6
6
  # A thread-safe, immutable variation of Ruby's standard `Struct`.
7
7
  #
8
- # @see http://ruby-doc.org/core-2.2.0/Struct.html Ruby standard library `Struct`
8
+ # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct`
9
9
  module ImmutableStruct
10
10
  include Synchronization::AbstractStruct
11
11
 
@@ -6,7 +6,7 @@ module Concurrent
6
6
  # An thread-safe variation of Ruby's standard `Struct`. Values can be set at
7
7
  # construction or safely changed at any time during the object's lifecycle.
8
8
  #
9
- # @see http://ruby-doc.org/core-2.2.0/Struct.html Ruby standard library `Struct`
9
+ # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct`
10
10
  module MutableStruct
11
11
  include Synchronization::AbstractStruct
12
12
 
@@ -40,7 +40,7 @@ module Concurrent
40
40
  # struct. Unset parameters default to nil. Passing more parameters than number of attributes
41
41
  # will raise an `ArgumentError`.
42
42
  #
43
- # @see http://ruby-doc.org/core-2.2.0/Struct.html#method-c-new Ruby standard library `Struct#new`
43
+ # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new`
44
44
 
45
45
  # @!macro struct_values
46
46
  #
@@ -9,7 +9,7 @@ module Concurrent
9
9
  # or any time thereafter. Attempting to assign a value to a member
10
10
  # that has already been set will result in a `Concurrent::ImmutabilityError`.
11
11
  #
12
- # @see http://ruby-doc.org/core-2.2.0/Struct.html Ruby standard library `Struct`
12
+ # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct`
13
13
  # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword
14
14
  module SettableStruct
15
15
  include Synchronization::AbstractStruct
@@ -26,8 +26,8 @@ module Concurrent
26
26
  # the classes using it. Use {Synchronization::Object} not this abstract class.
27
27
  #
28
28
  # @note this object does not support usage together with
29
- # [`Thread#wakeup`](http://ruby-doc.org/core-2.2.0/Thread.html#method-i-wakeup)
30
- # and [`Thread#raise`](http://ruby-doc.org/core-2.2.0/Thread.html#method-i-raise).
29
+ # [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup)
30
+ # and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise).
31
31
  # `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and
32
32
  # `Thread#wakeup` will not work on all platforms.
33
33
  #
@@ -97,7 +97,7 @@ module Concurrent
97
97
  # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
98
98
  # TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created
99
99
  # hide from yardoc in a method
100
- attr_reader *(12.times.collect{ |i| "padding_#{i}".to_sym })
100
+ attr_reader :padding_0, :padding_1, :padding_2, :padding_3, :padding_4, :padding_5, :padding_6, :padding_7, :padding_8, :padding_9, :padding_10, :padding_11
101
101
  end
102
102
  padding
103
103
  end
@@ -325,7 +325,6 @@ module Concurrent
325
325
  def timeout_task(completion)
326
326
  return unless @running.true?
327
327
  if completion.try?
328
- self.value = value
329
328
  schedule_next_task
330
329
  observers.notify_observers(Time.now, nil, Concurrent::TimeoutError.new)
331
330
  end
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '1.1.6'
2
+ VERSION = '1.1.7'
3
3
  end
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.1.6
4
+ version: 1.1.7
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: 2020-02-10 00:00:00.000000000 Z
13
+ date: 2020-08-08 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.
@@ -20,12 +20,12 @@ executables: []
20
20
  extensions: []
21
21
  extra_rdoc_files:
22
22
  - README.md
23
- - LICENSE.md
23
+ - LICENSE.txt
24
24
  - CHANGELOG.md
25
25
  files:
26
26
  - CHANGELOG.md
27
27
  - Gemfile
28
- - LICENSE.md
28
+ - LICENSE.txt
29
29
  - README.md
30
30
  - Rakefile
31
31
  - ext/concurrent-ruby/ConcurrentRubyService.java
@@ -184,8 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
184
184
  - !ruby/object:Gem::Version
185
185
  version: '0'
186
186
  requirements: []
187
- rubyforge_project:
188
- rubygems_version: 2.7.9
187
+ rubygems_version: 3.1.2
189
188
  signing_key:
190
189
  specification_version: 4
191
190
  summary: Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,