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,60 +30,28 @@ 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
32
35
class AbstractThreadLocalVar
33
36
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
-
79
37
NIL_SENTINEL = Object . new
38
+ private_constant :NIL_SENTINEL
80
39
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
81
45
def initialize ( default = nil )
82
46
@default = default
83
47
allocate_storage
84
48
end
85
49
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
86
55
def value
87
56
value = get
88
57
@@ -95,30 +64,132 @@ def value
95
64
end
96
65
end
97
66
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
98
73
def value = ( value )
99
74
bind value
100
75
end
101
76
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
102
85
def bind ( value , &block )
103
86
if value . nil?
104
87
stored_value = NIL_SENTINEL
105
88
else
106
89
stored_value = value
107
90
end
108
91
109
- set stored_value , &block
92
+ set ( stored_value , &block )
110
93
111
94
value
112
95
end
113
96
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
114
113
end
115
114
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 ]
122
127
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
+
123
194
end
124
195
end
0 commit comments