module ThreadAttrAccessor
`extend` this module on your class/module to get per-thread class attribute accessors. Example:
class MyClass
extend ThreadAttrAccessor thread_attr_accessor :setting
end
MyClass.setting = :original
threads = [
Thread.new { MyClass.setting = :foo; puts MyClass.setting }, Thread.new { MyClass.setting = :bar; puts MyClass.setting },
]
threads.each(&:join) MyClass.setting == :original # true
Constants
- VERSION
Public Class Methods
extended(base)
click to toggle source
# File lib/thread_attr_accessor.rb, line 102 def self.extended(base) mod = Module.new unless base.const_defined?(:ThreadAttributeAccessors, false) base.const_set(:ThreadAttributeAccessors, mod) base.extend(mod) end end
search_in_ancestor_threads(key)
click to toggle source
# File lib/thread_attr_accessor.rb, line 75 def self.search_in_ancestor_threads(key) fiber = Fiber.current thread = Thread.current until fiber.nil? storage = FiberStorage.new(fiber, thread) if storage.has_key?(key) return storage[key] else fiber = fiber.parent_fiber end end until thread.nil? storage = ThreadStorage.new(thread) if storage.has_key?(key) return storage[key] else thread = thread.parent_thread end end nil end
thread_accessor_key(base, name)
click to toggle source
# File lib/thread_attr_accessor.rb, line 27 def self.thread_accessor_key(base, name) "#{base.name}.#{name}" end
Public Instance Methods
thread_attr_accessor(*names, private: false, **opts)
click to toggle source
# File lib/thread_attr_accessor.rb, line 166 def thread_attr_accessor(*names, private: false, **opts) private_reader = private.to_s == "reader" || private == true private_writer = private.to_s == "writer" || private == true thread_attr_reader(*names, private: private_reader, **opts) thread_attr_writer(*names, private: private_writer, **opts) end
thread_attr_reader(*names, default: nil, inherit: false, private: false, **opts)
click to toggle source
# File lib/thread_attr_accessor.rb, line 128 def thread_attr_reader(*names, default: nil, inherit: false, private: false, **opts) if default && inherit get_default = ->(thread_key) { ThreadAttrAccessor.search_in_ancestor_threads(thread_key) || default.call } elsif inherit get_default = ThreadAttrAccessor.method(:search_in_ancestor_threads) elsif default get_default = ->(*) { default.call } end if get_default get_value = ->(thread_key) { storage = FiberStorage.new storage[thread_key] ||= get_default.call(thread_key) } else get_value = ->(thread_key) { FiberStorage.new[thread_key] } end mod = const_get(:ThreadAttributeAccessors) names.each do |name| thread_key = ThreadAttrAccessor.thread_accessor_key(self, name) mod.send(:define_method, name) do get_value.call(thread_key) end if private mod.send :private, name end end end
thread_attr_writer(*names, private: false, **opts)
click to toggle source
# File lib/thread_attr_accessor.rb, line 111 def thread_attr_writer(*names, private: false, **opts) mod = const_get(:ThreadAttributeAccessors) names.each do |name| thread_key = ThreadAttrAccessor.thread_accessor_key(self, name) mod.send(:define_method, "#{name}=") do |value| FiberStorage.new[thread_key] = value value end if private mod.send :private, "#{name}=" end end end