concurrent-ruby 1.0.5 → 1.1.6

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 (161) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +115 -0
  3. data/Gemfile +42 -0
  4. data/{LICENSE.txt → LICENSE.md} +2 -0
  5. data/README.md +242 -105
  6. data/Rakefile +332 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +159 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/concurrent-ruby/concurrent-ruby.rb +1 -0
  23. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
  25. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +18 -4
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  31. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  32. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +204 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +3 -1
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +43 -33
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +8 -8
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  53. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  65. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +19 -25
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +27 -30
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +19 -16
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +12 -8
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +9 -4
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +6 -6
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  94. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +8 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  97. data/lib/concurrent-ruby/concurrent/map.rb +337 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +25 -14
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +53 -21
  103. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  104. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  106. data/lib/concurrent-ruby/concurrent/set.rb +66 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +6 -6
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  118. data/lib/{concurrent/synchronization/mri_lockable_object.rb → concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb} +19 -14
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  122. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  128. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +63 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +5 -2
  134. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  135. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +2 -2
  136. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  137. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +3 -3
  138. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  139. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  140. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -2
  141. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  142. metadata +146 -131
  143. data/lib/concurrent/array.rb +0 -39
  144. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  145. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  146. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  147. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  148. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  149. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  150. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  151. data/lib/concurrent/atomics.rb +0 -53
  152. data/lib/concurrent/edge.rb +0 -26
  153. data/lib/concurrent/hash.rb +0 -36
  154. data/lib/concurrent/lazy_register.rb +0 -81
  155. data/lib/concurrent/map.rb +0 -240
  156. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  157. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  158. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  159. data/lib/concurrent/utility/at_exit.rb +0 -97
  160. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  161. data/lib/concurrent/version.rb +0 -4
@@ -0,0 +1,332 @@
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'
4
+
5
+ if Concurrent.ruby_version :<, 2, 0, 0
6
+ # @!visibility private
7
+ module Kernel
8
+ def __dir__
9
+ File.dirname __FILE__
10
+ end
11
+ end
12
+ end
13
+
14
+ core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
15
+ ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
16
+ edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.gemspec')
17
+
18
+ require 'rake/javaextensiontask'
19
+
20
+ ENV['JRUBY_HOME'] = ENV['CONCURRENT_JRUBY_HOME'] if ENV['CONCURRENT_JRUBY_HOME'] && !Concurrent.on_jruby?
21
+
22
+ Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
23
+ ext.ext_dir = 'ext/concurrent-ruby'
24
+ ext.lib_dir = 'lib/concurrent-ruby/concurrent'
25
+ end
26
+
27
+ unless Concurrent.on_jruby?
28
+ require 'rake/extensiontask'
29
+
30
+ Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
31
+ ext.ext_dir = 'ext/concurrent-ruby-ext'
32
+ ext.lib_dir = 'lib/concurrent-ruby/concurrent'
33
+ ext.source_pattern = '*.{c,h}'
34
+
35
+ ext.cross_compile = true
36
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
37
+ end
38
+ end
39
+
40
+ require 'rake_compiler_dock'
41
+ namespace :repackage do
42
+ desc '* with Windows fat distributions'
43
+ task :all do
44
+ Dir.chdir(__dir__) do
45
+ # store gems in vendor cache for docker
46
+ sh 'bundle package'
47
+
48
+ # build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
49
+ Rake::Task['lib/concurrent-ruby/concurrent/concurrent_ruby.jar'].invoke
50
+
51
+ # build all gem files
52
+ RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
53
+ end
54
+ end
55
+ end
56
+
57
+ require 'rubygems'
58
+ require 'rubygems/package_task'
59
+
60
+ Gem::PackageTask.new(core_gemspec) {} if core_gemspec
61
+ Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby?
62
+ Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
63
+
64
+ CLEAN.include('lib/concurrent-ruby/concurrent/2.*', 'lib/concurrent-ruby/concurrent/*.jar')
65
+
66
+ begin
67
+ require 'rspec'
68
+ require 'rspec/core/rake_task'
69
+
70
+ RSpec::Core::RakeTask.new(:spec)
71
+
72
+ namespace :spec do
73
+ desc '* Configured for ci'
74
+ RSpec::Core::RakeTask.new(:ci) do |t|
75
+ options = %w[ --color
76
+ --backtrace
77
+ --order defined
78
+ --format documentation
79
+ --tag ~notravis ]
80
+ t.rspec_opts = [*options].join(' ')
81
+ end
82
+
83
+ desc '* test packaged and installed gems instead of local files'
84
+ task :installed do
85
+ Dir.chdir(__dir__) do
86
+ sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
87
+ sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
88
+ sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
89
+ ENV['NO_PATH'] = 'true'
90
+ sh 'bundle update'
91
+ sh 'bundle exec rake spec:ci'
92
+ end
93
+ end
94
+ end
95
+
96
+ desc 'executed in CI'
97
+ task :ci => [:compile, 'spec:ci']
98
+
99
+ task :default => [:clobber, :compile, :spec]
100
+ rescue LoadError => e
101
+ puts 'RSpec is not installed, skipping test task definitions: ' + e.message
102
+ end
103
+
104
+ current_yard_version_name = Concurrent::VERSION
105
+
106
+ begin
107
+ require 'yard'
108
+ require 'md_ruby_eval'
109
+ require_relative 'support/yard_full_types'
110
+
111
+ common_yard_options = ['--no-yardopts',
112
+ '--no-document',
113
+ '--no-private',
114
+ '--embed-mixins',
115
+ '--markup', 'markdown',
116
+ '--title', 'Concurrent Ruby',
117
+ '--template', 'default',
118
+ '--template-path', 'yard-template',
119
+ '--default-return', 'undocumented']
120
+
121
+ desc 'Generate YARD Documentation (signpost, master)'
122
+ task :yard => ['yard:signpost', 'yard:master']
123
+
124
+ namespace :yard do
125
+
126
+ desc '* eval markdown files'
127
+ task :eval_md do
128
+ Dir.chdir File.join(__dir__, 'docs-source') do
129
+ sh 'bundle exec md-ruby-eval --auto'
130
+ end
131
+ end
132
+
133
+ task :update_readme do
134
+ Dir.chdir __dir__ do
135
+ content = File.read(File.join('README.md')).
136
+ gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
137
+ case $1
138
+ when 'LockFreeLinkedSet'
139
+ "{Concurrent::Edge::#{$1} #{$1}}"
140
+ when '.dataflow'
141
+ '{Concurrent.dataflow Concurrent.dataflow}'
142
+ when 'thread pool'
143
+ '{file:thread_pools.md thread pool}'
144
+ else
145
+ "{Concurrent::#{$1} #{$1}}"
146
+ end
147
+ end
148
+ FileUtils.mkpath 'tmp'
149
+ File.write 'tmp/README.md', content
150
+ end
151
+ end
152
+
153
+ define_yard_task = -> name do
154
+ output_dir = "docs/#{name}"
155
+
156
+ removal_name = "remove.#{name}"
157
+ task removal_name do
158
+ Dir.chdir __dir__ do
159
+ FileUtils.rm_rf output_dir
160
+ end
161
+ end
162
+
163
+ desc "* of #{name} into subdir #{name}"
164
+ YARD::Rake::YardocTask.new(name) do |yard|
165
+ yard.options.push(
166
+ '--output-dir', output_dir,
167
+ '--main', 'tmp/README.md',
168
+ *common_yard_options)
169
+ yard.files = ['./lib/concurrent-ruby/**/*.rb',
170
+ './lib/concurrent-ruby-edge/**/*.rb',
171
+ './ext/concurrent_ruby_ext/**/*.c',
172
+ '-',
173
+ 'docs-source/thread_pools.md',
174
+ 'docs-source/promises.out.md',
175
+ 'docs-source/medium-example.out.rb',
176
+ 'LICENSE.md',
177
+ 'CHANGELOG.md']
178
+ end
179
+ Rake::Task[name].prerequisites.push removal_name,
180
+ # 'yard:eval_md',
181
+ 'yard:update_readme'
182
+ end
183
+
184
+ define_yard_task.call current_yard_version_name
185
+ define_yard_task.call 'master'
186
+
187
+ desc "* signpost for versions"
188
+ YARD::Rake::YardocTask.new(:signpost) do |yard|
189
+ yard.options.push(
190
+ '--output-dir', 'docs',
191
+ '--main', 'docs-source/signpost.md',
192
+ *common_yard_options)
193
+ yard.files = ['no-lib']
194
+ end
195
+
196
+ define_uptodate_task = -> name do
197
+ namespace name do
198
+ desc "** ensure that #{name} generated documentation is matching the source code"
199
+ task :uptodate do
200
+ Dir.chdir(__dir__) do
201
+ begin
202
+ FileUtils.cp_r 'docs', 'docs-copy', verbose: true
203
+ Rake::Task["yard:#{name}"].invoke
204
+ sh 'diff -r docs/ docs-copy/' do |ok, res|
205
+ unless ok
206
+ begin
207
+ STDOUT.puts 'Command failed. Continue? (y/n)'
208
+ input = STDIN.gets.strip.downcase
209
+ end until %w(y n).include?(input)
210
+ exit 1 if input == 'n'
211
+ end
212
+ end
213
+ ensure
214
+ FileUtils.rm_rf 'docs-copy', verbose: true
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ define_uptodate_task.call current_yard_version_name
222
+ define_uptodate_task.call 'master'
223
+ end
224
+
225
+ rescue LoadError => e
226
+ puts 'YARD is not installed, skipping documentation task definitions: ' + e.message
227
+ end
228
+
229
+ desc 'build, test, and publish the gem'
230
+ task :release => ['release:checks', 'release:build', 'release:test', 'release:publish']
231
+
232
+ namespace :release do
233
+ # Depends on environment of @pitr-ch
234
+
235
+ mri_version = '2.6.5'
236
+ jruby_version = 'jruby-9.2.9.0'
237
+
238
+ task :checks => "yard:#{current_yard_version_name}:uptodate" do
239
+ Dir.chdir(__dir__) do
240
+ sh 'test -z "$(git status --porcelain)"' do |ok, res|
241
+ unless ok
242
+ begin
243
+ STDOUT.puts 'Command failed. Continue? (y/n)'
244
+ input = STDIN.gets.strip.downcase
245
+ end until %w(y n).include?(input)
246
+ exit 1 if input == 'n'
247
+ end
248
+ end
249
+ sh 'git fetch'
250
+ sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
251
+ '$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
252
+ unless ok
253
+ begin
254
+ STDOUT.puts 'Command failed. Continue? (y/n)'
255
+ input = STDIN.gets.strip.downcase
256
+ end until %w(y n).include?(input)
257
+ exit 1 if input == 'n'
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ desc '* build all *.gem files necessary for release'
264
+ task :build => [:clobber, 'repackage:all']
265
+
266
+ desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
267
+ task :test do
268
+ Dir.chdir(__dir__) do
269
+ old = ENV['RBENV_VERSION']
270
+
271
+ ENV['RBENV_VERSION'] = mri_version
272
+ sh 'rbenv version'
273
+ sh 'bundle exec rake spec:installed'
274
+
275
+ ENV['RBENV_VERSION'] = jruby_version
276
+ sh 'rbenv version'
277
+ sh 'bundle exec rake spec:installed'
278
+
279
+ puts 'Windows build is untested'
280
+
281
+ ENV['RBENV_VERSION'] = old
282
+ end
283
+ end
284
+
285
+ desc '* do all nested steps'
286
+ task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
287
+
288
+ namespace :publish do
289
+ publish_edge = false
290
+
291
+ task :ask do
292
+ begin
293
+ STDOUT.puts 'Do you want to publish anything? (y/n)'
294
+ input = STDIN.gets.strip.downcase
295
+ end until %w(y n).include?(input)
296
+ exit 1 if input == 'n'
297
+ begin
298
+ STDOUT.puts 'Do you want to publish edge? (y/n)'
299
+ input = STDIN.gets.strip.downcase
300
+ end until %w(y n).include?(input)
301
+ publish_edge = input == 'y'
302
+ end
303
+
304
+ desc '** tag HEAD with current version and push to github'
305
+ task :tag do
306
+ Dir.chdir(__dir__) do
307
+ sh "git tag v#{Concurrent::VERSION}"
308
+ sh "git push origin v#{Concurrent::VERSION}"
309
+ sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
310
+ sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
311
+ end
312
+ end
313
+
314
+ desc '** push all *.gem files to rubygems'
315
+ task :rubygems do
316
+ Dir.chdir(__dir__) do
317
+ sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
318
+ sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
319
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem"
320
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem"
321
+ sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem"
322
+ end
323
+ end
324
+
325
+ desc '** print post release steps'
326
+ task :post_steps do
327
+ puts 'Manually: create a release on GitHub with relevant changelog part'
328
+ puts 'Manually: send email same as release with relevant changelog part'
329
+ puts 'Manually: tweet'
330
+ end
331
+ end
332
+ end
@@ -0,0 +1,17 @@
1
+ import org.jruby.Ruby;
2
+ import org.jruby.runtime.load.BasicLibraryService;
3
+
4
+ import java.io.IOException;
5
+
6
+ public class ConcurrentRubyService implements BasicLibraryService {
7
+
8
+ public boolean basicLoad(final Ruby runtime) throws IOException {
9
+ new com.concurrent_ruby.ext.AtomicReferenceLibrary().load(runtime, false);
10
+ new com.concurrent_ruby.ext.JavaAtomicBooleanLibrary().load(runtime, false);
11
+ new com.concurrent_ruby.ext.JavaAtomicFixnumLibrary().load(runtime, false);
12
+ new com.concurrent_ruby.ext.JavaSemaphoreLibrary().load(runtime, false);
13
+ new com.concurrent_ruby.ext.SynchronizationLibrary().load(runtime, false);
14
+ new com.concurrent_ruby.ext.JRubyMapBackendLibrary().load(runtime, false);
15
+ return true;
16
+ }
17
+ }
@@ -0,0 +1,175 @@
1
+ package com.concurrent_ruby.ext;
2
+
3
+ import java.lang.reflect.Field;
4
+ import java.io.IOException;
5
+ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
6
+ import org.jruby.Ruby;
7
+ import org.jruby.RubyClass;
8
+ import org.jruby.RubyModule;
9
+ import org.jruby.RubyNumeric;
10
+ import org.jruby.RubyObject;
11
+ import org.jruby.anno.JRubyClass;
12
+ import org.jruby.anno.JRubyMethod;
13
+ import org.jruby.runtime.ObjectAllocator;
14
+ import org.jruby.runtime.ThreadContext;
15
+ import org.jruby.runtime.builtin.IRubyObject;
16
+ import org.jruby.runtime.load.Library;
17
+
18
+ /**
19
+ * This library adds an atomic reference type to JRuby for use in the atomic
20
+ * library. We do a native version to avoid the implicit value coercion that
21
+ * normally happens through JI.
22
+ *
23
+ * @author headius
24
+ */
25
+ public class AtomicReferenceLibrary implements Library {
26
+ public void load(Ruby runtime, boolean wrap) throws IOException {
27
+ RubyModule concurrentMod = runtime.defineModule("Concurrent");
28
+ RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicReference", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
29
+ try {
30
+ sun.misc.Unsafe.class.getMethod("getAndSetObject", Object.class);
31
+ atomicCls.setAllocator(JRUBYREFERENCE8_ALLOCATOR);
32
+ } catch (Exception e) {
33
+ // leave it as Java 6/7 version
34
+ }
35
+ atomicCls.defineAnnotatedMethods(JRubyReference.class);
36
+ }
37
+
38
+ private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
39
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
40
+ return new JRubyReference(runtime, klazz);
41
+ }
42
+ };
43
+
44
+ private static final ObjectAllocator JRUBYREFERENCE8_ALLOCATOR = new ObjectAllocator() {
45
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
46
+ return new JRubyReference8(runtime, klazz);
47
+ }
48
+ };
49
+
50
+ @JRubyClass(name="JRubyReference", parent="Object")
51
+ public static class JRubyReference extends RubyObject {
52
+ volatile IRubyObject reference;
53
+
54
+ static final sun.misc.Unsafe UNSAFE;
55
+ static final long referenceOffset;
56
+
57
+ static {
58
+ try {
59
+ UNSAFE = UnsafeHolder.U;
60
+ Class k = JRubyReference.class;
61
+ referenceOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("reference"));
62
+ } catch (Exception e) {
63
+ throw new RuntimeException(e);
64
+ }
65
+ }
66
+
67
+ public JRubyReference(Ruby runtime, RubyClass klass) {
68
+ super(runtime, klass);
69
+ }
70
+
71
+ @JRubyMethod
72
+ public IRubyObject initialize(ThreadContext context) {
73
+ UNSAFE.putObject(this, referenceOffset, context.nil);
74
+ return context.nil;
75
+ }
76
+
77
+ @JRubyMethod
78
+ public IRubyObject initialize(ThreadContext context, IRubyObject value) {
79
+ UNSAFE.putObject(this, referenceOffset, value);
80
+ return context.nil;
81
+ }
82
+
83
+ @JRubyMethod(name = {"get", "value"})
84
+ public IRubyObject get() {
85
+ return reference;
86
+ }
87
+
88
+ @JRubyMethod(name = {"set", "value="})
89
+ public IRubyObject set(IRubyObject newValue) {
90
+ UNSAFE.putObjectVolatile(this, referenceOffset, newValue);
91
+ return newValue;
92
+ }
93
+
94
+ @JRubyMethod(name = {"compare_and_set", "compare_and_swap"})
95
+ public IRubyObject compare_and_set(ThreadContext context, IRubyObject expectedValue, IRubyObject newValue) {
96
+ Ruby runtime = context.runtime;
97
+
98
+ if (expectedValue instanceof RubyNumeric) {
99
+ // numerics are not always idempotent in Ruby, so we need to do slower logic
100
+ return compareAndSetNumeric(context, expectedValue, newValue);
101
+ }
102
+
103
+ return runtime.newBoolean(UNSAFE.compareAndSwapObject(this, referenceOffset, expectedValue, newValue));
104
+ }
105
+
106
+ @JRubyMethod(name = {"get_and_set", "swap"})
107
+ public IRubyObject get_and_set(ThreadContext context, IRubyObject newValue) {
108
+ // less-efficient version for Java 6 and 7
109
+ while (true) {
110
+ IRubyObject oldValue = get();
111
+ if (UNSAFE.compareAndSwapObject(this, referenceOffset, oldValue, newValue)) {
112
+ return oldValue;
113
+ }
114
+ }
115
+ }
116
+
117
+ private IRubyObject compareAndSetNumeric(ThreadContext context, IRubyObject expectedValue, IRubyObject newValue) {
118
+ Ruby runtime = context.runtime;
119
+
120
+ // loop until:
121
+ // * reference CAS would succeed for same-valued objects
122
+ // * current and expected have different values as determined by #equals
123
+ while (true) {
124
+ IRubyObject current = reference;
125
+
126
+ if (!(current instanceof RubyNumeric)) {
127
+ // old value is not numeric, CAS fails
128
+ return runtime.getFalse();
129
+ }
130
+
131
+ RubyNumeric currentNumber = (RubyNumeric)current;
132
+ if (!currentNumber.equals(expectedValue)) {
133
+ // current number does not equal expected, fail CAS
134
+ return runtime.getFalse();
135
+ }
136
+
137
+ // check that current has not changed, or else allow loop to repeat
138
+ boolean success = UNSAFE.compareAndSwapObject(this, referenceOffset, current, newValue);
139
+ if (success) {
140
+ // value is same and did not change in interim...success
141
+ return runtime.getTrue();
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ private static final class UnsafeHolder {
148
+ private UnsafeHolder(){}
149
+
150
+ public static final sun.misc.Unsafe U = loadUnsafe();
151
+
152
+ private static sun.misc.Unsafe loadUnsafe() {
153
+ try {
154
+ Class unsafeClass = Class.forName("sun.misc.Unsafe");
155
+ Field f = unsafeClass.getDeclaredField("theUnsafe");
156
+ f.setAccessible(true);
157
+ return (sun.misc.Unsafe) f.get(null);
158
+ } catch (Exception e) {
159
+ return null;
160
+ }
161
+ }
162
+ }
163
+
164
+ public static class JRubyReference8 extends JRubyReference {
165
+ public JRubyReference8(Ruby runtime, RubyClass klass) {
166
+ super(runtime, klass);
167
+ }
168
+
169
+ @Override
170
+ public IRubyObject get_and_set(ThreadContext context, IRubyObject newValue) {
171
+ // efficient version for Java 8
172
+ return (IRubyObject)UNSAFE.getAndSetObject(this, referenceOffset, newValue);
173
+ }
174
+ }
175
+ }