concurrent-ruby 0.8.0.pre2-java → 0.9.0-java

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 (145) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +114 -3
  3. data/README.md +111 -55
  4. data/lib/concurrent.rb +90 -14
  5. data/lib/concurrent/async.rb +143 -51
  6. data/lib/concurrent/atom.rb +131 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +34 -3
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +17 -39
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +34 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +27 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +234 -109
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +19 -7
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +51 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +196 -23
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  46. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  47. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  48. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  49. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  50. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  51. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  52. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  53. data/lib/concurrent/executor/thread_pool_executor.rb +73 -60
  54. data/lib/concurrent/executor/timer_set.rb +96 -84
  55. data/lib/concurrent/executors.rb +1 -1
  56. data/lib/concurrent/future.rb +71 -38
  57. data/lib/concurrent/immutable_struct.rb +89 -0
  58. data/lib/concurrent/ivar.rb +152 -60
  59. data/lib/concurrent/lazy_register.rb +40 -20
  60. data/lib/concurrent/maybe.rb +226 -0
  61. data/lib/concurrent/mutable_struct.rb +227 -0
  62. data/lib/concurrent/mvar.rb +44 -43
  63. data/lib/concurrent/promise.rb +229 -136
  64. data/lib/concurrent/scheduled_task.rb +341 -43
  65. data/lib/concurrent/settable_struct.rb +127 -0
  66. data/lib/concurrent/synchronization.rb +17 -0
  67. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  68. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  69. data/lib/concurrent/synchronization/condition.rb +53 -0
  70. data/lib/concurrent/synchronization/java_object.rb +34 -0
  71. data/lib/concurrent/synchronization/lock.rb +32 -0
  72. data/lib/concurrent/synchronization/monitor_object.rb +26 -0
  73. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  74. data/lib/concurrent/synchronization/object.rb +78 -0
  75. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  76. data/lib/concurrent/timer_task.rb +92 -103
  77. data/lib/concurrent/tvar.rb +42 -38
  78. data/lib/concurrent/utilities.rb +3 -1
  79. data/lib/concurrent/utility/at_exit.rb +97 -0
  80. data/lib/concurrent/utility/engine.rb +44 -0
  81. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  82. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  83. data/lib/concurrent/utility/processor_counter.rb +156 -0
  84. data/lib/concurrent/utility/timeout.rb +18 -14
  85. data/lib/concurrent/utility/timer.rb +11 -6
  86. data/lib/concurrent/version.rb +2 -1
  87. data/lib/concurrent_ruby.rb +1 -0
  88. data/lib/concurrent_ruby_ext.jar +0 -0
  89. metadata +46 -66
  90. data/lib/concurrent/actor.rb +0 -103
  91. data/lib/concurrent/actor/behaviour.rb +0 -70
  92. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  93. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  94. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  95. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  96. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  97. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  98. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  99. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  100. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  101. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  102. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  103. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  104. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  105. data/lib/concurrent/actor/context.rb +0 -154
  106. data/lib/concurrent/actor/core.rb +0 -217
  107. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  108. data/lib/concurrent/actor/envelope.rb +0 -41
  109. data/lib/concurrent/actor/errors.rb +0 -27
  110. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  111. data/lib/concurrent/actor/public_delegations.rb +0 -40
  112. data/lib/concurrent/actor/reference.rb +0 -81
  113. data/lib/concurrent/actor/root.rb +0 -37
  114. data/lib/concurrent/actor/type_check.rb +0 -48
  115. data/lib/concurrent/actor/utils.rb +0 -10
  116. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  117. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  118. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  119. data/lib/concurrent/actor/utils/pool.rb +0 -59
  120. data/lib/concurrent/actress.rb +0 -3
  121. data/lib/concurrent/agent.rb +0 -209
  122. data/lib/concurrent/atomic.rb +0 -92
  123. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  124. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  125. data/lib/concurrent/atomic/synchronization.rb +0 -51
  126. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  127. data/lib/concurrent/channel/channel.rb +0 -41
  128. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  129. data/lib/concurrent/channel/waitable_list.rb +0 -40
  130. data/lib/concurrent/channels.rb +0 -5
  131. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  132. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  133. data/lib/concurrent/collections.rb +0 -3
  134. data/lib/concurrent/dereferenceable.rb +0 -108
  135. data/lib/concurrent/executor/java_cached_thread_pool.rb +0 -32
  136. data/lib/concurrent/executor/java_fixed_thread_pool.rb +0 -31
  137. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +0 -29
  138. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +0 -32
  139. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  140. data/lib/concurrent/logging.rb +0 -20
  141. data/lib/concurrent/obligation.rb +0 -171
  142. data/lib/concurrent/observable.rb +0 -73
  143. data/lib/concurrent/options_parser.rb +0 -48
  144. data/lib/concurrent/utility/processor_count.rb +0 -152
  145. data/lib/extension_helper.rb +0 -37
@@ -1,7 +1,21 @@
1
- require 'concurrent/atomic/condition'
1
+ require 'concurrent/synchronization'
2
2
 
3
3
  module Concurrent
4
- class MutexSemaphore
4
+
5
+ # @!macro [attach] semaphore
6
+ #
7
+ # A counting semaphore. Conceptually, a semaphore maintains a set of
8
+ # permits. Each {#acquire} blocks if necessary until a permit is
9
+ # available, and then takes it. Each {#release} adds a permit, potentially
10
+ # releasing a blocking acquirer.
11
+ # However, no actual permit objects are used; the Semaphore just keeps a
12
+ # count of the number available and acts accordingly.
13
+ #
14
+ # @!visibility private
15
+ #
16
+ # @!macro internal_implementation_note
17
+ class MutexSemaphore < Synchronization::Object
18
+
5
19
  # @!macro [attach] semaphore_method_initialize
6
20
  #
7
21
  # Create a new `Semaphore` with the initial `count`.
@@ -13,9 +27,8 @@ module Concurrent
13
27
  unless count.is_a?(Fixnum) && count >= 0
14
28
  fail ArgumentError, 'count must be an non-negative integer'
15
29
  end
16
- @mutex = Mutex.new
17
- @condition = Condition.new
18
- @free = count
30
+ super()
31
+ synchronize { ns_initialize count }
19
32
  end
20
33
 
21
34
  # @!macro [attach] semaphore_method_acquire
@@ -33,7 +46,7 @@ module Concurrent
33
46
  unless permits.is_a?(Fixnum) && permits > 0
34
47
  fail ArgumentError, 'permits must be an integer greater than zero'
35
48
  end
36
- @mutex.synchronize do
49
+ synchronize do
37
50
  try_acquire_timed(permits, nil)
38
51
  nil
39
52
  end
@@ -45,7 +58,7 @@ module Concurrent
45
58
  #
46
59
  # @return [Integer]
47
60
  def available_permits
48
- @mutex.synchronize { @free }
61
+ synchronize { @free }
49
62
  end
50
63
 
51
64
  # @!macro [attach] semaphore_method_drain_permits
@@ -54,7 +67,7 @@ module Concurrent
54
67
  #
55
68
  # @return [Integer]
56
69
  def drain_permits
57
- @mutex.synchronize do
70
+ synchronize do
58
71
  @free.tap { |_| @free = 0 }
59
72
  end
60
73
  end
@@ -79,7 +92,7 @@ module Concurrent
79
92
  unless permits.is_a?(Fixnum) && permits > 0
80
93
  fail ArgumentError, 'permits must be an integer greater than zero'
81
94
  end
82
- @mutex.synchronize do
95
+ synchronize do
83
96
  if timeout.nil?
84
97
  try_acquire_now(permits)
85
98
  else
@@ -101,15 +114,15 @@ module Concurrent
101
114
  unless permits.is_a?(Fixnum) && permits > 0
102
115
  fail ArgumentError, 'permits must be an integer greater than zero'
103
116
  end
104
- @mutex.synchronize do
117
+ synchronize do
105
118
  @free += permits
106
- permits.times { @condition.signal }
119
+ permits.times { ns_signal }
107
120
  end
108
121
  nil
109
122
  end
110
123
 
111
124
  # @!macro [attach] semaphore_method_reduce_permits
112
- #
125
+ #
113
126
  # @api private
114
127
  #
115
128
  # Shrinks the number of available permits by the indicated reduction.
@@ -125,12 +138,20 @@ module Concurrent
125
138
  unless reduction.is_a?(Fixnum) && reduction >= 0
126
139
  fail ArgumentError, 'reduction must be an non-negative integer'
127
140
  end
128
- @mutex.synchronize { @free -= reduction }
129
- nil
141
+ synchronize { @free -= reduction }
142
+ nil
143
+ end
144
+
145
+ protected
146
+
147
+ # @!visibility private
148
+ def ns_initialize(count)
149
+ @free = count
130
150
  end
131
151
 
132
152
  private
133
153
 
154
+ # @!visibility private
134
155
  def try_acquire_now(permits)
135
156
  if @free >= permits
136
157
  @free -= permits
@@ -140,93 +161,47 @@ module Concurrent
140
161
  end
141
162
  end
142
163
 
164
+ # @!visibility private
143
165
  def try_acquire_timed(permits, timeout)
144
- remaining = Condition::Result.new(timeout)
145
- while !try_acquire_now(permits) && remaining.can_wait?
146
- @condition.signal
147
- remaining = @condition.wait(@mutex, remaining.remaining_time)
148
- end
149
- remaining.can_wait? ? true : false
166
+ ns_wait_until(timeout) { try_acquire_now(permits) }
150
167
  end
151
168
  end
152
169
 
153
- if RUBY_PLATFORM == 'java'
154
-
155
- # @!macro semaphore
156
- #
157
- # A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {#acquire} blocks if necessary
158
- # until a permit is available, and then takes it. Each {#release} adds a permit,
159
- # potentially releasing a blocking acquirer.
160
- # However, no actual permit objects are used; the Semaphore just keeps a count of the number available and
161
- # acts accordingly.
162
- class JavaSemaphore
163
- # @!macro semaphore_method_initialize
164
- def initialize(count)
165
- unless count.is_a?(Fixnum) && count >= 0
166
- fail(ArgumentError,
167
- 'count must be in integer greater than or equal zero')
168
- end
169
- @semaphore = java.util.concurrent.Semaphore.new(count)
170
- end
170
+ # @!visibility private
171
+ # @!macro internal_implementation_note
172
+ SemaphoreImplementation = case
173
+ when Concurrent.on_jruby?
174
+ JavaSemaphore
175
+ else
176
+ MutexSemaphore
177
+ end
178
+ private_constant :SemaphoreImplementation
171
179
 
172
- # @!macro semaphore_method_acquire
173
- def acquire(permits = 1)
174
- unless permits.is_a?(Fixnum) && permits > 0
175
- fail ArgumentError, 'permits must be an integer greater than zero'
176
- end
177
- @semaphore.acquire(permits)
178
- end
180
+ # @!macro semaphore
181
+ #
182
+ # @see Concurrent::MutexSemaphore
183
+ class Semaphore < SemaphoreImplementation
179
184
 
180
- # @!macro semaphore_method_available_permits
181
- def available_permits
182
- @semaphore.availablePermits
183
- end
185
+ # @!method initialize(count)
186
+ # @!macro semaphore_method_initialize
184
187
 
185
- # @!macro semaphore_method_drain_permits
186
- def drain_permits
187
- @semaphore.drainPermits
188
- end
188
+ # @!method acquire(permits = 1)
189
+ # @!macro semaphore_method_acquire
189
190
 
190
- # @!macro semaphore_method_try_acquire
191
- def try_acquire(permits = 1, timeout = nil)
192
- unless permits.is_a?(Fixnum) && permits > 0
193
- fail ArgumentError, 'permits must be an integer greater than zero'
194
- end
195
- if timeout.nil?
196
- @semaphore.tryAcquire(permits)
197
- else
198
- @semaphore.tryAcquire(permits,
199
- timeout,
200
- java.util.concurrent.TimeUnit::SECONDS)
201
- end
202
- end
191
+ # @!method available_permits
192
+ # @!macro semaphore_method_available_permits
203
193
 
204
- # @!macro semaphore_method_release
205
- def release(permits = 1)
206
- unless permits.is_a?(Fixnum) && permits > 0
207
- fail ArgumentError, 'permits must be an integer greater than zero'
208
- end
209
- @semaphore.release(permits)
210
- true
211
- end
194
+ # @!method drain_permits
195
+ # @!macro semaphore_method_drain_permits
212
196
 
213
- # @!macro semaphore_method_reduce_permits
214
- def reduce_permits(reduction)
215
- unless reduction.is_a?(Fixnum) && reduction >= 0
216
- fail ArgumentError, 'reduction must be an non-negative integer'
217
- end
218
- @semaphore.reducePermits(reduction)
219
- end
220
- end
197
+ # @!method try_acquire(permits = 1, timeout = nil)
198
+ # @!macro semaphore_method_try_acquire
221
199
 
222
- # @!macro semaphore
223
- class Semaphore < JavaSemaphore
224
- end
200
+ # @!method release(permits = 1)
201
+ # @!macro semaphore_method_release
225
202
 
226
- else
203
+ # @!method reduce_permits(reduction)
204
+ # @!macro semaphore_method_reduce_permits
227
205
 
228
- # @!macro semaphore
229
- class Semaphore < MutexSemaphore
230
- end
231
206
  end
232
207
  end
@@ -1,8 +1,9 @@
1
- require 'concurrent/atomic'
1
+ require 'concurrent/atomic/thread_local_var/weak_key_map'
2
2
 
3
3
  module Concurrent
4
4
 
5
- # @!macro [attach] abstract_thread_local_var
5
+ # @!macro [attach] thread_local_var
6
+ #
6
7
  # A `ThreadLocalVar` is a variable where the value is different for each thread.
7
8
  # Each variable may have a default value, but when you modify the variable only
8
9
  # the current thread will ever see that change.
@@ -29,64 +30,31 @@ module Concurrent
29
30
  # end
30
31
  #
31
32
  # v.value #=> 14
33
+ #
34
+ # @see https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html Java ThreadLocal
35
+ #
36
+ # @!visibility private
32
37
  class AbstractThreadLocalVar
33
38
 
34
- module ThreadLocalRubyStorage
35
-
36
- protected
37
-
38
- unless RUBY_PLATFORM == 'java'
39
- require 'ref'
40
- end
41
-
42
- def allocate_storage
43
- @storage = Ref::WeakKeyMap.new
44
- end
45
-
46
- def get
47
- @storage[Thread.current]
48
- end
49
-
50
- def set(value, &block)
51
- key = Thread.current
52
-
53
- @storage[key] = value
54
-
55
- if block_given?
56
- begin
57
- block.call
58
- ensure
59
- @storage.delete key
60
- end
61
- end
62
- end
63
- end
64
-
65
- module ThreadLocalJavaStorage
66
-
67
- protected
68
-
69
- def allocate_storage
70
- @var = java.lang.ThreadLocal.new
71
- end
72
-
73
- def get
74
- @var.get
75
- end
76
-
77
- def set(value)
78
- @var.set(value)
79
- end
80
-
81
- end
82
-
39
+ # @!visibility private
83
40
  NIL_SENTINEL = Object.new
41
+ private_constant :NIL_SENTINEL
84
42
 
43
+ # @!macro [attach] thread_local_var_method_initialize
44
+ #
45
+ # Creates a thread local variable.
46
+ #
47
+ # @param [Object] default the default value when otherwise unset
85
48
  def initialize(default = nil)
86
49
  @default = default
87
50
  allocate_storage
88
51
  end
89
52
 
53
+ # @!macro [attach] thread_local_var_method_get
54
+ #
55
+ # Returns the value in the current thread's copy of this thread-local variable.
56
+ #
57
+ # @return [Object] the current value
90
58
  def value
91
59
  value = get
92
60
 
@@ -99,10 +67,24 @@ module Concurrent
99
67
  end
100
68
  end
101
69
 
70
+ # @!macro [attach] thread_local_var_method_set
71
+ #
72
+ # Sets the current thread's copy of this thread-local variable to the specified value.
73
+ #
74
+ # @param [Object] value the value to set
75
+ # @return [Object] the new value
102
76
  def value=(value)
103
77
  bind value
104
78
  end
105
79
 
80
+ # @!macro [attach] thread_local_var_method_bind
81
+ #
82
+ # Bind the given value to thread local storage during
83
+ # execution of the given block.
84
+ #
85
+ # @param [Object] value the value to bind
86
+ # @yield the operation to be performed with the bound variable
87
+ # @return [Object] the value
106
88
  def bind(value, &block)
107
89
  if value.nil?
108
90
  stored_value = NIL_SENTINEL
@@ -110,20 +92,110 @@ module Concurrent
110
92
  stored_value = value
111
93
  end
112
94
 
113
- set stored_value, &block
95
+ set(stored_value, &block)
114
96
 
115
97
  value
116
98
  end
117
99
 
100
+ protected
101
+
102
+ # @!visibility private
103
+ def allocate_storage
104
+ raise NotImplementedError
105
+ end
106
+
107
+ # @!visibility private
108
+ def get
109
+ raise NotImplementedError
110
+ end
111
+
112
+ # @!visibility private
113
+ def set(value)
114
+ raise NotImplementedError
115
+ end
118
116
  end
119
117
 
120
- # @!macro abstract_thread_local_var
121
- class ThreadLocalVar < AbstractThreadLocalVar
122
- if RUBY_PLATFORM == 'java'
123
- include ThreadLocalJavaStorage
124
- else
125
- include ThreadLocalRubyStorage
118
+ # @!visibility private
119
+ # @!macro internal_implementation_note
120
+ class RubyThreadLocalVar < AbstractThreadLocalVar
121
+
122
+ protected
123
+
124
+ # @!visibility private
125
+ def allocate_storage
126
+ @storage = WeakKeyMap.new
127
+ end
128
+
129
+ # @!visibility private
130
+ def get
131
+ @storage[Thread.current]
132
+ end
133
+
134
+ # @!visibility private
135
+ def set(value)
136
+ key = Thread.current
137
+
138
+ @storage[key] = value
139
+
140
+ if block_given?
141
+ begin
142
+ yield
143
+ ensure
144
+ @storage.delete(key)
145
+ end
146
+ end
126
147
  end
127
148
  end
128
149
 
150
+ if Concurrent.on_jruby?
151
+
152
+ # @!visibility private
153
+ # @!macro internal_implementation_note
154
+ class JavaThreadLocalVar < AbstractThreadLocalVar
155
+
156
+ protected
157
+
158
+ # @!visibility private
159
+ def allocate_storage
160
+ @var = java.lang.ThreadLocal.new
161
+ end
162
+
163
+ # @!visibility private
164
+ def get
165
+ @var.get
166
+ end
167
+
168
+ # @!visibility private
169
+ def set(value)
170
+ @var.set(value)
171
+ end
172
+ end
173
+ end
174
+
175
+ # @!visibility private
176
+ # @!macro internal_implementation_note
177
+ ThreadLocalVarImplementation = case
178
+ when Concurrent.on_jruby?
179
+ JavaThreadLocalVar
180
+ else
181
+ RubyThreadLocalVar
182
+ end
183
+ private_constant :ThreadLocalVarImplementation
184
+
185
+ # @!macro thread_local_var
186
+ class ThreadLocalVar < ThreadLocalVarImplementation
187
+
188
+ # @!method initialize(default = nil)
189
+ # @!macro thread_local_var_method_initialize
190
+
191
+ # @!method value
192
+ # @!macro thread_local_var_method_get
193
+
194
+ # @!method value=(value)
195
+ # @!macro thread_local_var_method_set
196
+
197
+ # @!method bind(value, &block)
198
+ # @!macro thread_local_var_method_bind
199
+
200
+ end
129
201
  end