Module: Tins::ThreadGlobal

Included in:
Object
Defined in:
lib/tins/dslkit.rb

Overview

Provides thread-safe global variable functionality for modules and classes.

This module enables the definition of thread-global variables that maintain their state per thread within a given module or class scope. These variables are initialized lazily and provide thread safety through mutex synchronization.

Examples:

Basic usage with module-level thread globals

class MyClass
  extend Tins::ThreadGlobal

  thread_global :counter, 0
end

mc = MyClass.new
mc2 = MyClass.new
mc.counter = 5
puts mc.counter  # => 5
puts mc2.counter # => 5
mc2.counter = 6
puts mc.counter  # => 6

Usage with instance-level thread globals

require 'securerandom'

class MyClass
  include Tins::ThreadGlobal

  def initialize
    instance_thread_global :session_id, SecureRandom.uuid
  end
end

obj = MyClass.new
puts obj.session_id # => unique UUID per instance

Instance Method Summary collapse

Instance Method Details

#instance_thread_global(name, value = nil) ⇒ self

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

This method creates thread-global variables at the instance level by extending the singleton class of the current object. It’s useful when you need per-instance global state that’s still thread-safe.

Examples:

Create instance thread global

class MyClass
  include Tins::ThreadGlobal

  def initialize
    instance_thread_global :session_id, SecureRandom.uuid
  end
end

Parameters:

  • name (Symbol, String)

    The name of the thread global variable to define

  • value (Object) (defaults to: nil)

    The initial value for the variable (optional)

Returns:

  • (self)

    Returns self to allow method chaining



232
233
234
235
236
237
238
239
# File 'lib/tins/dslkit.rb', line 232

def instance_thread_global(name, value = nil)
  sc = class << self
    extend Tins::ThreadGlobal
    self
  end
  sc.thread_global name, value
  self
end

#thread_global(name, default_value = nil) {|Object| ... } ⇒ self

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

Thread global variables maintain their state per thread within the scope of the module or class where they are defined. The initialization is lazy, meaning the default value or block is only executed when first accessed.

Examples:

Define with default value

thread_global :counter, 0

Define with lazy initialization block

thread_global :config do
  { timeout: 30, retries: 3 }
end

Parameters:

  • name (Symbol, String)

    The name of the thread global variable to define

  • default_value (Object) (defaults to: nil)

    The default value for the variable (optional)

Yields:

  • (Object)

    A block that returns the default value for lazy initialization

Yield Parameters:

  • args (Array)

    Arguments passed to the default block

Returns:

  • (self)

    Returns self to allow method chaining

Raises:

  • (TypeError)

    If the receiver is not a Module

  • (ArgumentError)

    If both default_value and default block are provided



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/tins/dslkit.rb', line 181

def thread_global(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
  var_name = "@__#{name}_#{__id__.abs}__"

  lock = Mutex.new
  modul = self

  define_method(name) do
    lock.synchronize {
      if default && !modul.instance_variable_defined?(var_name)
        modul.instance_variable_set var_name, default.call
      end
      modul.instance_variable_get var_name
    }
  end

  define_method(name + "=") do |value|
    lock.synchronize { modul.instance_variable_set var_name, value }
  end

  self
end