class Concurrent::ThreadLocalVar
A ‘ThreadLocalVar` is a variable where the value is different for each thread. Each variable may have a default value, but when you modify the variable only the current thread will ever see that change.
This is similar to Ruby’s built-in thread-local variables (‘Thread#thread_variable_get`), but with these major advantages:
-
‘ThreadLocalVar` has its own identity, it doesn’t need a Symbol.
-
Each Ruby’s built-in thread-local variable leaks some memory forever (it’s a Symbol held forever on the thread), so it’s only OK to create a small amount of them. ‘ThreadLocalVar` has no such issue and it is fine to create many of them.
-
Ruby’s built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly). ‘ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC’d.
@!macro thread_safe_variable_comparison
@example
v = ThreadLocalVar.new(14) v.value #=> 14 v.value = 2 v.value #=> 2
@example
v = ThreadLocalVar.new(14) t1 = Thread.new do v.value #=> 14 v.value = 1 v.value #=> 1 end t2 = Thread.new do v.value #=> 14 v.value = 2 v.value #=> 2 end v.value #=> 14
Constants
- LOCALS
Public Class Methods
Creates a thread local variable.
@param [Object] default the default value when otherwise unset @param [Proc] default_block Optional block that gets called to obtain the
default value for each thread
# File lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb, line 51 def initialize(default = nil, &default_block) if default && block_given? raise ArgumentError, "Cannot use both value and block as default value" end if block_given? @default_block = default_block @default = nil else @default_block = nil @default = default end @index = LOCALS.next_index(self) end
Public Instance Methods
Bind the given value to thread local storage during execution of the given block.
@param [Object] value the value to bind @yield the operation to be performed with the bound variable @return [Object] the value
# File lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb, line 88 def bind(value) if block_given? old_value = self.value self.value = value begin yield ensure self.value = old_value end end end
Returns the value in the current thread’s copy of this thread-local variable.
@return [Object] the current value
# File lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb, line 70 def value LOCALS.fetch(@index) { default } end
Sets the current thread’s copy of this thread-local variable to the specified value.
@param [Object] value the value to set @return [Object] the new value
# File lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb, line 78 def value=(value) LOCALS.set(@index, value) end
Protected Instance Methods
@!visibility private
# File lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb, line 103 def default if @default_block self.value = @default_block.call else @default end end