diff options
Diffstat (limited to 'activesupport/lib/active_support/core_ext/thread.rb')
-rw-r--r-- | activesupport/lib/active_support/core_ext/thread.rb | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/core_ext/thread.rb b/activesupport/lib/active_support/core_ext/thread.rb new file mode 100644 index 0000000000..4cd6634558 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/thread.rb @@ -0,0 +1,86 @@ +class Thread + LOCK = Mutex.new # :nodoc: + + # Returns the value of a thread local variable that has been set. Note that + # these are different than fiber local values. + # + # Thread local values are carried along with threads, and do not respect + # fibers. For example: + # + # Thread.new { + # Thread.current.thread_variable_set("foo", "bar") # set a thread local + # Thread.current["foo"] = "bar" # set a fiber local + # + # Fiber.new { + # Fiber.yield [ + # Thread.current.thread_variable_get("foo"), # get the thread local + # Thread.current["foo"], # get the fiber local + # ] + # }.resume + # }.join.value # => ['bar', nil] + # + # The value <tt>"bar"</tt> is returned for the thread local, where +nil+ is returned + # for the fiber local. The fiber is executed in the same thread, so the + # thread local values are available. + def thread_variable_get(key) + _locals[key.to_sym] + end + + # Sets a thread local with +key+ to +value+. Note that these are local to + # threads, and not to fibers. Please see Thread#thread_variable_get for + # more information. + def thread_variable_set(key, value) + _locals[key.to_sym] = value + end + + # Returns an array of the names of the thread-local variables (as Symbols). + # + # thr = Thread.new do + # Thread.current.thread_variable_set(:cat, 'meow') + # Thread.current.thread_variable_set("dog", 'woof') + # end + # thr.join # => #<Thread:0x401b3f10 dead> + # thr.thread_variables # => [:dog, :cat] + # + # Note that these are not fiber local variables. Please see Thread#thread_variable_get + # for more details. + def thread_variables + _locals.keys + end + + # Returns <tt>true</tt> if the given string (or symbol) exists as a + # thread-local variable. + # + # me = Thread.current + # me.thread_variable_set(:oliver, "a") + # me.thread_variable?(:oliver) # => true + # me.thread_variable?(:stanley) # => false + # + # Note that these are not fiber local variables. Please see Thread#thread_variable_get + # for more details. + def thread_variable?(key) + _locals.has_key?(key.to_sym) + end + + # Freezes the thread so that thread local variables cannot be set via + # Thread#thread_variable_set, nor can fiber local variables be set. + # + # me = Thread.current + # me.freeze + # me.thread_variable_set(:oliver, "a") #=> RuntimeError: can't modify frozen thread locals + # me[:oliver] = "a" #=> RuntimeError: can't modify frozen thread locals + def freeze + _locals.freeze + super + end + + private + + def _locals + if defined?(@_locals) + @_locals + else + LOCK.synchronize { @_locals ||= {} } + end + end +end unless Thread.instance_methods.include?(:thread_variable_set) |