File tree Expand file tree Collapse file tree 3 files changed +52
-51
lines changed Expand file tree Collapse file tree 3 files changed +52
-51
lines changed Original file line number Diff line number Diff line change 22
33module Concurrent
44
5- module ThreadLocalRubyStorage
5+ class AbstractThreadLocalVar
66
7- protected
7+ module ThreadLocalRubyStorage
88
9- def allocate_storage
10- @storage = Atomic . new Hash . new
11- end
9+ protected
1210
13- def get
14- @storage . get [ Thread . current . object_id ]
15- end
11+ begin
12+ require 'ref'
13+ rescue LoadError
14+ raise LoadError ,
15+ 'ThreadLocalVar requires ref gem installed on MRI. It\'s not concurrent-ruby dependency.'
16+ end
1617
17- def set ( value , &block )
18- key = Thread . current . object_id
18+ def allocate_storage
19+ @storage = Ref ::WeakKeyMap . new
20+ end
1921
20- @storage . update do | s |
21- s . merge ( key => value )
22+ def get
23+ @storage [ Thread . current ]
2224 end
2325
24- if block_given?
25- begin
26- block . call
27- ensure
28- @storage . update do |s |
29- s . clone . tap { |h | h . delete key }
30- end
31- end
26+ def set ( value , &block )
27+ key = Thread . current
3228
33- else
34- unless ThreadLocalRubyStorage . i_know_it_may_leak_values?
35- warn "it may leak values if used without block\n #{ caller [ 0 ] } "
29+ @storage [ key ] = value
30+
31+ if block_given?
32+ begin
33+ block . call
34+ ensure
35+ @storage . delete key
36+ end
3637 end
3738 end
3839 end
3940
40- def self . i_know_it_may_leak_values!
41- @leak_acknowledged = true
42- end
43-
44- def self . i_know_it_may_leak_values?
45- @leak_acknowledged
46- end
47-
48- end
41+ module ThreadLocalJavaStorage
4942
50- module ThreadLocalJavaStorage
43+ protected
5144
52- protected
45+ def allocate_storage
46+ @var = java . lang . ThreadLocal . new
47+ end
5348
54- def allocate_storage
55- @var = java . lang . ThreadLocal . new
56- end
49+ def get
50+ @var . get
51+ end
5752
58- def get
59- @var . get
60- end
53+ def set ( value )
54+ @var . set ( value )
55+ end
6156
62- def set ( value )
63- @var . set ( value )
6457 end
6558
66- end
67-
68- class AbstractThreadLocalVar
69-
7059 NIL_SENTINEL = Object . new
7160
7261 def initialize ( default = nil )
Original file line number Diff line number Diff line change 77require 'concurrent/atomic/cyclic_barrier'
88require 'concurrent/atomic/count_down_latch'
99require 'concurrent/atomic/event'
10- require 'concurrent/atomic/thread_local_var'
1110require 'concurrent/atomic/synchronization'
Original file line number Diff line number Diff line change 33
44module Concurrent
55
6- ThreadLocalRubyStorage . i_know_it_may_leak_values!
6+ require 'concurrent/atomic/thread_local_var'
77
88 describe ThreadLocalVar do
99
@@ -31,11 +31,11 @@ module Concurrent
3131
3232 if jruby?
3333 it 'uses ThreadLocalJavaStorage' do
34- expect ( subject . class . ancestors ) . to include ( Concurrent ::ThreadLocalJavaStorage )
34+ expect ( subject . class . ancestors ) . to include ( Concurrent ::AbstractThreadLocalVar :: ThreadLocalJavaStorage )
3535 end
3636 else
3737 it 'uses ThreadLocalNewStorage' do
38- expect ( subject . class . ancestors ) . to include ( Concurrent ::ThreadLocalRubyStorage )
38+ expect ( subject . class . ancestors ) . to include ( Concurrent ::AbstractThreadLocalVar :: ThreadLocalRubyStorage )
3939 end
4040 end
4141 end
@@ -48,7 +48,20 @@ module Concurrent
4848 Thread . new { var . bind ( i ) { var . value } }
4949 end . each ( &:join )
5050 var . value = 0
51- expect ( var . instance_variable_get ( :@storage ) . get . size ) . to be == 1
51+ expect ( var . instance_variable_get ( :@storage ) . keys . size ) . to be == 1
52+ end
53+
54+ it 'does not leave values behind when bind is not used' do
55+ var = ThreadLocalVar . new ( 0 )
56+ 100 . times . map do |i |
57+ Thread . new { var . value = i ; var . value }
58+ end . each ( &:join )
59+ var . value = 0
60+ sleep 0.1
61+ GC . start
62+ sleep 0.1
63+ GC . start
64+ expect ( var . instance_variable_get ( :@storage ) . keys . size ) . to be == 1
5265 end
5366 end
5467 end
You can’t perform that action at this time.
0 commit comments