concurrent-ruby 1.1.0.pre2 → 1.1.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: a9eff851dc1c1194d74471f51e804151e6523be1af22c681393518897d8723e7
4
- data.tar.gz: 97aea57e3c31de3e0a927b07b5bbae7a5b2859537fe959f08d045fadc86d818a
3
+ metadata.gz: 8d042c846e692138ba0eea6efbabb53794abbaae207477dc5e549abac9fab266
4
+ data.tar.gz: 34678c0ec6d519d5beac0b12a8c6116d4eb1ff29dd620ba03df851d086b04adc
5
5
  SHA512:
6
- metadata.gz: ee74332b245d576afd75179edf7d37e2d815e0f24afe157e9b76189c7275e60a8edc348646d659c5d631e73fa5382a57a94ec82c6b4bb909a993f86b45677192
7
- data.tar.gz: d21e2f11e2c3f9090cbb4e7dada48cd64d3eb3a9c7588417b6e52975ebe0a0f8fafc612695c46cd58f94389c7597800c038a57f89fa70db936493b007890d1e7
6
+ metadata.gz: 9b75559855ce216316a81bb68a9fcb1e74dceed4baa8e816d2e02cd12af50745e88f9afba7470681a8f47297a297fe9fd79e82ace4b5f63410197469eab45523
7
+ data.tar.gz: 79e63eb2ef9ab15e9fd5d1d777ae027e68b399ec885d85bc8156f9edad741ecf4eb20fc063357068018ef932c18e7263466ef64cee7592bf50b39433e83b94a7
@@ -1,9 +1,30 @@
1
1
  ## Current
2
2
 
3
+ ## Release v1.1.1, edge v0.4.1 (1 Nov 2018)
4
+
5
+ * (#768) add support for 1.9.3 back
6
+
7
+ ## Release v1.1.0, edge v0.4.0 (31 OCt 2018) (yanked)
8
+
9
+ * (#768) yanked because of issues with removed 1.9.3 support
10
+
11
+ ## Release v1.1.0.pre2, edge v0.4.0.pre2 (18 Sep 2018)
12
+
13
+ concurrent-ruby:
14
+
15
+ * fixed documentation and README links
16
+ * fix Set for TruffleRuby and Rubinius
17
+ * use properly supported TruffleRuby APIs
18
+
19
+ concurrent-ruby-edge:
20
+
21
+ * add Promises.zip_futures_over_on
22
+
3
23
  ## Release v1.1.0.pre1, edge v0.4.0.pre1 (15 Aug 2018)
4
24
 
5
25
  concurrent-ruby:
6
26
 
27
+ * requires at least Ruby 2.0
7
28
  * [Promises](http://ruby-concurrency.github.io/concurrent-ruby/1.1.0/Concurrent/Promises.html)
8
29
  are moved from `concurrent-ruby-edge` to `concurrent-ruby`
9
30
  * Add support for TruffleRuby
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- require_relative 'lib/concurrent/version'
3
+ require File.join(File.dirname(__FILE__ ), 'lib/concurrent/version')
4
4
 
5
5
  no_path = ENV['NO_PATH']
6
6
  options = no_path ? {} : { path: '.' }
@@ -19,7 +19,7 @@ end
19
19
  group :documentation, optional: true do
20
20
  gem 'yard', '~> 0.9.0', :require => false
21
21
  gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
22
- gem 'md-ruby-eval', '~> 0.2'
22
+ gem 'md-ruby-eval', '~> 0.3'
23
23
  end
24
24
 
25
25
  group :testing do
data/README.md CHANGED
@@ -227,8 +227,12 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
227
227
 
228
228
  ## Supported Ruby versions
229
229
 
230
- MRI 2.0 and above, JRuby 9000, TruffleRuby are supported.
231
- This gem should be fully compatible with any interpreter that is compliant with Ruby 2.0 or newer.
230
+ * MRI 2.0 and above
231
+ * JRuby 9000
232
+ * TruffleRuby are supported.
233
+ * Any Ruby interpreter that is compliant with Ruby 2.0 or newer.
234
+
235
+ Actually we still support mri 1.9.3 and jruby 1.7.27 but we are looking at ways how to drop the support.
232
236
  Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs is supported.
233
237
 
234
238
  The legacy support for Rubinius is kept but it is no longer maintained, if you would like to help
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'lib/concurrent/version'
4
4
  require_relative 'lib/concurrent/utility/engine'
5
+ require_relative 'lib/concurrent/utility/193'
5
6
 
6
7
  core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
7
8
  ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
@@ -9,7 +10,29 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.
9
10
 
10
11
  require 'rake/javaextensiontask'
11
12
 
12
- Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
13
+ JRUBY_JAR_PATH = '/usr/local/opt/rbenv/versions/jruby-9.1.17.0/lib/jruby.jar'
14
+
15
+ class ConcurrentRubyJavaExtensionTask < Rake::JavaExtensionTask
16
+ def java_classpath_arg(*args)
17
+ jruby_cpath = nil
18
+ if RUBY_PLATFORM =~ /java/
19
+ begin
20
+ cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR)
21
+ cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR)
22
+ jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR)
23
+ rescue => e
24
+ end
25
+ end
26
+ unless jruby_cpath
27
+ jruby_cpath = JRUBY_JAR_PATH
28
+ raise "#{jruby_cpath} does not exist" unless File.exist? jruby_cpath
29
+ end
30
+ jruby_cpath += File::PATH_SEPARATOR + args.join(File::PATH_SEPARATOR) unless args.empty?
31
+ jruby_cpath ? "-cp \"#{jruby_cpath}\"" : ""
32
+ end
33
+ end
34
+
35
+ ConcurrentRubyJavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
13
36
  ext.ext_dir = 'ext/concurrent-ruby'
14
37
  ext.lib_dir = 'lib/concurrent'
15
38
  end
@@ -70,9 +93,9 @@ begin
70
93
  desc '* test packaged and installed gems instead of local files'
71
94
  task :installed do
72
95
  Dir.chdir(__dir__) do
73
- sh 'gem install pkg/concurrent-ruby-1.1.0.pre1.gem'
74
- sh 'gem install pkg/concurrent-ruby-ext-1.1.0.pre1.gem' if Concurrent.on_cruby?
75
- sh 'gem install pkg/concurrent-ruby-edge-0.4.0.pre1.gem'
96
+ sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
97
+ sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
98
+ sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
76
99
  ENV['NO_PATH'] = 'true'
77
100
  sh 'bundle update'
78
101
  sh 'bundle exec rake spec:ci'
@@ -132,6 +155,7 @@ begin
132
155
  "{Concurrent::#{$1} #{$1}}"
133
156
  end
134
157
  end
158
+ FileUtils.mkpath 'tmp'
135
159
  File.write 'tmp/README.md', content
136
160
  end
137
161
  end
@@ -199,18 +223,29 @@ namespace :release do
199
223
  # Depends on environment of @pitr-ch
200
224
 
201
225
  mri_version = '2.5.1'
202
- jruby_version = 'jruby-9.1.17.0'
226
+ jruby_version = 'jruby-9.1.17.1'
203
227
 
204
228
  task :checks => "yard:#{current_yard_version_name}:uptodate" do
205
229
  Dir.chdir(__dir__) do
206
- begin
207
- STDOUT.puts "Is this a final release build? (Do git checks?) (y/n)"
208
- input = STDIN.gets.strip.downcase
209
- end until %w(y n).include?(input)
210
- if input == 'y'
211
- sh 'test -z "$(git status --porcelain)"'
212
- sh 'git fetch'
213
- sh 'test $(git show-ref --verify --hash refs/heads/master) = $(git show-ref --verify --hash refs/remotes/github/master)'
230
+ sh 'test -z "$(git status --porcelain)"' do |ok, res|
231
+ unless ok
232
+ begin
233
+ STDOUT.puts 'Command failed. Continue? (y/n)'
234
+ input = STDIN.gets.strip.downcase
235
+ end until %w(y n).include?(input)
236
+ exit 1 if input == 'n'
237
+ end
238
+ end
239
+ sh 'git fetch'
240
+ sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
241
+ '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
242
+ unless ok
243
+ begin
244
+ STDOUT.puts 'Command failed. Continue? (y/n)'
245
+ input = STDIN.gets.strip.downcase
246
+ end until %w(y n).include?(input)
247
+ exit 1 if input == 'n'
248
+ end
214
249
  end
215
250
  end
216
251
  end
@@ -243,10 +278,10 @@ namespace :release do
243
278
  namespace :publish do
244
279
  task :ask do
245
280
  begin
246
- STDOUT.puts "Do you want to publish? (y/n)"
281
+ STDOUT.puts 'Do you want to publish? (y/n)'
247
282
  input = STDIN.gets.strip.downcase
248
283
  end until %w(y n).include?(input)
249
- raise 'reconsidered' if input == 'n'
284
+ exit 1 if input == 'n'
250
285
  end
251
286
 
252
287
  desc '** tag HEAD with current version and push to github'
@@ -254,7 +289,7 @@ namespace :release do
254
289
  Dir.chdir(__dir__) do
255
290
  sh "git tag v#{Concurrent::VERSION}"
256
291
  sh "git tag edge-v#{Concurrent::EDGE_VERSION}"
257
- sh "git push github v#{Concurrent::VERSION} edge-v#{Concurrent::EDGE_VERSION}"
292
+ sh "git push origin v#{Concurrent::VERSION} edge-v#{Concurrent::EDGE_VERSION}"
258
293
  end
259
294
  end
260
295
 
@@ -284,21 +284,23 @@ public class SynchronizationLibrary implements Library {
284
284
  }
285
285
 
286
286
  @JRubyMethod(name = "sleep_interruptibly", visibility = Visibility.PUBLIC, module = true)
287
- public static IRubyObject sleepInterruptibly(ThreadContext context, IRubyObject receiver, Block block) {
287
+ public static IRubyObject sleepInterruptibly(final ThreadContext context, IRubyObject receiver, final Block block) {
288
288
  try {
289
- return context.getThread().executeTask(context, block,
290
- new RubyThread.Task<Block, IRubyObject>() {
291
- public IRubyObject run(ThreadContext context, Block block1) throws InterruptedException {
292
- return block1.call(context);
293
- }
294
-
295
- public void wakeup(RubyThread thread, Block block1) {
296
- thread.getNativeThread().interrupt();
297
- }
298
- });
289
+ context.getThread().executeBlockingTask(new RubyThread.BlockingTask() {
290
+ @Override
291
+ public void run() throws InterruptedException {
292
+ block.call(context);
293
+ }
294
+
295
+ @Override
296
+ public void wakeup() {
297
+ context.getThread().getNativeThread().interrupt();
298
+ }
299
+ });
299
300
  } catch (InterruptedException e) {
300
301
  throw context.runtime.newThreadError("interrupted in Concurrent::Synchronization::JRuby.sleep_interruptibly");
301
302
  }
303
+ return context.nil;
302
304
  }
303
305
  }
304
306
  }
@@ -1,3 +1,5 @@
1
+ require 'concurrent/utility/193'
2
+
1
3
  require 'concurrent/version'
2
4
  require 'concurrent/constants'
3
5
  require 'concurrent/errors'
@@ -2,6 +2,14 @@ require 'concurrent/synchronization'
2
2
  require 'concurrent/utility/engine'
3
3
  require 'concurrent/atomic_reference/numeric_cas_wrapper'
4
4
 
5
+ # Shim for TruffleRuby::AtomicReference
6
+ if Concurrent.on_truffleruby? && !defined?(TruffleRuby::AtomicReference)
7
+ # @!visibility private
8
+ module TruffleRuby
9
+ AtomicReference = Truffle::AtomicReference
10
+ end
11
+ end
12
+
5
13
  module Concurrent
6
14
 
7
15
  # Define update methods that use direct paths
@@ -155,8 +163,10 @@ module Concurrent
155
163
  end
156
164
  JavaAtomicReference
157
165
  when Concurrent.on_truffleruby?
158
- class TruffleRubyAtomicReference < Truffle::AtomicReference
166
+ class TruffleRubyAtomicReference < TruffleRuby::AtomicReference
159
167
  include AtomicDirectUpdate
168
+ alias_method :value, :get
169
+ alias_method :value=, :set
160
170
  alias_method :compare_and_swap, :compare_and_set
161
171
  alias_method :swap, :get_and_set
162
172
  end
@@ -16,14 +16,16 @@ if Concurrent.on_jruby?
16
16
 
17
17
  # @!macro count_down_latch_method_wait
18
18
  def wait(timeout = nil)
19
+ result = nil
19
20
  if timeout.nil?
20
21
  Synchronization::JRuby.sleep_interruptibly { @latch.await }
21
- true
22
+ result = true
22
23
  else
23
24
  Synchronization::JRuby.sleep_interruptibly do
24
- @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
25
+ result = @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
25
26
  end
26
27
  end
28
+ result
27
29
  end
28
30
 
29
31
  # @!macro count_down_latch_method_count_down
@@ -50,6 +50,8 @@ module Concurrent
50
50
  @value = !!initial
51
51
  end
52
52
 
53
+ private
54
+
53
55
  # @!visibility private
54
56
  def ns_make_value(value)
55
57
  old = @value
@@ -141,8 +141,8 @@ module Concurrent
141
141
 
142
142
  def initialize(item)
143
143
  super()
144
- @Item = item
145
- @Latch = Concurrent::CountDownLatch.new
144
+ @Item = item
145
+ @Latch = Concurrent::CountDownLatch.new
146
146
  self.value = nil
147
147
  end
148
148
 
@@ -252,8 +252,8 @@ module Concurrent
252
252
  # - Wake the sleeping occupier
253
253
  # - Return the occupier's item
254
254
 
255
- value = NULL if value.nil? # The sentinel allows nil to be a valid value
256
- me = Node.new(value) # create my node in case I need to occupy
255
+ value = NULL if value.nil? # The sentinel allows nil to be a valid value
256
+ me = Node.new(value) # create my node in case I need to occupy
257
257
  end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up
258
258
 
259
259
  result = loop do
@@ -304,13 +304,17 @@ module Concurrent
304
304
  #
305
305
  # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout
306
306
  def do_exchange(value, timeout)
307
+ result = nil
307
308
  if timeout.nil?
308
- Synchronization::JRuby.sleep_interruptibly { @exchanger.exchange(value) }
309
+ Synchronization::JRuby.sleep_interruptibly do
310
+ result = @exchanger.exchange(value)
311
+ end
309
312
  else
310
313
  Synchronization::JRuby.sleep_interruptibly do
311
- @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
314
+ result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
312
315
  end
313
316
  end
317
+ result
314
318
  rescue java.util.concurrent.TimeoutException
315
319
  CANCEL
316
320
  end
@@ -31,46 +31,89 @@ module Concurrent
31
31
  # -- for instance, it does not necessarily retain ordering by insertion time as `Hash`
32
32
  # does. For most uses it should do fine though, and we recommend you consider
33
33
  # `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs.
34
- #
35
- # > require 'concurrent'
36
- # >
37
- # > map = Concurrent::Map.new
38
34
  class Map < Collection::MapImplementation
39
35
 
40
- # @!macro map_method_is_atomic
41
- # This method is atomic. Atomic methods of `Map` which accept a block
42
- # do not allow the `self` instance to be used within the block. Doing
43
- # so will cause a deadlock.
36
+ # @!macro map.atomic_method
37
+ # This method is atomic.
38
+
39
+ # @!macro map.atomic_method_with_block
40
+ # This method is atomic.
41
+ # @note Atomic methods taking a block do not allow the `self` instance
42
+ # to be used within the block. Doing so will cause a deadlock.
43
+
44
+ # @!method compute_if_absent(key)
45
+ # Compute and store new value for key if the key is absent.
46
+ # @param [Object] key
47
+ # @yield new value
48
+ # @yieldreturn [Object] new value
49
+ # @return [Object] new value or current value
50
+ # @!macro map.atomic_method_with_block
51
+
52
+ # @!method compute_if_present(key)
53
+ # Compute and store new value for key if the key is present.
54
+ # @param [Object] key
55
+ # @yield new value
56
+ # @yieldparam old_value [Object]
57
+ # @yieldreturn [Object, nil] new value, when nil the key is removed
58
+ # @return [Object, nil] new value or nil
59
+ # @!macro map.atomic_method_with_block
60
+
61
+ # @!method compute(key)
62
+ # Compute and store new value for key.
63
+ # @param [Object] key
64
+ # @yield compute new value from old one
65
+ # @yieldparam old_value [Object, nil] old_value, or nil when key is absent
66
+ # @yieldreturn [Object, nil] new value, when nil the key is removed
67
+ # @return [Object, nil] new value or nil
68
+ # @!macro map.atomic_method_with_block
69
+
70
+ # @!method merge_pair(key, value)
71
+ # If the key is absent, the value is stored, otherwise new value is
72
+ # computed with a block.
73
+ # @param [Object] key
74
+ # @param [Object] value
75
+ # @yield compute new value from old one
76
+ # @yieldparam old_value [Object] old value
77
+ # @yieldreturn [Object, nil] new value, when nil the key is removed
78
+ # @return [Object, nil] new value or nil
79
+ # @!macro map.atomic_method_with_block
80
+
81
+ # @!method replace_pair(key, old_value, new_value)
82
+ # Replaces old_value with new_value if key exists and current value
83
+ # matches old_value
84
+ # @param [Object] key
85
+ # @param [Object] old_value
86
+ # @param [Object] new_value
87
+ # @return [true, false] true if replaced
88
+ # @!macro map.atomic_method
89
+
90
+ # @!method replace_if_exists(key, new_value)
91
+ # Replaces current value with new_value if key exists
92
+ # @param [Object] key
93
+ # @param [Object] new_value
94
+ # @return [Object, nil] old value or nil
95
+ # @!macro map.atomic_method
96
+
97
+ # @!method get_and_set(key, value)
98
+ # Get the current value under key and set new value.
99
+ # @param [Object] key
100
+ # @param [Object] value
101
+ # @return [Object, nil] old value or nil when the key was absent
102
+ # @!macro map.atomic_method
103
+
104
+ # @!method delete(key)
105
+ # Delete key and its value.
106
+ # @param [Object] key
107
+ # @return [Object, nil] old value or nil when the key was absent
108
+ # @!macro map.atomic_method
109
+
110
+ # @!method delete_pair(key, value)
111
+ # Delete pair and its value if current value equals the provided value.
112
+ # @param [Object] key
113
+ # @param [Object] value
114
+ # @return [true, false] true if deleted
115
+ # @!macro map.atomic_method
44
116
 
45
- # @!method put_if_absent
46
- # @!macro map_method_is_atomic
47
-
48
- # @!method compute_if_absent
49
- # @!macro map_method_is_atomic
50
-
51
- # @!method compute_if_present
52
- # @!macro map_method_is_atomic
53
-
54
- # @!method compute
55
- # @!macro map_method_is_atomic
56
-
57
- # @!method merge_pair
58
- # @!macro map_method_is_atomic
59
-
60
- # @!method replace_pair
61
- # @!macro map_method_is_atomic
62
-
63
- # @!method replace_if_exists
64
- # @!macro map_method_is_atomic
65
-
66
- # @!method get_and_set
67
- # @!macro map_method_is_atomic
68
-
69
- # @!method delete
70
- # @!macro map_method_is_atomic
71
-
72
- # @!method delete_pair
73
- # @!macro map_method_is_atomic
74
117
 
75
118
  def initialize(options = nil, &block)
76
119
  if options.kind_of?(::Hash)
@@ -83,6 +126,9 @@ module Concurrent
83
126
  @default_proc = block
84
127
  end
85
128
 
129
+ # Get a value with key
130
+ # @param [Object] key
131
+ # @return [Object] the value
86
132
  def [](key)
87
133
  if value = super # non-falsy value is an existing mapping, return it right away
88
134
  value
@@ -98,17 +144,27 @@ module Concurrent
98
144
  end
99
145
 
100
146
  alias_method :get, :[]
147
+ # TODO (pitr-ch 30-Oct-2018): doc
101
148
  alias_method :put, :[]=
102
149
 
150
+ # Get a value with key, or default_value when key is absent,
151
+ # or fail when no default_value is given.
152
+ # @param [Object] key
153
+ # @param [Object] default_value
154
+ # @yield default value for a key
155
+ # @yieldparam key [Object]
156
+ # @yieldreturn [Object] default value
157
+ # @return [Object] the value or default value
158
+ # @raise [KeyError] when key is missing and no default_value is provided
103
159
  # @!macro map_method_not_atomic
104
- # The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended
105
- # to be use as a concurrency primitive with strong happens-before
106
- # guarantees. It is not intended to be used as a high-level abstraction
107
- # supporting complex operations. All read and write operations are
108
- # thread safe, but no guarantees are made regarding race conditions
109
- # between the fetch operation and yielding to the block. Additionally,
110
- # this method does not support recursion. This is due to internal
111
- # constraints that are very unlikely to change in the near future.
160
+ # @note The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended
161
+ # to be use as a concurrency primitive with strong happens-before
162
+ # guarantees. It is not intended to be used as a high-level abstraction
163
+ # supporting complex operations. All read and write operations are
164
+ # thread safe, but no guarantees are made regarding race conditions
165
+ # between the fetch operation and yielding to the block. Additionally,
166
+ # this method does not support recursion. This is due to internal
167
+ # constraints that are very unlikely to change in the near future.
112
168
  def fetch(key, default_value = NULL)
113
169
  if NULL != (value = get_or_default(key, NULL))
114
170
  value
@@ -121,23 +177,39 @@ module Concurrent
121
177
  end
122
178
  end
123
179
 
124
- # @!macro map_method_not_atomic
180
+ # Fetch value with key, or store default value when key is absent,
181
+ # or fail when no default_value is given. This is a two step operation,
182
+ # therefore not atomic. The store can overwrite other concurrently
183
+ # stored value.
184
+ # @param [Object] key
185
+ # @param [Object] default_value
186
+ # @yield default value for a key
187
+ # @yieldparam key [Object]
188
+ # @yieldreturn [Object] default value
189
+ # @return [Object] the value or default value
190
+ # @!macro map.atomic_method_with_block
125
191
  def fetch_or_store(key, default_value = NULL)
126
192
  fetch(key) do
127
193
  put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value))
128
194
  end
129
195
  end
130
196
 
131
- # @!macro map_method_is_atomic
197
+ # Insert value into map with key if key is absent in one atomic step.
198
+ # @param [Object] key
199
+ # @param [Object] value
200
+ # @return [Object, nil] the value or nil when key was present
132
201
  def put_if_absent(key, value)
133
202
  computed = false
134
- result = compute_if_absent(key) do
203
+ result = compute_if_absent(key) do
135
204
  computed = true
136
205
  value
137
206
  end
138
207
  computed ? nil : result
139
208
  end unless method_defined?(:put_if_absent)
140
209
 
210
+ # Is the value stored in the map. Iterates over all values.
211
+ # @param [Object] value
212
+ # @return [true, false]
141
213
  def value?(value)
142
214
  each_value do |v|
143
215
  return true if value.equal?(v)
@@ -145,26 +217,46 @@ module Concurrent
145
217
  false
146
218
  end
147
219
 
220
+ # All keys
221
+ # @return [::Array<Object>] keys
148
222
  def keys
149
223
  arr = []
150
- each_pair {|k, v| arr << k}
224
+ each_pair { |k, v| arr << k }
151
225
  arr
152
226
  end unless method_defined?(:keys)
153
227
 
228
+ # All values
229
+ # @return [::Array<Object>] values
154
230
  def values
155
231
  arr = []
156
- each_pair {|k, v| arr << v}
232
+ each_pair { |k, v| arr << v }
157
233
  arr
158
234
  end unless method_defined?(:values)
159
235
 
236
+ # Iterates over each key.
237
+ # @yield for each key in the map
238
+ # @yieldparam key [Object]
239
+ # @return [self]
240
+ # @!macro map.atomic_method_with_block
160
241
  def each_key
161
- each_pair {|k, v| yield k}
242
+ each_pair { |k, v| yield k }
162
243
  end unless method_defined?(:each_key)
163
244
 
245
+ # Iterates over each value.
246
+ # @yield for each value in the map
247
+ # @yieldparam value [Object]
248
+ # @return [self]
249
+ # @!macro map.atomic_method_with_block
164
250
  def each_value
165
- each_pair {|k, v| yield v}
251
+ each_pair { |k, v| yield v }
166
252
  end unless method_defined?(:each_value)
167
253
 
254
+ # Iterates over each key value pair.
255
+ # @yield for each key value pair in the map
256
+ # @yieldparam key [Object]
257
+ # @yieldparam value [Object]
258
+ # @return [self]
259
+ # @!macro map.atomic_method_with_block
168
260
  def each_pair
169
261
  return enum_for :each_pair unless block_given?
170
262
  super
@@ -172,30 +264,39 @@ module Concurrent
172
264
 
173
265
  alias_method :each, :each_pair unless method_defined?(:each)
174
266
 
267
+ # Find key of a value.
268
+ # @param [Object] value
269
+ # @return [Object, nil] key or nil when not found
175
270
  def key(value)
176
- each_pair {|k, v| return k if v == value}
271
+ each_pair { |k, v| return k if v == value }
177
272
  nil
178
273
  end unless method_defined?(:key)
179
274
  alias_method :index, :key if RUBY_VERSION < '1.9'
180
275
 
276
+ # Is map empty?
277
+ # @return [true, false]
181
278
  def empty?
182
- each_pair {|k, v| return false}
279
+ each_pair { |k, v| return false }
183
280
  true
184
281
  end unless method_defined?(:empty?)
185
282
 
283
+ # The size of map.
284
+ # @return [Integer] size
186
285
  def size
187
286
  count = 0
188
- each_pair {|k, v| count += 1}
287
+ each_pair { |k, v| count += 1 }
189
288
  count
190
289
  end unless method_defined?(:size)
191
290
 
291
+ # @!visibility private
192
292
  def marshal_dump
193
293
  raise TypeError, "can't dump hash with default proc" if @default_proc
194
294
  h = {}
195
- each_pair {|k, v| h[k] = v}
295
+ each_pair { |k, v| h[k] = v }
196
296
  h
197
297
  end
198
298
 
299
+ # @!visibility private
199
300
  def marshal_load(hash)
200
301
  initialize
201
302
  populate_from(hash)
@@ -209,6 +310,7 @@ module Concurrent
209
310
  end
210
311
 
211
312
  private
313
+
212
314
  def raise_fetch_no_key
213
315
  raise KeyError, 'key not found'
214
316
  end
@@ -219,7 +321,7 @@ module Concurrent
219
321
  end
220
322
 
221
323
  def populate_from(hash)
222
- hash.each_pair {|k, v| self[k] = v}
324
+ hash.each_pair { |k, v| self[k] = v }
223
325
  self
224
326
  end
225
327
 
@@ -1,5 +1,14 @@
1
1
  require 'concurrent/thread_safe/util'
2
2
 
3
+ # Shim for TruffleRuby.synchronized
4
+ if Concurrent.on_truffleruby? && !TruffleRuby.respond_to?(:synchronized)
5
+ module TruffleRuby
6
+ def self.synchronized(object, &block)
7
+ Truffle::System.synchronized(object, &block)
8
+ end
9
+ end
10
+ end
11
+
3
12
  module Concurrent
4
13
  module ThreadSafe
5
14
  module Util
@@ -44,8 +53,7 @@ module Concurrent
44
53
  klass.superclass.instance_methods(false).each do |method|
45
54
  klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
46
55
  def #{method}(*args, &block)
47
- # TODO (pitr-ch 01-Jul-2018): don't use internal TruffleRuby APIs
48
- Truffle::System.synchronized(self) { super(*args, &block) }
56
+ TruffleRuby.synchronized(self) { super(*args, &block) }
49
57
  end
50
58
  RUBY
51
59
  end
@@ -0,0 +1,17 @@
1
+ require_relative 'engine'
2
+
3
+ if Concurrent.ruby_version :<, 2, 0, 0
4
+ # @!visibility private
5
+ module Kernel
6
+ def __dir__
7
+ File.dirname __FILE__
8
+ end
9
+ end
10
+
11
+ # @!visibility private
12
+ class LoadError < ScriptError
13
+ def path
14
+ message.split(' -- ').last
15
+ end
16
+ end
17
+ end
@@ -8,7 +8,7 @@ module Concurrent
8
8
  end
9
9
 
10
10
  def on_jruby_9000?
11
- on_jruby? && ruby_version(:>=, 9, 0, 0, JRUBY_VERSION)
11
+ on_jruby? && ruby_version(JRUBY_VERSION, :>=, 9, 0, 0)
12
12
  end
13
13
 
14
14
  def on_cruby?
@@ -39,7 +39,7 @@ module Concurrent
39
39
  defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
40
40
  end
41
41
 
42
- def ruby_version(comparison, major, minor, patch, version = RUBY_VERSION)
42
+ def ruby_version(version = RUBY_VERSION, comparison, major, minor, patch)
43
43
  result = (version.split('.').map(&:to_i) <=> [major, minor, patch])
44
44
  comparisons = { :== => [0],
45
45
  :>= => [1, 0],
@@ -1,4 +1,4 @@
1
1
  module Concurrent
2
- VERSION = '1.1.0.pre2'
3
- EDGE_VERSION = '0.4.0.pre2'
2
+ VERSION = '1.1.1'
3
+ EDGE_VERSION = '0.4.1'
4
4
  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.0.pre2
4
+ version: 1.1.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: 2018-09-18 00:00:00.000000000 Z
13
+ date: 2018-11-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.
@@ -157,6 +157,7 @@ files:
157
157
  - lib/concurrent/timer_task.rb
158
158
  - lib/concurrent/tuple.rb
159
159
  - lib/concurrent/tvar.rb
160
+ - lib/concurrent/utility/193.rb
160
161
  - lib/concurrent/utility/at_exit.rb
161
162
  - lib/concurrent/utility/engine.rb
162
163
  - lib/concurrent/utility/monotonic_time.rb
@@ -176,12 +177,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
176
177
  requirements:
177
178
  - - ">="
178
179
  - !ruby/object:Gem::Version
179
- version: 2.0.0
180
+ version: 1.9.3
180
181
  required_rubygems_version: !ruby/object:Gem::Requirement
181
182
  requirements:
182
- - - ">"
183
+ - - ">="
183
184
  - !ruby/object:Gem::Version
184
- version: 1.3.1
185
+ version: '0'
185
186
  requirements: []
186
187
  rubyforge_project:
187
188
  rubygems_version: 2.7.3