Skip to content

Commit 62d9ba1

Browse files
committed
ThreadLocalVar follows new subclass declaration convention.
1 parent 54c2b5a commit 62d9ba1

File tree

3 files changed

+288
-220
lines changed

3 files changed

+288
-220
lines changed

lib/concurrent/atomic/thread_local_var.rb

Lines changed: 124 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
module Concurrent
44

5-
# @!macro [attach] abstract_thread_local_var
5+
# @!macro [attach] thread_local_var
6+
#
67
# A `ThreadLocalVar` is a variable where the value is different for each thread.
78
# Each variable may have a default value, but when you modify the variable only
89
# the current thread will ever see that change.
@@ -29,60 +30,28 @@ module Concurrent
2930
# end
3031
#
3132
# v.value #=> 14
33+
#
34+
# @see https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html Java ThreadLocal
3235
class AbstractThreadLocalVar
3336

34-
module ThreadLocalRubyStorage
35-
36-
protected
37-
38-
def allocate_storage
39-
@storage = WeakKeyMap.new
40-
end
41-
42-
def get
43-
@storage[Thread.current]
44-
end
45-
46-
def set(value, &block)
47-
key = Thread.current
48-
49-
@storage[key] = value
50-
51-
if block_given?
52-
begin
53-
block.call
54-
ensure
55-
@storage.delete key
56-
end
57-
end
58-
end
59-
end
60-
61-
module ThreadLocalJavaStorage
62-
63-
protected
64-
65-
def allocate_storage
66-
@var = java.lang.ThreadLocal.new
67-
end
68-
69-
def get
70-
@var.get
71-
end
72-
73-
def set(value)
74-
@var.set(value)
75-
end
76-
77-
end
78-
7937
NIL_SENTINEL = Object.new
38+
private_constant :NIL_SENTINEL
8039

40+
# @!macro [attach] thread_local_var_method_initialize
41+
#
42+
# Creates a thread local variable.
43+
#
44+
# @param [Object] default the default value when otherwise unset
8145
def initialize(default = nil)
8246
@default = default
8347
allocate_storage
8448
end
8549

50+
# @!macro [attach] thread_local_var_method_get
51+
#
52+
# Returns the value in the current thread's copy of this thread-local variable.
53+
#
54+
# @return [Object] the current value
8655
def value
8756
value = get
8857

@@ -95,30 +64,132 @@ def value
9564
end
9665
end
9766

67+
# @!macro [attach] thread_local_var_method_set
68+
#
69+
# Sets the current thread's copy of this thread-local variable to the specified value.
70+
#
71+
# @param [Object] value the value to set
72+
# @return [Object] the new value
9873
def value=(value)
9974
bind value
10075
end
10176

77+
# @!macro [attach] thread_local_var_method_bind
78+
#
79+
# Bind the given value to thread local storage during
80+
# execution of the given block.
81+
#
82+
# @param [Object] value the value to bind
83+
# @yield the operation to be performed with the bound variable
84+
# @return [Object] the value
10285
def bind(value, &block)
10386
if value.nil?
10487
stored_value = NIL_SENTINEL
10588
else
10689
stored_value = value
10790
end
10891

109-
set stored_value, &block
92+
set(stored_value, &block)
11093

11194
value
11295
end
11396

97+
protected
98+
99+
# @!visibility private
100+
def allocate_storage
101+
raise NotImplementedError
102+
end
103+
104+
# @!visibility private
105+
def get
106+
raise NotImplementedError
107+
end
108+
109+
# @!visibility private
110+
def set(value)
111+
raise NotImplementedError
112+
end
114113
end
115114

116-
# @!macro abstract_thread_local_var
117-
class ThreadLocalVar < AbstractThreadLocalVar
118-
if Concurrent.on_jruby?
119-
include ThreadLocalJavaStorage
120-
else
121-
include ThreadLocalRubyStorage
115+
class RubyThreadLocalVar < AbstractThreadLocalVar
116+
117+
protected
118+
119+
# @!visibility private
120+
def allocate_storage
121+
@storage = WeakKeyMap.new
122+
end
123+
124+
# @!visibility private
125+
def get
126+
@storage[Thread.current]
122127
end
128+
129+
# @!visibility private
130+
def set(value)
131+
key = Thread.current
132+
133+
@storage[key] = value
134+
135+
if block_given?
136+
begin
137+
yield
138+
ensure
139+
@storage.delete(key)
140+
end
141+
end
142+
end
143+
end
144+
145+
if Concurrent.on_jruby?
146+
147+
class JavaThreadLocalVar < AbstractThreadLocalVar
148+
149+
protected
150+
151+
# @!visibility private
152+
def allocate_storage
153+
@var = java.lang.ThreadLocal.new
154+
end
155+
156+
# @!visibility private
157+
def get
158+
@var.get
159+
end
160+
161+
# @!visibility private
162+
def set(value)
163+
@var.set(value)
164+
end
165+
end
166+
end
167+
168+
ThreadLocalVarImplementation = case
169+
when Concurrent.on_jruby?
170+
JavaThreadLocalVar
171+
else
172+
RubyThreadLocalVar
173+
end
174+
private_constant :AtomicBooleanImplementation
175+
176+
# @!macro thread_local_var
177+
#
178+
# @see Concurrent::AbstractThreadLocalVar
179+
# @see Concurrent::RubyThreadLocalVar
180+
class ThreadLocalVar < ThreadLocalVarImplementation
181+
182+
# @!method initialize(default = nil)
183+
# @!macro thread_local_var_method_initialize
184+
185+
# @!method value
186+
# @!macro thread_local_var_method_get
187+
188+
# @!method value=(value)
189+
# @!macro thread_local_var_method_set
190+
191+
# @!method bind(value, &block)
192+
# @!macro thread_local_var_method_bind
193+
123194
end
124195
end

0 commit comments

Comments
 (0)