concurrent-ruby 1.2.0 → 1.2.1

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: 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.