concurrent-ruby 1.2.0 → 1.2.1

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: f224c72d89a1bd079ad1086c9ed28a1d4d6432c718b9e0624c9a32afc8500cc8
4
- data.tar.gz: dfb811189c8e7eeb2ea1f17fc1e680657dffe767c77bb09312e85a4f29f2bd60
3
+ metadata.gz: 366b0c4f0d3184143a58a6b30538fe9997e7dfad19c8ea38a468168d680f3bdf
4
+ data.tar.gz: 010f0ee92f5132a2ed41da7d789a72955691dbcf880c579fd121cb366ba000bc
5
5
  SHA512:
6
- metadata.gz: 807b1aac5e1bdee569df0b9e38fff1ed339f2c8569cd0a7ab565cbbecb23ffc9c6cf968e457e2acecf3abd187ac43da16dc2fb91716c912e78c08aa122dcaf0e
7
- data.tar.gz: 07c37140aa1417ad32daa0de92f4c0883c7a96c1c53fba9aa09e34598632b3ad274283034064df41181e59964d0c79e41d083f17912e8e121c4f2d774c988b81
6
+ metadata.gz: 876b3302b218236cb89bd838e3030e2c5937d9682edd8e88a47d538ec5f0da21a7d49b55452e278e6c01b7210cb51c4bad3afc6b5767294f16890f5bd630e69b
7
+ data.tar.gz: 938906cad82d61617a0267dc28dc99e18420c7872593344c1c6adb4fa54c751839226703e1ce6ea81e79dcd35b2650e5868c6c11bcaf83c02d2fb105aa8b35a2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ## Current
2
2
 
3
+ * (#990) Add missing `require 'fiber'` for `FiberLocalVar`.
4
+ * (#989) Optimize `Concurrent::Map#[]` on CRuby by letting the backing Hash handle the `default_proc`.
5
+
3
6
  ## Release v1.2.0 (23 Jan 2023)
4
7
 
5
8
  * (#962) Fix ReentrantReadWriteLock to use the same granularity for locals as for Mutex it uses.
data/Rakefile CHANGED
@@ -271,6 +271,7 @@ namespace :release do
271
271
  task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
272
272
 
273
273
  namespace :publish do
274
+ publish_base = true
274
275
  publish_edge = false
275
276
 
276
277
  task :ask do
@@ -289,8 +290,8 @@ namespace :release do
289
290
  desc '** tag HEAD with current version and push to github'
290
291
  task :tag => :ask do
291
292
  Dir.chdir(__dir__) do
292
- sh "git tag v#{Concurrent::VERSION}"
293
- sh "git push origin v#{Concurrent::VERSION}"
293
+ sh "git tag v#{Concurrent::VERSION}" if publish_base
294
+ sh "git push origin v#{Concurrent::VERSION}" if publish_base
294
295
  sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
295
296
  sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
296
297
  end
@@ -299,11 +300,11 @@ namespace :release do
299
300
  desc '** push all *.gem files to rubygems'
300
301
  task :rubygems => :ask do
301
302
  Dir.chdir(__dir__) do
302
- sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
303
+ sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem" if publish_base
303
304
  sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
304
- sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem"
305
- sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem"
306
- sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem"
305
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if publish_base
306
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem" if publish_base
307
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem" if publish_base
307
308
  end
308
309
  end
309
310
 
@@ -1,3 +1,4 @@
1
+ require 'fiber'
1
2
  require 'concurrent/utility/engine'
2
3
  require 'concurrent/constants'
3
4
 
@@ -9,8 +9,8 @@ module Concurrent
9
9
  # @!visibility private
10
10
  class MriMapBackend < NonConcurrentMapBackend
11
11
 
12
- def initialize(options = nil)
13
- super(options)
12
+ def initialize(options = nil, &default_proc)
13
+ super(options, &default_proc)
14
14
  @write_lock = Mutex.new
15
15
  end
16
16
 
@@ -12,8 +12,10 @@ module Concurrent
12
12
  # directly without calling each other. This is important because of the
13
13
  # SynchronizedMapBackend which uses a non-reentrant mutex for performance
14
14
  # reasons.
15
- def initialize(options = nil)
16
- @backend = {}
15
+ def initialize(options = nil, &default_proc)
16
+ validate_options_hash!(options) if options.kind_of?(::Hash)
17
+ @backend = Hash.new(&default_proc)
18
+ @default_proc = default_proc
17
19
  end
18
20
 
19
21
  def [](key)
@@ -55,7 +57,7 @@ module Concurrent
55
57
  end
56
58
 
57
59
  def compute(key)
58
- store_computed_value(key, yield(@backend[key]))
60
+ store_computed_value(key, yield(get_or_default(key, nil)))
59
61
  end
60
62
 
61
63
  def merge_pair(key, value)
@@ -67,7 +69,7 @@ module Concurrent
67
69
  end
68
70
 
69
71
  def get_and_set(key, value)
70
- stored_value = @backend[key]
72
+ stored_value = get_or_default(key, nil)
71
73
  @backend[key] = value
72
74
  stored_value
73
75
  end
@@ -109,13 +111,11 @@ module Concurrent
109
111
  @backend.fetch(key, default_value)
110
112
  end
111
113
 
112
- alias_method :_get, :[]
113
- alias_method :_set, :[]=
114
- private :_get, :_set
115
114
  private
115
+
116
116
  def initialize_copy(other)
117
117
  super
118
- @backend = {}
118
+ @backend = Hash.new(&@default_proc)
119
119
  self
120
120
  end
121
121
 
@@ -46,6 +46,12 @@ module Concurrent
46
46
  # @note Atomic methods taking a block do not allow the `self` instance
47
47
  # to be used within the block. Doing so will cause a deadlock.
48
48
 
49
+ # @!method []=(key, value)
50
+ # Set a value with key
51
+ # @param [Object] key
52
+ # @param [Object] value
53
+ # @return [Object] the new value
54
+
49
55
  # @!method compute_if_absent(key)
50
56
  # Compute and store new value for key if the key is absent.
51
57
  # @param [Object] key
@@ -119,41 +125,38 @@ module Concurrent
119
125
  # @return [true, false] true if deleted
120
126
  # @!macro map.atomic_method
121
127
 
122
- #
123
- def initialize(options = nil, &block)
124
- if options.kind_of?(::Hash)
125
- validate_options_hash!(options)
126
- else
127
- options = nil
128
- end
128
+ # NonConcurrentMapBackend handles default_proc natively
129
+ unless defined?(Collection::NonConcurrentMapBackend) and self < Collection::NonConcurrentMapBackend
129
130
 
130
- super(options)
131
- @default_proc = block
132
- end
131
+ # @param [Hash, nil] options options to set the :initial_capacity or :load_factor. Ignored on some Rubies.
132
+ # @param [Proc] default_proc Optional block to compute the default value if the key is not set, like `Hash#default_proc`
133
+ def initialize(options = nil, &default_proc)
134
+ if options.kind_of?(::Hash)
135
+ validate_options_hash!(options)
136
+ else
137
+ options = nil
138
+ end
133
139
 
134
- # Get a value with key
135
- # @param [Object] key
136
- # @return [Object] the value
137
- def [](key)
138
- if value = super # non-falsy value is an existing mapping, return it right away
139
- value
140
- # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
141
- # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
142
- # would be returned)
143
- # note: nil == value check is not technically necessary
144
- elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
145
- @default_proc.call(self, key)
146
- else
147
- value
140
+ super(options)
141
+ @default_proc = default_proc
148
142
  end
149
- end
150
143
 
151
- # Set a value with key
152
- # @param [Object] key
153
- # @param [Object] value
154
- # @return [Object] the new value
155
- def []=(key, value)
156
- super
144
+ # Get a value with key
145
+ # @param [Object] key
146
+ # @return [Object] the value
147
+ def [](key)
148
+ if value = super # non-falsy value is an existing mapping, return it right away
149
+ value
150
+ # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call
151
+ # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value
152
+ # would be returned)
153
+ # note: nil == value check is not technically necessary
154
+ elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL))
155
+ @default_proc.call(self, key)
156
+ else
157
+ value
158
+ end
159
+ end
157
160
  end
158
161
 
159
162
  alias_method :get, :[]
@@ -1,3 +1,3 @@
1
1
  module Concurrent
2
- VERSION = '1.2.0'
2
+ VERSION = '1.2.1'
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.2.0
4
+ version: 1.2.1
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: 2023-01-23 00:00:00.000000000 Z
13
+ date: 2023-02-24 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.