concurrent-ruby 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 207cadfd4ec0e25f6ba9881ef8f32ea86c5772074d4aff5e2ab5d5bdf4613e09
4
- data.tar.gz: b41c0dd080a6d2fbf1d2c97bf2e9a8db0e99849ba875d32ade39384838e20e23
3
+ metadata.gz: 4e26dce842bfb7973c28f13017d50c3e729a9261f48427920db279055c4d089b
4
+ data.tar.gz: 501e9d485d4683657b49cd5820ef0462ce91133ad163ba9e790f254892d1e533
5
5
  SHA512:
6
- metadata.gz: 4edf0b84df6aa42a69c6ff231c730d12a64df6819ebea508599b469d88951c47ce4b091d3f3fc41afcb9196986091efe57d156161510f03cfb8ee0ebaf66ff0c
7
- data.tar.gz: a18c3ef751cadd220d424779e96d96ead76362ad4e7bfcfb2341d9ba4baed6f0b8427c452e31868e512ab2b3a8226fe350041e0e5b87cd28e10d9ce1b5334c72
6
+ metadata.gz: 7f894d3207ce129044970321fabe750cc4b9744a876f354dd791d045fb4ffed1d0a5a9a50dcb1ab0ca36df705b6b7578fe7eded26bcaa3dbeb0c7a12e655596c
7
+ data.tar.gz: 3cb4ccbbf13e2f73987eda48a32b444d7330c53a668ddef2fd4a73841caf18805d68cec45273a02de2c10087da4a4ce063c01b1bdccb96d4668b10cc4af79f88
data/CHANGELOG.md CHANGED
@@ -1,7 +1,19 @@
1
1
  ## Current
2
2
 
3
+ ## Release v1.1.9 (5 Jun 2021)
4
+
5
+ concurrent-ruby:
6
+
7
+ * (#866) Child promise state not set to :pending immediately after #execute when parent has completed
8
+ * (#905, #872) Fix RubyNonConcurrentPriorityQueue#delete method
9
+ * (2df0337d) Make sure locks are not shared on shared when objects are dup/cloned
10
+ * (#900, #906, #796, #847, #911) Fix Concurrent::Set tread-safety issues on CRuby
11
+ * (#907) Add new ConcurrentMap backend for TruffleRuby
12
+
3
13
  ## Release v1.1.8 (20 January 2021)
4
14
 
15
+ concurrent-ruby:
16
+
5
17
  * (#885) Fix race condition in TVar for stale reads
6
18
  * (#884) RubyThreadLocalVar: Do not iterate over hash which might conflict with new pair addition
7
19
 
data/README.md CHANGED
@@ -353,19 +353,43 @@ and load the appropriate C extensions.
353
353
  No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users. The
354
354
  best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
355
355
 
356
+ ## Building the gem
357
+
358
+ ### Requirements
359
+
360
+ * Recent CRuby
361
+ * JRuby, `rbenv install jruby-9.2.17.0`
362
+ * Set env variable `CONCURRENT_JRUBY_HOME` to point to it, e.g. `/usr/local/opt/rbenv/versions/jruby-9.2.17.0`
363
+ * Install Docker, required for Windows builds
364
+
365
+ ### Publishing the Gem
366
+
367
+ * Update`version.rb`
368
+ * Update the CHANGELOG
369
+ * Update the Yard documentation
370
+ - Add the new version to `docs-source/signpost.md`. Needs to be done only if there are visible changes in the
371
+ documentation.
372
+ - Run `bundle exec rake yard` to update the master documentation and signpost.
373
+ - Run `bundle exec rake yard:<new-version>` to add or update the documentation of the new version.
374
+ * Commit (and push) the changes.
375
+ * Use `be rake release` to release the gem. It consists
376
+ of `['release:checks', 'release:build', 'release:test', 'release:publish']` steps. It will ask at the end before
377
+ publishing anything. Steps can also be executed individually.
378
+
356
379
  ## Maintainers
357
380
 
358
- * [Petr Chalupa](https://github.com/pitr-ch) (lead maintainer, point-of-contact)
359
- * [Jerry D'Antonio](https://github.com/jdantonio) (creator)
360
- * [Chris Seaton](https://github.com/chrisseaton)
381
+ * [Petr Chalupa](https://github.com/pitr-ch) Lead maintainer, point-of-contact.
382
+ * [Chris Seaton](https://github.com/chrisseaton)
383
+ If Petr is not available Chris can help or poke Petr to pay attention where it is needed.
361
384
 
362
385
  ### Special Thanks to
363
386
 
387
+ * [Jerry D'Antonio](https://github.com/jdantonio) for creating the gem
364
388
  * [Brian Durand](https://github.com/bdurand) for the `ref` gem
365
389
  * [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
366
390
  * [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
367
391
 
368
- and to the past maintainers
392
+ to the past maintainers
369
393
 
370
394
  * [Michele Della Torre](https://github.com/mighe)
371
395
  * [Paweł Obrok](https://github.com/obrok)
data/Rakefile CHANGED
@@ -135,7 +135,7 @@ begin
135
135
  task :update_readme do
136
136
  Dir.chdir __dir__ do
137
137
  content = File.read(File.join('README.md')).
138
- gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
138
+ gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
139
139
  case $1
140
140
  when 'LockFreeLinkedSet'
141
141
  "{Concurrent::Edge::#{$1} #{$1}}"
@@ -165,9 +165,9 @@ begin
165
165
  desc "* of #{name} into subdir #{name}"
166
166
  YARD::Rake::YardocTask.new(name) do |yard|
167
167
  yard.options.push(
168
- '--output-dir', output_dir,
169
- '--main', 'tmp/README.md',
170
- *common_yard_options)
168
+ '--output-dir', output_dir,
169
+ '--main', 'tmp/README.md',
170
+ *common_yard_options)
171
171
  yard.files = ['./lib/concurrent-ruby/**/*.rb',
172
172
  './lib/concurrent-ruby-edge/**/*.rb',
173
173
  './ext/concurrent_ruby_ext/**/*.c',
@@ -189,9 +189,9 @@ begin
189
189
  desc "* signpost for versions"
190
190
  YARD::Rake::YardocTask.new(:signpost) do |yard|
191
191
  yard.options.push(
192
- '--output-dir', 'docs',
193
- '--main', 'docs-source/signpost.md',
194
- *common_yard_options)
192
+ '--output-dir', 'docs',
193
+ '--main', 'docs-source/signpost.md',
194
+ *common_yard_options)
195
195
  yard.files = ['no-lib']
196
196
  end
197
197
 
@@ -206,7 +206,7 @@ begin
206
206
  sh 'diff -r docs/ docs-copy/' do |ok, res|
207
207
  unless ok
208
208
  begin
209
- STDOUT.puts 'Command failed. Continue? (y/n)'
209
+ STDOUT.puts "yard:#{name} is not properly generated and committed.", "Continue? (y/n)"
210
210
  input = STDIN.gets.strip.downcase
211
211
  end until %w(y n).include?(input)
212
212
  exit 1 if input == 'n'
@@ -234,15 +234,13 @@ task :release => ['release:checks', 'release:build', 'release:test', 'release:pu
234
234
  namespace :release do
235
235
  # Depends on environment of @pitr-ch
236
236
 
237
- mri_version = '2.6.5'
238
- jruby_version = 'jruby-9.2.9.0'
239
-
240
237
  task :checks => "yard:#{current_yard_version_name}:uptodate" do
241
238
  Dir.chdir(__dir__) do
242
239
  sh 'test -z "$(git status --porcelain)"' do |ok, res|
243
240
  unless ok
244
241
  begin
245
- STDOUT.puts 'Command failed. Continue? (y/n)'
242
+ status = `git status --porcelain`
243
+ STDOUT.puts 'There are local changes that you might want to commit.', status, 'Continue? (y/n)'
246
244
  input = STDIN.gets.strip.downcase
247
245
  end until %w(y n).include?(input)
248
246
  exit 1 if input == 'n'
@@ -250,10 +248,10 @@ namespace :release do
250
248
  end
251
249
  sh 'git fetch'
252
250
  sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
253
- '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
251
+ '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
254
252
  unless ok
255
253
  begin
256
- STDOUT.puts 'Command failed. Continue? (y/n)'
254
+ STDOUT.puts 'Local master branch is not pushed to origin.', 'Continue? (y/n)'
257
255
  input = STDIN.gets.strip.downcase
258
256
  end until %w(y n).include?(input)
259
257
  exit 1 if input == 'n'
@@ -270,6 +268,12 @@ namespace :release do
270
268
  Dir.chdir(__dir__) do
271
269
  old = ENV['RBENV_VERSION']
272
270
 
271
+ mri_version = `ruby -e 'puts RUBY_VERSION'`.chomp
272
+ jruby_version = File.basename(ENV['CONCURRENT_JRUBY_HOME'])
273
+
274
+ puts "Using following version:"
275
+ pp mri_version: mri_version, jruby_version: jruby_version
276
+
273
277
  ENV['RBENV_VERSION'] = mri_version
274
278
  sh 'rbenv version'
275
279
  sh 'bundle exec rake spec:installed'
@@ -292,12 +296,12 @@ namespace :release do
292
296
 
293
297
  task :ask do
294
298
  begin
295
- STDOUT.puts 'Do you want to publish anything? (y/n)'
299
+ STDOUT.puts 'Do you want to publish anything now? (y/n)'
296
300
  input = STDIN.gets.strip.downcase
297
301
  end until %w(y n).include?(input)
298
302
  exit 1 if input == 'n'
299
303
  begin
300
- STDOUT.puts 'Do you want to publish edge? (y/n)'
304
+ STDOUT.puts 'It will publish `concurrent-ruby`. Do you want to publish `concurrent-ruby-edge`? (y/n)'
301
305
  input = STDIN.gets.strip.downcase
302
306
  end until %w(y n).include?(input)
303
307
  publish_edge = input == 'y'
@@ -326,9 +330,10 @@ namespace :release do
326
330
 
327
331
  desc '** print post release steps'
328
332
  task :post_steps do
329
- puts 'Manually: create a release on GitHub with relevant changelog part'
330
- puts 'Manually: send email same as release with relevant changelog part'
331
- puts 'Manually: tweet'
333
+ # TODO: (petr 05-Jun-2021) automate and renew the process
334
+ # puts 'Manually: create a release on GitHub with relevant changelog part'
335
+ # puts 'Manually: send email same as release with relevant changelog part'
336
+ # puts 'Manually: tweet'
332
337
  end
333
338
  end
334
339
  end
@@ -0,0 +1,14 @@
1
+ module Concurrent
2
+
3
+ # @!visibility private
4
+ module Collection
5
+
6
+ # @!visibility private
7
+ class TruffleRubyMapBackend < TruffleRuby::ConcurrentMap
8
+ def initialize(options = nil)
9
+ options ||= {}
10
+ super(initial_capacity: options[:initial_capacity], load_factor: options[:load_factor])
11
+ end
12
+ end
13
+ end
14
+ end
@@ -30,7 +30,7 @@ module Concurrent
30
30
  if @queue[k] == item
31
31
  swap(k, @length)
32
32
  @length -= 1
33
- sink(k)
33
+ sink(k) || swim(k)
34
34
  @queue.pop
35
35
  else
36
36
  k += 1
@@ -126,12 +126,17 @@ module Concurrent
126
126
  #
127
127
  # @!visibility private
128
128
  def sink(k)
129
+ success = false
130
+
129
131
  while (j = (2 * k)) <= @length do
130
132
  j += 1 if j < @length && ! ordered?(j, j+1)
131
133
  break if ordered?(k, j)
132
134
  swap(k, j)
135
+ success = true
133
136
  k = j
134
137
  end
138
+
139
+ success
135
140
  end
136
141
 
137
142
  # Percolate up to maintain heap invariant.
@@ -140,10 +145,15 @@ module Concurrent
140
145
  #
141
146
  # @!visibility private
142
147
  def swim(k)
148
+ success = false
149
+
143
150
  while k > 1 && ! ordered?(k/2, k) do
144
151
  swap(k, k/2)
145
152
  k = k/2
153
+ success = true
146
154
  end
155
+
156
+ success
147
157
  end
148
158
  end
149
159
  end
@@ -15,7 +15,10 @@ module Concurrent
15
15
  when Concurrent.on_cruby?
16
16
  require 'concurrent/collection/map/mri_map_backend'
17
17
  MriMapBackend
18
- when Concurrent.on_rbx? || Concurrent.on_truffleruby?
18
+ when Concurrent.on_truffleruby? && defined?(::TruffleRuby::ConcurrentMap)
19
+ require 'concurrent/collection/map/truffleruby_map_backend'
20
+ TruffleRubyMapBackend
21
+ when Concurrent.on_truffleruby? || Concurrent.on_rbx?
19
22
  require 'concurrent/collection/map/atomic_reference_map_backend'
20
23
  AtomicReferenceMapBackend
21
24
  else
@@ -114,7 +117,7 @@ module Concurrent
114
117
  # @return [true, false] true if deleted
115
118
  # @!macro map.atomic_method
116
119
 
117
-
120
+ #
118
121
  def initialize(options = nil, &block)
119
122
  if options.kind_of?(::Hash)
120
123
  validate_options_hash!(options)
@@ -143,8 +146,15 @@ module Concurrent
143
146
  end
144
147
  end
145
148
 
149
+ # Set a value with key
150
+ # @param [Object] key
151
+ # @param [Object] value
152
+ # @return [Object] the new value
153
+ def []=(key, value)
154
+ super
155
+ end
156
+
146
157
  alias_method :get, :[]
147
- # TODO (pitr-ch 30-Oct-2018): doc
148
158
  alias_method :put, :[]=
149
159
 
150
160
  # Get a value with key, or default_value when key is absent,
@@ -250,6 +250,7 @@ module Concurrent
250
250
  realize(@promise_body)
251
251
  end
252
252
  else
253
+ compare_and_set_state(:pending, :unscheduled)
253
254
  @parent.execute
254
255
  end
255
256
  self
@@ -19,13 +19,19 @@ module Concurrent
19
19
  #
20
20
  # @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set`
21
21
 
22
-
23
22
  # @!macro internal_implementation_note
24
23
  SetImplementation = case
25
24
  when Concurrent.on_cruby?
26
- # Because MRI never runs code in parallel, the existing
27
- # non-thread-safe structures should usually work fine.
28
- ::Set
25
+ # The CRuby implementation of Set is written in Ruby itself and is
26
+ # not thread safe for certain methods.
27
+ require 'monitor'
28
+ require 'concurrent/thread_safe/util/data_structures'
29
+
30
+ class CRubySet < ::Set
31
+ end
32
+
33
+ ThreadSafe::Util.make_synchronized_on_cruby CRubySet
34
+ CRubySet
29
35
 
30
36
  when Concurrent.on_jruby?
31
37
  require 'jruby/synchronized'
@@ -33,6 +39,7 @@ module Concurrent
33
39
  class JRubySet < ::Set
34
40
  include JRuby::Synchronized
35
41
  end
42
+
36
43
  JRubySet
37
44
 
38
45
  when Concurrent.on_rbx?
@@ -41,7 +48,8 @@ module Concurrent
41
48
 
42
49
  class RbxSet < ::Set
43
50
  end
44
- ThreadSafe::Util.make_synchronized_on_rbx Concurrent::RbxSet
51
+
52
+ ThreadSafe::Util.make_synchronized_on_rbx RbxSet
45
53
  RbxSet
46
54
 
47
55
  when Concurrent.on_truffleruby?
@@ -50,7 +58,7 @@ module Concurrent
50
58
  class TruffleRubySet < ::Set
51
59
  end
52
60
 
53
- ThreadSafe::Util.make_synchronized_on_truffleruby Concurrent::TruffleRubySet
61
+ ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubySet
54
62
  TruffleRubySet
55
63
 
56
64
  else
@@ -32,6 +32,12 @@ module Concurrent
32
32
  @__Condition__ = ::ConditionVariable.new
33
33
  end
34
34
 
35
+ def initialize_copy(other)
36
+ super
37
+ @__Lock__ = ::Mutex.new
38
+ @__Condition__ = ::ConditionVariable.new
39
+ end
40
+
35
41
  protected
36
42
 
37
43
  def synchronize
@@ -61,6 +67,12 @@ module Concurrent
61
67
  @__Condition__ = @__Lock__.new_cond
62
68
  end
63
69
 
70
+ def initialize_copy(other)
71
+ super
72
+ @__Lock__ = ::Monitor.new
73
+ @__Condition__ = @__Lock__.new_cond
74
+ end
75
+
64
76
  protected
65
77
 
66
78
  def synchronize # TODO may be a problem with lock.synchronize { lock.wait }
@@ -12,6 +12,12 @@ module Concurrent
12
12
  @__owner__ = nil
13
13
  end
14
14
 
15
+ def initialize_copy(other)
16
+ super
17
+ @__Waiters__ = []
18
+ @__owner__ = nil
19
+ end
20
+
15
21
  protected
16
22
 
17
23
  def synchronize(&block)
@@ -12,12 +12,37 @@ end
12
12
  module Concurrent
13
13
  module ThreadSafe
14
14
  module Util
15
+ def self.make_synchronized_on_cruby(klass)
16
+ klass.class_eval do
17
+ def initialize(*args, &block)
18
+ @_monitor = Monitor.new
19
+ super
20
+ end
21
+
22
+ def initialize_copy(other)
23
+ # make sure a copy is not sharing a monitor with the original object!
24
+ @_monitor = Monitor.new
25
+ super
26
+ end
27
+ end
28
+
29
+ klass.superclass.instance_methods(false).each do |method|
30
+ klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
31
+ def #{method}(*args)
32
+ monitor = @_monitor
33
+ monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.")
34
+ monitor.synchronize { super }
35
+ end
36
+ RUBY
37
+ end
38
+ end
39
+
15
40
  def self.make_synchronized_on_rbx(klass)
16
41
  klass.class_eval do
17
42
  private
18
43
 
19
44
  def _mon_initialize
20
- @_monitor = Monitor.new unless @_monitor # avoid double initialisation
45
+ @_monitor ||= Monitor.new # avoid double initialisation
21
46
  end
22
47
 
23
48
  def self.new(*args)
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '1.1.8'
2
+ VERSION = '1.1.9'
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.8
4
+ version: 1.1.9
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: 2021-01-20 00:00:00.000000000 Z
13
+ date: 2021-06-05 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.
@@ -79,6 +79,7 @@ files:
79
79
  - lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb
80
80
  - lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb
81
81
  - lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb
82
+ - lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb
82
83
  - lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb
83
84
  - lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb
84
85
  - lib/concurrent-ruby/concurrent/concern/deprecation.rb