From 45448a578877f6a753492113d72cc3512a6f1720 Mon Sep 17 00:00:00 2001
From: thedarkone <thedarkone2@gmail.com>
Date: Thu, 13 Dec 2012 14:47:33 +0100
Subject: Replace some global Hash usages with the new thread safe cache.

Summary of the changes:
 * Add thread_safe gem.
 * Use thread safe cache for digestor caching.
 * Replace manual synchronization with ThreadSafe::Cache in Relation::Delegation.
 * Replace @attribute_method_matchers_cache Hash with ThreadSafe::Cache.
 * Use TS::Cache to avoid the synchronisation overhead on listener retrieval.
 * Replace synchronisation with TS::Cache usage.
 * Use a preallocated array for performance/memory reasons.
 * Update the controllers cache to the new AS::Dependencies::ClassCache API.
   The original @controllers cache no longer makes much sense after @tenderlove's
   changes in 7b6bfe84f3 and f345e2380c.
 * Use TS::Cache in the connection pool to avoid locking overhead.
 * Use TS::Cache in ConnectionHandler.
---
 activesupport/activesupport.gemspec                       | 1 +
 activesupport/lib/active_support/dependencies.rb          | 3 ++-
 activesupport/lib/active_support/inflector/inflections.rb | 6 ++++--
 activesupport/lib/active_support/key_generator.rb         | 8 +++-----
 activesupport/lib/active_support/notifications/fanout.rb  | 7 +++++--
 5 files changed, 15 insertions(+), 10 deletions(-)

(limited to 'activesupport')

diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index a4216d2cb4..4c9e59dbd2 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -24,4 +24,5 @@ Gem::Specification.new do |s|
   s.add_dependency 'multi_json', '~> 1.3'
   s.add_dependency 'tzinfo',     '~> 0.3.33'
   s.add_dependency 'minitest',   '~> 4.1'
+  s.add_dependency 'thread_safe','~> 0.1'
 end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index efd351d741..fff4c776a9 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,5 +1,6 @@
 require 'set'
 require 'thread'
+require 'thread_safe'
 require 'pathname'
 require 'active_support/core_ext/module/aliasing'
 require 'active_support/core_ext/module/attribute_accessors'
@@ -517,7 +518,7 @@ module ActiveSupport #:nodoc:
 
     class ClassCache
       def initialize
-        @store = Hash.new
+        @store = ThreadSafe::Cache.new
       end
 
       def empty?
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
index 6f259a093b..9cf4b2b2ba 100644
--- a/activesupport/lib/active_support/inflector/inflections.rb
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -1,3 +1,4 @@
+require 'thread_safe'
 require 'active_support/core_ext/array/prepend_and_append'
 require 'active_support/i18n'
 
@@ -24,9 +25,10 @@ module ActiveSupport
     # singularization rules that is runs. This guarantees that your rules run
     # before any of the rules that may already have been loaded.
     class Inflections
+      @__instance__ = ThreadSafe::Cache.new
+
       def self.instance(locale = :en)
-        @__instance__ ||= Hash.new { |h, k| h[k] = new }
-        @__instance__[locale]
+        @__instance__[locale] ||= new
       end
 
       attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex
diff --git a/activesupport/lib/active_support/key_generator.rb b/activesupport/lib/active_support/key_generator.rb
index 6beb2b6afa..71654dbb87 100644
--- a/activesupport/lib/active_support/key_generator.rb
+++ b/activesupport/lib/active_support/key_generator.rb
@@ -1,4 +1,4 @@
-require 'mutex_m'
+require 'thread_safe'
 require 'openssl'
 
 module ActiveSupport
@@ -28,16 +28,14 @@ module ActiveSupport
   class CachingKeyGenerator
     def initialize(key_generator)
       @key_generator = key_generator
-      @cache_keys = {}.extend(Mutex_m)
+      @cache_keys = ThreadSafe::Cache.new
     end
 
     # Returns a derived key suitable for use.  The default key_size is chosen
     # to be compatible with the default settings of ActiveSupport::MessageVerifier.
     # i.e. OpenSSL::Digest::SHA1#block_length
     def generate_key(salt, key_size=64)
-      @cache_keys.synchronize do
-        @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
-      end
+      @cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
     end
   end
 
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index 2e5bcf4639..7588fdb67c 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -1,4 +1,5 @@
 require 'mutex_m'
+require 'thread_safe'
 
 module ActiveSupport
   module Notifications
@@ -11,7 +12,7 @@ module ActiveSupport
 
       def initialize
         @subscribers = []
-        @listeners_for = {}
+        @listeners_for = ThreadSafe::Cache.new
         super
       end
 
@@ -44,7 +45,9 @@ module ActiveSupport
       end
 
       def listeners_for(name)
-        synchronize do
+        # this is correctly done double-checked locking (ThreadSafe::Cache's lookups have volatile semantics)
+        @listeners_for[name] || synchronize do
+          # use synchronisation when accessing @subscribers
           @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) }
         end
       end
-- 
cgit v1.2.3