@@ -32,13 +32,11 @@ module Concurrent
3232 # them. This is why we need to use a finalizer to clean up the locals array
3333 # when the EC goes out of scope.
3434 class AbstractLocals
35- def initialize ( name_prefix = :concurrent_locals )
35+ def initialize
3636 @free = [ ]
3737 @lock = Mutex . new
38- @all_locals = { }
38+ @all_arrays = { }
3939 @next = 0
40-
41- @name = :"#{ name_prefix } _#{ object_id } "
4240 end
4341
4442 def synchronize
@@ -53,7 +51,7 @@ def weak_synchronize
5351 alias_method :weak_synchronize , :synchronize
5452 end
5553
56- def next_index ( target )
54+ def next_index ( local )
5755 index = synchronize do
5856 if @free . empty?
5957 @next += 1
@@ -62,11 +60,11 @@ def next_index(target)
6260 end
6361 end
6462
65- # When the target goes out of scope, we should free the associated index
63+ # When the local goes out of scope, we should free the associated index
6664 # and all values stored into it.
67- ObjectSpace . define_finalizer ( target , target_finalizer ( index ) )
65+ ObjectSpace . define_finalizer ( local , local_finalizer ( index ) )
6866
69- return index
67+ index
7068 end
7169
7270 def free_index ( index )
@@ -78,7 +76,7 @@ def free_index(index)
7876 #
7977 # DO NOT use each_value which might conflict with new pair assignment
8078 # into the hash in #set method.
81- @all_locals . values . each do |locals |
79+ @all_arrays . values . each do |locals |
8280 locals [ index ] = nil
8381 end
8482
@@ -87,18 +85,13 @@ def free_index(index)
8785 end
8886 end
8987
90- def fetch ( index , default = nil )
91- if locals = self . locals
92- value = locals [ index ]
93- end
88+ def fetch ( index )
89+ locals = self . locals
90+ value = locals ? locals [ index ] : nil
9491
95- if value . nil?
96- if block_given?
97- yield
98- else
99- default
100- end
101- elsif value . equal? ( NULL )
92+ if nil == value
93+ yield
94+ elsif NULL . equal? ( value )
10295 nil
10396 else
10497 value
@@ -107,25 +100,25 @@ def fetch(index, default = nil)
107100
108101 def set ( index , value )
109102 locals = self . locals!
110- locals [ index ] = ( value . nil? ? NULL : value )
103+ locals [ index ] = ( nil == value ? NULL : value )
111104
112105 value
113106 end
114107
115108 private
116109
117- # When the target index goes out of scope, clean up that slot across all locals currently assigned.
118- def target_finalizer ( index )
110+ # When the local goes out of scope, clean up that slot across all locals currently assigned.
111+ def local_finalizer ( index )
119112 proc do
120113 free_index ( index )
121114 end
122115 end
123116
124- # When a target (locals) goes out of scope, delete the locals from all known locals .
125- def locals_finalizer ( locals_object_id )
126- proc do | locals_id |
117+ # When a thread/fiber goes out of scope, remove the array from @all_arrays .
118+ def thread_fiber_finalizer ( array_object_id )
119+ proc do
127120 weak_synchronize do
128- @all_locals . delete ( locals_object_id )
121+ @all_arrays . delete ( array_object_id )
129122 end
130123 end
131124 end
@@ -146,23 +139,23 @@ def locals!
146139 # An array-backed storage of indexed variables per thread.
147140 class ThreadLocals < AbstractLocals
148141 def locals
149- Thread . current . thread_variable_get ( @name )
142+ Thread . current . thread_variable_get ( :concurrent_thread_locals )
150143 end
151144
152145 def locals!
153146 thread = Thread . current
154- locals = thread . thread_variable_get ( @name )
147+ locals = thread . thread_variable_get ( :concurrent_thread_locals )
155148
156149 unless locals
157- locals = thread . thread_variable_set ( @name , [ ] )
150+ locals = thread . thread_variable_set ( :concurrent_thread_locals , [ ] )
158151 weak_synchronize do
159- @all_locals [ locals . object_id ] = locals
160- # When the thread goes out of scope, we should delete the associated locals:
161- ObjectSpace . define_finalizer ( thread , locals_finalizer ( locals . object_id ) )
152+ @all_arrays [ locals . object_id ] = locals
162153 end
154+ # When the thread goes out of scope, we should delete the associated locals:
155+ ObjectSpace . define_finalizer ( thread , thread_fiber_finalizer ( locals . object_id ) )
163156 end
164157
165- return locals
158+ locals
166159 end
167160 end
168161
@@ -171,23 +164,25 @@ def locals!
171164 # An array-backed storage of indexed variables per fiber.
172165 class FiberLocals < AbstractLocals
173166 def locals
174- Thread . current [ @name ]
167+ Thread . current [ :concurrent_fiber_locals ]
175168 end
176169
177170 def locals!
178171 thread = Thread . current
179- locals = thread [ @name ]
172+ locals = thread [ :concurrent_fiber_locals ]
180173
181174 unless locals
182- locals = thread [ @name ] = [ ]
175+ locals = thread [ :concurrent_fiber_locals ] = [ ]
183176 weak_synchronize do
184- @all_locals [ locals . object_id ] = locals
185- # When the thread goes out of scope, we should delete the associated locals:
186- ObjectSpace . define_finalizer ( Fiber . current , locals_finalizer ( locals . object_id ) )
177+ @all_arrays [ locals . object_id ] = locals
187178 end
179+ # When the fiber goes out of scope, we should delete the associated locals:
180+ ObjectSpace . define_finalizer ( Fiber . current , thread_fiber_finalizer ( locals . object_id ) )
188181 end
189182
190- return locals
183+ locals
191184 end
192185 end
186+
187+ private_constant :AbstractLocals , :ThreadLocals , :FiberLocals
193188end
0 commit comments