Skip to content

Commit bc8dc63

Browse files
committed
Merge pull request ruby-concurrency#136 from ruby-concurrency/thread-local-var
Do not create un-GC-able symbols when creating ThreadLocalVars
2 parents cb7c45a + 316dddd commit bc8dc63

File tree

3 files changed

+13
-60
lines changed

3 files changed

+13
-60
lines changed

lib/concurrent/atomic/thread_local_var.rb

Lines changed: 6 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,19 @@
1-
require 'concurrent/atomic/atomic_fixnum'
1+
require 'concurrent/atomic'
22

33
module Concurrent
44

5-
module ThreadLocalSymbolAllocator
6-
7-
COUNTER = Concurrent::AtomicFixnum.new
8-
9-
protected
10-
11-
def allocate_symbol
12-
# Warning: this symbol may never be deallocated
13-
@symbol = :"thread_local_symbol_#{COUNTER.increment}"
14-
end
15-
16-
end
17-
18-
module ThreadLocalOldStorage
19-
20-
include ThreadLocalSymbolAllocator
21-
22-
protected
23-
24-
def allocate_storage
25-
allocate_symbol
26-
end
27-
28-
def get
29-
Thread.current[@symbol]
30-
end
31-
32-
def set(value)
33-
Thread.current[@symbol] = value
34-
end
35-
36-
end
37-
38-
module ThreadLocalNewStorage
39-
40-
include ThreadLocalSymbolAllocator
41-
42-
protected
5+
module ThreadLocalRubyStorage
436

447
def allocate_storage
45-
allocate_symbol
8+
@storage = Atomic.new Hash.new
469
end
4710

4811
def get
49-
Thread.current.thread_variable_get(@symbol)
12+
@storage.get[Thread.current]
5013
end
5114

5215
def set(value)
53-
Thread.current.thread_variable_set(@symbol, value)
16+
@storage.update { |s| s.merge Thread.current => value }
5417
end
5518

5619
end
@@ -79,10 +42,8 @@ class ThreadLocalVar
7942

8043
if RUBY_PLATFORM == 'java'
8144
include ThreadLocalJavaStorage
82-
elsif Thread.current.respond_to?(:thread_variable_set)
83-
include ThreadLocalNewStorage
8445
else
85-
include ThreadLocalOldStorage
46+
include ThreadLocalRubyStorage
8647
end
8748

8849
def initialize(default = nil)

lib/concurrent/tvar.rb

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
require 'set'
22

3-
require 'concurrent/atomic/thread_local_var'
4-
53
module Concurrent
64

75
# A `TVar` is a transactional variable - a single-element container that
@@ -97,7 +95,7 @@ def atomically
9795

9896
begin
9997
# Retry loop
100-
98+
10199
loop do
102100

103101
# Create a new transaction
@@ -149,17 +147,15 @@ class Transaction
149147

150148
ABORTED = Object.new
151149

152-
CURRENT_TRANSACTION = ThreadLocalVar.new(nil)
153-
154150
ReadLogEntry = Struct.new(:tvar, :version)
155151
UndoLogEntry = Struct.new(:tvar, :value)
156152

157153
AbortError = Class.new(StandardError)
158154

159155
def initialize
160156
@write_set = Set.new
161-
@read_log = []
162-
@undo_log = []
157+
@read_log = []
158+
@undo_log = []
163159
end
164160

165161
def read(tvar)
@@ -217,7 +213,7 @@ def commit
217213
end
218214

219215
unlock
220-
216+
221217
true
222218
end
223219

@@ -240,11 +236,11 @@ def unlock
240236
end
241237

242238
def self.current
243-
CURRENT_TRANSACTION.value
239+
Thread.current[:current_tvar_transaction]
244240
end
245241

246242
def self.current=(transaction)
247-
CURRENT_TRANSACTION.value = transaction
243+
Thread.current[:current_tvar_transaction] = transaction
248244
end
249245

250246
end

spec/concurrent/atomic/thread_local_var_spec.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,9 @@ module Concurrent
3131
it 'uses ThreadLocalJavaStorage' do
3232
expect(subject.class.ancestors).to include(Concurrent::ThreadLocalJavaStorage)
3333
end
34-
elsif rbx? || RbConfig::CONFIG['ruby_version'] =~ /^1\.9/
35-
it 'uses ThreadLocalOldStorage' do
36-
expect(subject.class.ancestors).to include(Concurrent::ThreadLocalOldStorage)
37-
end
3834
else
3935
it 'uses ThreadLocalNewStorage' do
40-
expect(subject.class.ancestors).to include(Concurrent::ThreadLocalNewStorage)
36+
expect(subject.class.ancestors).to include(Concurrent::ThreadLocalRubyStorage)
4137
end
4238
end
4339
end

0 commit comments

Comments
 (0)