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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +84 -1
  3. data/Gemfile +5 -10
  4. data/{LICENSE.md → LICENSE.txt} +18 -20
  5. data/README.md +55 -31
  6. data/Rakefile +84 -92
  7. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  10. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +2 -1
  11. data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +6 -16
  12. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +10 -20
  13. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +2 -2
  14. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +7 -6
  15. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +5 -4
  16. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +3 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +135 -0
  18. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  19. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +3 -3
  20. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  21. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +1 -0
  22. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
  23. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +11 -5
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +11 -5
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -1
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +19 -3
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +9 -9
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +32 -14
  31. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +111 -0
  32. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +15 -4
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +2 -0
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +3 -3
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +16 -8
  39. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
  42. data/lib/concurrent-ruby/concurrent/concern/logging.rb +116 -0
  43. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  44. data/lib/concurrent-ruby/concurrent/configuration.rb +105 -0
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +2 -2
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +5 -0
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +1 -0
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +34 -37
  49. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +29 -15
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +21 -9
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +19 -2
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +46 -42
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +6 -6
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +1 -1
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +5 -2
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +0 -1
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +1 -10
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +10 -2
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +2 -1
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +44 -31
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +13 -3
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +1 -1
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +2 -1
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +7 -6
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +2 -0
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +30 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +17 -19
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +13 -3
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -1
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +1 -3
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +11 -0
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  81. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +3 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +8 -7
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +18 -5
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +12 -44
  87. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  88. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +101 -0
  89. data/lib/concurrent-ruby/concurrent/synchronization.rb +13 -0
  90. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +47 -0
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +2 -39
  92. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +52 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +11 -34
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -5
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +21 -57
  97. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +5 -16
  98. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +19 -0
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +8 -10
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +1 -0
  101. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +110 -0
  102. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  103. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  104. metadata +127 -129
  105. data/lib/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  106. data/lib/concurrent/atomic/atomic_reference.rb +0 -204
  107. data/lib/concurrent/atomic/java_thread_local_var.rb +0 -37
  108. data/lib/concurrent/atomic/ruby_thread_local_var.rb +0 -161
  109. data/lib/concurrent/atomic/thread_local_var.rb +0 -104
  110. data/lib/concurrent/concern/logging.rb +0 -32
  111. data/lib/concurrent/concurrent_ruby.jar +0 -0
  112. data/lib/concurrent/configuration.rb +0 -184
  113. data/lib/concurrent/synchronization/jruby_object.rb +0 -45
  114. data/lib/concurrent/synchronization/mri_object.rb +0 -44
  115. data/lib/concurrent/synchronization/rbx_lockable_object.rb +0 -65
  116. data/lib/concurrent/synchronization/rbx_object.rb +0 -49
  117. data/lib/concurrent/synchronization/truffleruby_object.rb +0 -47
  118. data/lib/concurrent/synchronization/volatile.rb +0 -36
  119. data/lib/concurrent/synchronization.rb +0 -30
  120. data/lib/concurrent/thread_safe/synchronized_delegator.rb +0 -50
  121. data/lib/concurrent/thread_safe/util/data_structures.rb +0 -63
  122. data/lib/concurrent/utility/at_exit.rb +0 -97
  123. data/lib/concurrent/utility/monotonic_time.rb +0 -58
  124. data/lib/concurrent/utility/processor_counter.rb +0 -158
  125. data/lib/concurrent/version.rb +0 -3
  126. data/lib/concurrent-ruby.rb +0 -1
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
  128. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
  134. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  135. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  136. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
  137. /data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
  138. /data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
  139. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  140. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  141. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  142. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  143. /data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  144. /data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
  145. /data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  146. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  147. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  148. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  149. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  150. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  151. /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/utility/engine'
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
- sh 'bundle package'
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
- RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
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('lib/concurrent/2.*', 'lib/concurrent/*.jar')
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
- Dir.chdir(__dir__) do
83
- sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
84
- sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
85
- sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
86
- ENV['NO_PATH'] = 'true'
87
- sh 'bundle update'
88
- sh 'bundle exec rake spec:ci'
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
- gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
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
- '--output-dir', output_dir,
164
- '--main', 'tmp/README.md',
165
- *common_yard_options)
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.md',
192
+ 'LICENSE.txt',
174
193
  'CHANGELOG.md']
175
194
  end
176
- Rake::Task[name].prerequisites.push removal_name, 'yard:eval_md', 'yard:update_readme'
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
- '--output-dir', 'docs',
186
- '--main', 'docs-source/signpost.md',
187
- *common_yard_options)
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
- mri_version = '2.5.1'
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
- STDOUT.puts 'Command failed. Continue? (y/n)'
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
- '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
237
+ '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
247
238
  unless ok
248
239
  begin
249
- STDOUT.puts 'Command failed. Continue? (y/n)'
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
- old = ENV['RBENV_VERSION']
255
+ puts "Testing with the installed gem"
265
256
 
266
- ENV['RBENV_VERSION'] = mri_version
267
- sh 'rbenv version'
268
- sh 'bundle exec rake spec:installed'
257
+ Bundler.with_original_env do
258
+ sh 'ruby -v'
259
+ sh 'bundle exec rake spec:installed'
269
260
 
270
- ENV['RBENV_VERSION'] = jruby_version
271
- sh 'rbenv version'
272
- sh 'bundle exec rake spec:installed'
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? (y/n)'
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'
@@ -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, IRubyObject value) throws InterruptedException {
49
- this.semaphore.acquire(rubyFixnumToPositiveInt(value, "permits"));
50
- return context.nil;
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
- return getRuntime().newBoolean(semaphore.tryAcquire(1));
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
- return getRuntime().newBoolean(semaphore.tryAcquire(rubyFixnumToPositiveInt(permits, "permits")));
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
- return getRuntime().newBoolean(
82
- semaphore.tryAcquire(
83
- rubyFixnumToPositiveInt(permits, "permits"),
84
- rubyNumericToLong(timeout, "timeout"),
85
- java.util.concurrent.TimeUnit.SECONDS)
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 value) {
97
- this.semaphore.release(rubyFixnumToPositiveInt(value, "permits"));
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", "JRubyObject",
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 self) {
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 = "JRubyObject", parent = "AbstractObject")
199
- public static class JRubyObject extends RubyObject {
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 JRubyObject {
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
- # `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.
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-2.2.0/Array.html Ruby standard library `Array`
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