concurrent-ruby 1.1.5 → 1.2.2
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 +4 -4
- data/CHANGELOG.md +84 -1
- data/Gemfile +5 -10
- data/{LICENSE.md → LICENSE.txt} +18 -20
- data/README.md +55 -31
- data/Rakefile +84 -92
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
- data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
- data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +6 -16
- data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +10 -20
- data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +7 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +5 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +3 -0
- data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +135 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +3 -3
- data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +1 -0
- data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
- data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +11 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +11 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +19 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +9 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +32 -14
- data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +111 -0
- data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +15 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +3 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +16 -8
- data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
- data/lib/concurrent-ruby/concurrent/concern/logging.rb +116 -0
- data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent-ruby/concurrent/configuration.rb +105 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +5 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +34 -37
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +29 -15
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +21 -9
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +19 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +46 -42
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +6 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +5 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +1 -10
- data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +10 -2
- data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +44 -31
- data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +13 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +2 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +7 -6
- data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +30 -17
- data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +17 -19
- data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +13 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +1 -3
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +11 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
- data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +3 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +8 -7
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +18 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +12 -44
- data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
- data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +101 -0
- data/lib/concurrent-ruby/concurrent/synchronization.rb +13 -0
- data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +47 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +2 -39
- data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +52 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +11 -34
- data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -5
- data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +21 -57
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +5 -16
- data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +19 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +8 -10
- data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +1 -0
- data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +110 -0
- data/lib/concurrent-ruby/concurrent/version.rb +3 -0
- data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
- metadata +127 -129
- data/lib/concurrent/atomic/abstract_thread_local_var.rb +0 -66
- data/lib/concurrent/atomic/atomic_reference.rb +0 -204
- data/lib/concurrent/atomic/java_thread_local_var.rb +0 -37
- data/lib/concurrent/atomic/ruby_thread_local_var.rb +0 -161
- data/lib/concurrent/atomic/thread_local_var.rb +0 -104
- data/lib/concurrent/concern/logging.rb +0 -32
- data/lib/concurrent/concurrent_ruby.jar +0 -0
- data/lib/concurrent/configuration.rb +0 -184
- data/lib/concurrent/synchronization/jruby_object.rb +0 -45
- data/lib/concurrent/synchronization/mri_object.rb +0 -44
- data/lib/concurrent/synchronization/rbx_lockable_object.rb +0 -65
- data/lib/concurrent/synchronization/rbx_object.rb +0 -49
- data/lib/concurrent/synchronization/truffleruby_object.rb +0 -47
- data/lib/concurrent/synchronization/volatile.rb +0 -36
- data/lib/concurrent/synchronization.rb +0 -30
- data/lib/concurrent/thread_safe/synchronized_delegator.rb +0 -50
- data/lib/concurrent/thread_safe/util/data_structures.rb +0 -63
- data/lib/concurrent/utility/at_exit.rb +0 -97
- data/lib/concurrent/utility/monotonic_time.rb +0 -58
- data/lib/concurrent/utility/processor_counter.rb +0 -158
- data/lib/concurrent/version.rb +0 -3
- data/lib/concurrent-ruby.rb +0 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
- data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
- /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
- /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
- /data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
data/Rakefile
CHANGED
@@ -1,14 +1,6 @@
|
|
1
|
-
require_relative 'lib/concurrent/version'
|
2
|
-
require_relative 'lib/concurrent/
|
3
|
-
|
4
|
-
if Concurrent.ruby_version :<, 2, 0, 0
|
5
|
-
# @!visibility private
|
6
|
-
module Kernel
|
7
|
-
def __dir__
|
8
|
-
File.dirname __FILE__
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
1
|
+
require_relative 'lib/concurrent-ruby/concurrent/version'
|
2
|
+
require_relative 'lib/concurrent-ruby-edge/concurrent/edge/version'
|
3
|
+
require_relative 'lib/concurrent-ruby/concurrent/utility/engine'
|
12
4
|
|
13
5
|
core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
|
14
6
|
ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
|
@@ -16,17 +8,19 @@ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.
|
|
16
8
|
|
17
9
|
require 'rake/javaextensiontask'
|
18
10
|
|
11
|
+
ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && !Concurrent.on_jruby?
|
12
|
+
|
19
13
|
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
|
20
14
|
ext.ext_dir = 'ext/concurrent-ruby'
|
21
|
-
ext.lib_dir = 'lib/concurrent'
|
15
|
+
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
22
16
|
end
|
23
17
|
|
24
|
-
unless Concurrent.on_jruby?
|
18
|
+
unless Concurrent.on_jruby? || Concurrent.on_truffleruby?
|
25
19
|
require 'rake/extensiontask'
|
26
20
|
|
27
21
|
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
|
28
22
|
ext.ext_dir = 'ext/concurrent-ruby-ext'
|
29
|
-
ext.lib_dir = 'lib/concurrent'
|
23
|
+
ext.lib_dir = 'lib/concurrent-ruby/concurrent'
|
30
24
|
ext.source_pattern = '*.{c,h}'
|
31
25
|
|
32
26
|
ext.cross_compile = true
|
@@ -40,13 +34,21 @@ namespace :repackage do
|
|
40
34
|
task :all do
|
41
35
|
Dir.chdir(__dir__) do
|
42
36
|
# store gems in vendor cache for docker
|
43
|
-
|
37
|
+
Bundler.with_original_env do
|
38
|
+
sh 'bundle package'
|
39
|
+
end
|
44
40
|
|
45
41
|
# build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
|
46
|
-
Rake::Task['lib/concurrent/concurrent_ruby.jar'].invoke
|
42
|
+
Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
|
47
43
|
|
48
44
|
# build all gem files
|
49
|
-
|
45
|
+
%w[x86-mingw32 x64-mingw32].each do |plat|
|
46
|
+
RakeCompilerDock.sh(
|
47
|
+
"bundle install --local && bundle exec rake native:#{plat} gem --trace",
|
48
|
+
platform: plat,
|
49
|
+
options: ['--privileged'], # otherwise the directory in the image is empty
|
50
|
+
runas: false)
|
51
|
+
end
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -58,7 +60,10 @@ Gem::PackageTask.new(core_gemspec) {} if core_gemspec
|
|
58
60
|
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby?
|
59
61
|
Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
|
60
62
|
|
61
|
-
CLEAN.include(
|
63
|
+
CLEAN.include(
|
64
|
+
'lib/concurrent-ruby/concurrent/concurrent_ruby_ext.*',
|
65
|
+
'lib/concurrent-ruby/concurrent/2.*',
|
66
|
+
'lib/concurrent-ruby/concurrent/*.jar')
|
62
67
|
|
63
68
|
begin
|
64
69
|
require 'rspec'
|
@@ -72,20 +77,21 @@ begin
|
|
72
77
|
options = %w[ --color
|
73
78
|
--backtrace
|
74
79
|
--order defined
|
75
|
-
--format documentation
|
76
|
-
--tag ~notravis ]
|
80
|
+
--format documentation ]
|
77
81
|
t.rspec_opts = [*options].join(' ')
|
78
82
|
end
|
79
83
|
|
80
84
|
desc '* test packaged and installed gems instead of local files'
|
81
85
|
task :installed do
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
Bundler.with_original_env do
|
87
|
+
Dir.chdir(__dir__) do
|
88
|
+
sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
|
89
|
+
sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
|
90
|
+
sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
|
91
|
+
ENV['NO_PATH'] = 'true'
|
92
|
+
sh 'bundle update'
|
93
|
+
sh 'bundle exec rake spec:ci'
|
94
|
+
end
|
89
95
|
end
|
90
96
|
end
|
91
97
|
end
|
@@ -93,6 +99,19 @@ begin
|
|
93
99
|
desc 'executed in CI'
|
94
100
|
task :ci => [:compile, 'spec:ci']
|
95
101
|
|
102
|
+
desc 'run each spec file in a separate process to help find missing requires'
|
103
|
+
task 'spec:isolated' do
|
104
|
+
glob = "#{ENV['DIR'] || 'spec'}/**/*_spec.rb"
|
105
|
+
from = ENV['FROM']
|
106
|
+
env = { 'ISOLATED' => 'true' }
|
107
|
+
Dir[glob].each do |spec|
|
108
|
+
next if from and from != spec
|
109
|
+
from = nil if from == spec
|
110
|
+
|
111
|
+
sh env, 'rspec', spec
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
96
115
|
task :default => [:clobber, :compile, :spec]
|
97
116
|
rescue LoadError => e
|
98
117
|
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
|
@@ -130,7 +149,7 @@ begin
|
|
130
149
|
task :update_readme do
|
131
150
|
Dir.chdir __dir__ do
|
132
151
|
content = File.read(File.join('README.md')).
|
133
|
-
|
152
|
+
gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
|
134
153
|
case $1
|
135
154
|
when 'LockFreeLinkedSet'
|
136
155
|
"{Concurrent::Edge::#{$1} #{$1}}"
|
@@ -160,20 +179,22 @@ begin
|
|
160
179
|
desc "* of #{name} into subdir #{name}"
|
161
180
|
YARD::Rake::YardocTask.new(name) do |yard|
|
162
181
|
yard.options.push(
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
yard.files = ['./lib/**/*.rb',
|
167
|
-
'./lib-edge/**/*.rb',
|
182
|
+
'--output-dir', output_dir,
|
183
|
+
'--main', 'tmp/README.md',
|
184
|
+
*common_yard_options)
|
185
|
+
yard.files = ['./lib/concurrent-ruby/**/*.rb',
|
186
|
+
'./lib/concurrent-ruby-edge/**/*.rb',
|
168
187
|
'./ext/concurrent_ruby_ext/**/*.c',
|
169
188
|
'-',
|
170
189
|
'docs-source/thread_pools.md',
|
171
190
|
'docs-source/promises.out.md',
|
172
191
|
'docs-source/medium-example.out.rb',
|
173
|
-
'LICENSE.
|
192
|
+
'LICENSE.txt',
|
174
193
|
'CHANGELOG.md']
|
175
194
|
end
|
176
|
-
Rake::Task[name].prerequisites.push removal_name,
|
195
|
+
Rake::Task[name].prerequisites.push removal_name,
|
196
|
+
# 'yard:eval_md',
|
197
|
+
'yard:update_readme'
|
177
198
|
end
|
178
199
|
|
179
200
|
define_yard_task.call current_yard_version_name
|
@@ -182,39 +203,11 @@ begin
|
|
182
203
|
desc "* signpost for versions"
|
183
204
|
YARD::Rake::YardocTask.new(:signpost) do |yard|
|
184
205
|
yard.options.push(
|
185
|
-
|
186
|
-
|
187
|
-
|
206
|
+
'--output-dir', 'docs',
|
207
|
+
'--main', 'docs-source/signpost.md',
|
208
|
+
*common_yard_options)
|
188
209
|
yard.files = ['no-lib']
|
189
210
|
end
|
190
|
-
|
191
|
-
define_uptodate_task = -> name do
|
192
|
-
namespace name do
|
193
|
-
desc "** ensure that #{name} generated documentation is matching the source code"
|
194
|
-
task :uptodate do
|
195
|
-
Dir.chdir(__dir__) do
|
196
|
-
begin
|
197
|
-
FileUtils.cp_r 'docs', 'docs-copy', verbose: true
|
198
|
-
Rake::Task["yard:#{name}"].invoke
|
199
|
-
sh 'diff -r docs/ docs-copy/' do |ok, res|
|
200
|
-
unless ok
|
201
|
-
begin
|
202
|
-
STDOUT.puts 'Command failed. Continue? (y/n)'
|
203
|
-
input = STDIN.gets.strip.downcase
|
204
|
-
end until %w(y n).include?(input)
|
205
|
-
exit 1 if input == 'n'
|
206
|
-
end
|
207
|
-
end
|
208
|
-
ensure
|
209
|
-
FileUtils.rm_rf 'docs-copy', verbose: true
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
define_uptodate_task.call current_yard_version_name
|
217
|
-
define_uptodate_task.call 'master'
|
218
211
|
end
|
219
212
|
|
220
213
|
rescue LoadError => e
|
@@ -227,15 +220,13 @@ task :release => ['release:checks', 'release:build', 'release:test', 'release:pu
|
|
227
220
|
namespace :release do
|
228
221
|
# Depends on environment of @pitr-ch
|
229
222
|
|
230
|
-
|
231
|
-
jruby_version = 'jruby-9.1.17.1'
|
232
|
-
|
233
|
-
task :checks => "yard:#{current_yard_version_name}:uptodate" do
|
223
|
+
task :checks do
|
234
224
|
Dir.chdir(__dir__) do
|
235
225
|
sh 'test -z "$(git status --porcelain)"' do |ok, res|
|
236
226
|
unless ok
|
237
227
|
begin
|
238
|
-
|
228
|
+
status = `git status --porcelain`
|
229
|
+
STDOUT.puts 'There are local changes that you might want to commit.', status, 'Continue? (y/n)'
|
239
230
|
input = STDIN.gets.strip.downcase
|
240
231
|
end until %w(y n).include?(input)
|
241
232
|
exit 1 if input == 'n'
|
@@ -243,10 +234,10 @@ namespace :release do
|
|
243
234
|
end
|
244
235
|
sh 'git fetch'
|
245
236
|
sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
|
246
|
-
|
237
|
+
'$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
|
247
238
|
unless ok
|
248
239
|
begin
|
249
|
-
STDOUT.puts '
|
240
|
+
STDOUT.puts 'Local master branch is not pushed to origin.', 'Continue? (y/n)'
|
250
241
|
input = STDIN.gets.strip.downcase
|
251
242
|
end until %w(y n).include?(input)
|
252
243
|
exit 1 if input == 'n'
|
@@ -261,19 +252,18 @@ namespace :release do
|
|
261
252
|
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
|
262
253
|
task :test do
|
263
254
|
Dir.chdir(__dir__) do
|
264
|
-
|
255
|
+
puts "Testing with the installed gem"
|
265
256
|
|
266
|
-
|
267
|
-
|
268
|
-
|
257
|
+
Bundler.with_original_env do
|
258
|
+
sh 'ruby -v'
|
259
|
+
sh 'bundle exec rake spec:installed'
|
269
260
|
|
270
|
-
|
271
|
-
|
272
|
-
|
261
|
+
env = { "PATH" => "#{ENV['CONCURRENT_JRUBY_HOME']}/bin:#{ENV['PATH']}" }
|
262
|
+
sh env, 'ruby -v'
|
263
|
+
sh env, 'bundle exec rake spec:installed'
|
264
|
+
end
|
273
265
|
|
274
266
|
puts 'Windows build is untested'
|
275
|
-
|
276
|
-
ENV['RBENV_VERSION'] = old
|
277
267
|
end
|
278
268
|
end
|
279
269
|
|
@@ -281,44 +271,46 @@ namespace :release do
|
|
281
271
|
task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
|
282
272
|
|
283
273
|
namespace :publish do
|
274
|
+
publish_base = true
|
284
275
|
publish_edge = false
|
285
276
|
|
286
277
|
task :ask do
|
287
278
|
begin
|
288
|
-
STDOUT.puts 'Do you want to publish anything? (y/n)'
|
279
|
+
STDOUT.puts 'Do you want to publish anything now? (y/n)'
|
289
280
|
input = STDIN.gets.strip.downcase
|
290
281
|
end until %w(y n).include?(input)
|
291
282
|
exit 1 if input == 'n'
|
292
283
|
begin
|
293
|
-
STDOUT.puts 'Do you want to publish edge
|
284
|
+
STDOUT.puts 'It will publish `concurrent-ruby`. Do you want to publish `concurrent-ruby-edge`? (y/n)'
|
294
285
|
input = STDIN.gets.strip.downcase
|
295
286
|
end until %w(y n).include?(input)
|
296
287
|
publish_edge = input == 'y'
|
297
288
|
end
|
298
289
|
|
299
290
|
desc '** tag HEAD with current version and push to github'
|
300
|
-
task :tag do
|
291
|
+
task :tag => :ask do
|
301
292
|
Dir.chdir(__dir__) do
|
302
|
-
sh "git tag v#{Concurrent::VERSION}"
|
303
|
-
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
|
304
295
|
sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
|
305
296
|
sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
|
306
297
|
end
|
307
298
|
end
|
308
299
|
|
309
300
|
desc '** push all *.gem files to rubygems'
|
310
|
-
task :rubygems do
|
301
|
+
task :rubygems => :ask do
|
311
302
|
Dir.chdir(__dir__) do
|
312
|
-
sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
|
303
|
+
sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem" if publish_base
|
313
304
|
sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
|
314
|
-
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem"
|
315
|
-
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem"
|
316
|
-
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
|
317
308
|
end
|
318
309
|
end
|
319
310
|
|
320
311
|
desc '** print post release steps'
|
321
312
|
task :post_steps do
|
313
|
+
# TODO: (petr 05-Jun-2021) automate and renew the process
|
322
314
|
puts 'Manually: create a release on GitHub with relevant changelog part'
|
323
315
|
puts 'Manually: send email same as release with relevant changelog part'
|
324
316
|
puts 'Manually: tweet'
|
File without changes
|
@@ -10,6 +10,7 @@ import org.jruby.RubyNumeric;
|
|
10
10
|
import org.jruby.RubyObject;
|
11
11
|
import org.jruby.anno.JRubyClass;
|
12
12
|
import org.jruby.anno.JRubyMethod;
|
13
|
+
import org.jruby.runtime.Block;
|
13
14
|
import org.jruby.runtime.ObjectAllocator;
|
14
15
|
import org.jruby.runtime.ThreadContext;
|
15
16
|
import org.jruby.runtime.builtin.IRubyObject;
|
@@ -45,9 +46,13 @@ public class JavaSemaphoreLibrary {
|
|
45
46
|
}
|
46
47
|
|
47
48
|
@JRubyMethod
|
48
|
-
public IRubyObject acquire(ThreadContext context,
|
49
|
-
this.
|
50
|
-
|
49
|
+
public IRubyObject acquire(ThreadContext context, final Block block) throws InterruptedException {
|
50
|
+
return this.acquire(context, 1, block);
|
51
|
+
}
|
52
|
+
|
53
|
+
@JRubyMethod
|
54
|
+
public IRubyObject acquire(ThreadContext context, IRubyObject permits, final Block block) throws InterruptedException {
|
55
|
+
return this.acquire(context, rubyFixnumToPositiveInt(permits, "permits"), block);
|
51
56
|
}
|
52
57
|
|
53
58
|
@JRubyMethod(name = "available_permits")
|
@@ -60,30 +65,32 @@ public class JavaSemaphoreLibrary {
|
|
60
65
|
return getRuntime().newFixnum(this.semaphore.drainPermits());
|
61
66
|
}
|
62
67
|
|
63
|
-
@JRubyMethod
|
64
|
-
public IRubyObject acquire(ThreadContext context) throws InterruptedException {
|
65
|
-
this.semaphore.acquire(1);
|
66
|
-
return context.nil;
|
67
|
-
}
|
68
|
-
|
69
68
|
@JRubyMethod(name = "try_acquire")
|
70
|
-
public IRubyObject tryAcquire(ThreadContext context) throws InterruptedException {
|
71
|
-
|
69
|
+
public IRubyObject tryAcquire(ThreadContext context, final Block block) throws InterruptedException {
|
70
|
+
int permitsInt = 1;
|
71
|
+
boolean acquired = semaphore.tryAcquire(permitsInt);
|
72
|
+
|
73
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
72
74
|
}
|
73
75
|
|
74
76
|
@JRubyMethod(name = "try_acquire")
|
75
|
-
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits) throws InterruptedException {
|
76
|
-
|
77
|
+
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, final Block block) throws InterruptedException {
|
78
|
+
int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
|
79
|
+
boolean acquired = semaphore.tryAcquire(permitsInt);
|
80
|
+
|
81
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
77
82
|
}
|
78
83
|
|
79
84
|
@JRubyMethod(name = "try_acquire")
|
80
|
-
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, IRubyObject timeout) throws InterruptedException {
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, IRubyObject timeout, final Block block) throws InterruptedException {
|
86
|
+
int permitsInt = rubyFixnumToPositiveInt(permits, "permits");
|
87
|
+
boolean acquired = semaphore.tryAcquire(
|
88
|
+
permitsInt,
|
89
|
+
rubyNumericToLong(timeout, "timeout"),
|
90
|
+
java.util.concurrent.TimeUnit.SECONDS
|
91
|
+
);
|
92
|
+
|
93
|
+
return triedAcquire(context, permitsInt, acquired, block);
|
87
94
|
}
|
88
95
|
|
89
96
|
@JRubyMethod
|
@@ -93,8 +100,8 @@ public class JavaSemaphoreLibrary {
|
|
93
100
|
}
|
94
101
|
|
95
102
|
@JRubyMethod
|
96
|
-
public IRubyObject release(ThreadContext context, IRubyObject
|
97
|
-
this.semaphore.release(rubyFixnumToPositiveInt(
|
103
|
+
public IRubyObject release(ThreadContext context, IRubyObject permits) {
|
104
|
+
this.semaphore.release(rubyFixnumToPositiveInt(permits, "permits"));
|
98
105
|
return getRuntime().newBoolean(true);
|
99
106
|
}
|
100
107
|
|
@@ -104,6 +111,29 @@ public class JavaSemaphoreLibrary {
|
|
104
111
|
return context.nil;
|
105
112
|
}
|
106
113
|
|
114
|
+
private IRubyObject acquire(ThreadContext context, int permits, final Block block) throws InterruptedException {
|
115
|
+
this.semaphore.acquire(permits);
|
116
|
+
|
117
|
+
if (!block.isGiven()) return context.nil;
|
118
|
+
|
119
|
+
try {
|
120
|
+
return block.yieldSpecific(context);
|
121
|
+
} finally {
|
122
|
+
this.semaphore.release(permits);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
private IRubyObject triedAcquire(ThreadContext context, int permits, boolean acquired, final Block block) {
|
127
|
+
if (!block.isGiven()) return getRuntime().newBoolean(acquired);
|
128
|
+
if (!acquired) return context.nil;
|
129
|
+
|
130
|
+
try {
|
131
|
+
return block.yieldSpecific(context);
|
132
|
+
} finally {
|
133
|
+
this.semaphore.release(permits);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
107
137
|
private int rubyFixnumInt(IRubyObject value, String paramName) {
|
108
138
|
if (value instanceof RubyFixnum) {
|
109
139
|
RubyFixnum fixNum = (RubyFixnum) value;
|
@@ -55,12 +55,6 @@ public class SynchronizationLibrary implements Library {
|
|
55
55
|
}
|
56
56
|
}
|
57
57
|
|
58
|
-
private static final ObjectAllocator JRUBY_OBJECT_ALLOCATOR = new ObjectAllocator() {
|
59
|
-
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
|
60
|
-
return new JRubyObject(runtime, klazz);
|
61
|
-
}
|
62
|
-
};
|
63
|
-
|
64
58
|
private static final ObjectAllocator OBJECT_ALLOCATOR = new ObjectAllocator() {
|
65
59
|
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
|
66
60
|
return new Object(runtime, klazz);
|
@@ -87,10 +81,7 @@ public class SynchronizationLibrary implements Library {
|
|
87
81
|
RubyModule jrubyAttrVolatileModule = synchronizationModule.defineModuleUnder("JRubyAttrVolatile");
|
88
82
|
jrubyAttrVolatileModule.defineAnnotatedMethods(JRubyAttrVolatile.class);
|
89
83
|
|
90
|
-
defineClass(runtime, synchronizationModule, "AbstractObject", "
|
91
|
-
JRubyObject.class, JRUBY_OBJECT_ALLOCATOR);
|
92
|
-
|
93
|
-
defineClass(runtime, synchronizationModule, "JRubyObject", "Object",
|
84
|
+
defineClass(runtime, synchronizationModule, "AbstractObject", "Object",
|
94
85
|
Object.class, OBJECT_ALLOCATOR);
|
95
86
|
|
96
87
|
defineClass(runtime, synchronizationModule, "Object", "AbstractLockableObject",
|
@@ -143,8 +134,8 @@ public class SynchronizationLibrary implements Library {
|
|
143
134
|
// attempt to avoid code elimination.
|
144
135
|
private static volatile int volatileField;
|
145
136
|
|
146
|
-
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
|
147
|
-
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject
|
137
|
+
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC, module = true)
|
138
|
+
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject module) {
|
148
139
|
// Prevent reordering of ivar writes with publication of this instance
|
149
140
|
if (!FULL_FENCE) {
|
150
141
|
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
|
@@ -158,9 +149,10 @@ public class SynchronizationLibrary implements Library {
|
|
158
149
|
return context.nil;
|
159
150
|
}
|
160
151
|
|
161
|
-
@JRubyMethod(name = "instance_variable_get_volatile", visibility = Visibility.PUBLIC)
|
152
|
+
@JRubyMethod(name = "instance_variable_get_volatile", visibility = Visibility.PUBLIC, module = true)
|
162
153
|
public static IRubyObject instanceVariableGetVolatile(
|
163
154
|
ThreadContext context,
|
155
|
+
IRubyObject module,
|
164
156
|
IRubyObject self,
|
165
157
|
IRubyObject name) {
|
166
158
|
// Ensure we ses latest value with loadFence
|
@@ -174,9 +166,10 @@ public class SynchronizationLibrary implements Library {
|
|
174
166
|
}
|
175
167
|
}
|
176
168
|
|
177
|
-
@JRubyMethod(name = "instance_variable_set_volatile", visibility = Visibility.PUBLIC)
|
169
|
+
@JRubyMethod(name = "instance_variable_set_volatile", visibility = Visibility.PUBLIC, module = true)
|
178
170
|
public static IRubyObject InstanceVariableSetVolatile(
|
179
171
|
ThreadContext context,
|
172
|
+
IRubyObject module,
|
180
173
|
IRubyObject self,
|
181
174
|
IRubyObject name,
|
182
175
|
IRubyObject value) {
|
@@ -195,16 +188,8 @@ public class SynchronizationLibrary implements Library {
|
|
195
188
|
}
|
196
189
|
}
|
197
190
|
|
198
|
-
@JRubyClass(name = "
|
199
|
-
public static class
|
200
|
-
|
201
|
-
public JRubyObject(Ruby runtime, RubyClass metaClass) {
|
202
|
-
super(runtime, metaClass);
|
203
|
-
}
|
204
|
-
}
|
205
|
-
|
206
|
-
@JRubyClass(name = "Object", parent = "JRubyObject")
|
207
|
-
public static class Object extends JRubyObject {
|
191
|
+
@JRubyClass(name = "Object", parent = "AbstractObject")
|
192
|
+
public static class Object extends RubyObject {
|
208
193
|
|
209
194
|
public Object(Ruby runtime, RubyClass metaClass) {
|
210
195
|
super(runtime, metaClass);
|
@@ -220,7 +205,7 @@ public class SynchronizationLibrary implements Library {
|
|
220
205
|
}
|
221
206
|
|
222
207
|
@JRubyClass(name = "JRubyLockableObject", parent = "AbstractLockableObject")
|
223
|
-
public static class JRubyLockableObject extends
|
208
|
+
public static class JRubyLockableObject extends AbstractLockableObject {
|
224
209
|
|
225
210
|
public JRubyLockableObject(Ruby runtime, RubyClass metaClass) {
|
226
211
|
super(runtime, metaClass);
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'concurrent/configuration'
|
2
2
|
require 'concurrent/atomic/atomic_reference'
|
3
|
+
require 'concurrent/atomic/count_down_latch'
|
3
4
|
require 'concurrent/atomic/thread_local_var'
|
4
5
|
require 'concurrent/collection/copy_on_write_observer_set'
|
5
6
|
require 'concurrent/concern/observable'
|
6
|
-
require 'concurrent/synchronization'
|
7
|
+
require 'concurrent/synchronization/lockable_object'
|
7
8
|
|
8
9
|
module Concurrent
|
9
10
|
|
@@ -10,13 +10,13 @@ module Concurrent
|
|
10
10
|
# or writing at a time. This includes iteration methods like `#each`.
|
11
11
|
#
|
12
12
|
# @note `a += b` is **not** a **thread-safe** operation on
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
13
|
+
# `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array`
|
14
|
+
# which is concatenation of `a` and `b`, then it writes the concatenation to `a`.
|
15
|
+
# The read and write are independent operations they do not form a single atomic
|
16
|
+
# operation therefore when two `+=` operations are executed concurrently updates
|
17
|
+
# may be lost. Use `#concat` instead.
|
18
18
|
#
|
19
|
-
# @see http://ruby-doc.org/core
|
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
|
@@ -34,16 +34,6 @@ module Concurrent
|
|
34
34
|
end
|
35
35
|
JRubyArray
|
36
36
|
|
37
|
-
when Concurrent.on_rbx?
|
38
|
-
require 'monitor'
|
39
|
-
require 'concurrent/thread_safe/util/data_structures'
|
40
|
-
|
41
|
-
class RbxArray < ::Array
|
42
|
-
end
|
43
|
-
|
44
|
-
ThreadSafe::Util.make_synchronized_on_rbx RbxArray
|
45
|
-
RbxArray
|
46
|
-
|
47
37
|
when Concurrent.on_truffleruby?
|
48
38
|
require 'concurrent/thread_safe/util/data_structures'
|
49
39
|
|
@@ -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
|
@@ -292,6 +272,7 @@ module Concurrent
|
|
292
272
|
obj.send(:init_synchronization)
|
293
273
|
obj
|
294
274
|
end
|
275
|
+
ruby2_keywords :new if respond_to?(:ruby2_keywords, true)
|
295
276
|
end
|
296
277
|
private_constant :ClassMethods
|
297
278
|
|
@@ -309,6 +290,7 @@ module Concurrent
|
|
309
290
|
@delegate = delegate
|
310
291
|
@queue = []
|
311
292
|
@executor = Concurrent.global_io_executor
|
293
|
+
@ruby_pid = $$
|
312
294
|
end
|
313
295
|
|
314
296
|
# Delegates method calls to the wrapped object.
|
@@ -326,6 +308,7 @@ module Concurrent
|
|
326
308
|
|
327
309
|
ivar = Concurrent::IVar.new
|
328
310
|
synchronize do
|
311
|
+
reset_if_forked
|
329
312
|
@queue.push [ivar, method, args, block]
|
330
313
|
@executor.post { perform } if @queue.length == 1
|
331
314
|
end
|
@@ -361,6 +344,13 @@ module Concurrent
|
|
361
344
|
end
|
362
345
|
end
|
363
346
|
end
|
347
|
+
|
348
|
+
def reset_if_forked
|
349
|
+
if $$ != @ruby_pid
|
350
|
+
@queue.clear
|
351
|
+
@ruby_pid = $$
|
352
|
+
end
|
353
|
+
end
|
364
354
|
end
|
365
355
|
private_constant :AsyncDelegator
|
366
356
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'concurrent/atomic/atomic_reference'
|
2
2
|
require 'concurrent/collection/copy_on_notify_observer_set'
|
3
3
|
require 'concurrent/concern/observable'
|
4
|
-
require 'concurrent/synchronization'
|
4
|
+
require 'concurrent/synchronization/object'
|
5
5
|
|
6
6
|
# @!macro thread_safe_variable_comparison
|
7
7
|
#
|
@@ -18,7 +18,7 @@ require 'concurrent/synchronization'
|
|
18
18
|
# uncoordinated, *synchronous* change of individual values. Best used when
|
19
19
|
# the value will undergo frequent reads but only occasional, though complex,
|
20
20
|
# updates. Suitable when the result of an update must be known immediately.
|
21
|
-
# * *{Concurrent::AtomicReference}:* A simple object reference that can be
|
21
|
+
# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated
|
22
22
|
# atomically. Updates are synchronous but fast. Best used when updates a
|
23
23
|
# simple set operations. Not suitable when updates are complex.
|
24
24
|
# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar
|