Module: Tins::ThreadLocal

Included in:
Object, Deflect, HashSymbolizeKeysRecursive
Defined in:
lib/tins/thread_local.rb

Constant Summary collapse

@@mutex =
Mutex.new
@@cleanup =
lambda do |my_object_id|
  my_id = "__thread_local_#{my_object_id}__"
  @@mutex.synchronize do
    for t in Thread.list
      t[my_id] = nil if t[my_id]
    end
  end
end

Instance Method Summary collapse

Instance Method Details

#instance_thread_local(name, default_value = nil, &default) ⇒ Object

Define a thread local variable for the current instance with name name. If the value value is given, it is used to initialize the variable.



49
50
51
52
53
54
55
# File 'lib/tins/thread_local.rb', line 49

def instance_thread_local(name, default_value = nil, &default)
  class << self
    extend Tins::ThreadLocal
    self
  end.thread_local name, default_value, &default
  self
end

#thread_local(name, default_value = nil, &default) ⇒ Object

Define a thread local variable named name in this module/class. If the value value is given, it is used to initialize the variable.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/tins/thread_local.rb', line 16

def thread_local(name, default_value = nil, &default)
  is_a?(Module) or raise TypeError, "receiver has to be a Module"

  default_value && default and raise ArgumentError,
    "require either default_falue or default block"

  if default_value
    default = -> * { default_value }
  end

  name = name.to_s
  my_id = "__thread_local_#{__id__}__"

  ObjectSpace.define_finalizer(self, @@cleanup)

  define_method(name) do
    values = Thread.current[my_id] ||= {}
    if default && !values.key?(name)
      values[name] = default.call
    end
    values[name]
  end

  define_method("#{name}=") do |value|
    Thread.current[my_id] ||= {}
    Thread.current[my_id][name] = value
  end

  self
end