File: active_support/core_ext/module/synchronization.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: <Built-in Module>
  class: Module#1
includes
  Module ( ActiveSupport::CoreExtensions )
  ClassMethods ( ActiveSupport::Deprecation )
inherits from
  Object ( Builtin-Module )
has properties
method: synchronize / 1 #15

Class Hierarchy

Object ( Builtin-Module )
  Module    #1

Code

   1  class Module
   2    # Synchronize access around a method, delegating synchronization to a
   3    # particular mutex. A mutex (either a Mutex, or any object that responds to 
   4    # #synchronize and yields to a block) must be provided as a final :with option.
   5    # The :with option should be a symbol or string, and can represent a method, 
   6    # constant, or instance or class variable.
   7    # Example:
   8    #   class SharedCache
   9    #     @@lock = Mutex.new
  10    #     def expire
  11    #       ...
  12    #     end
  13    #     synchronize :expire, :with => :@@lock
  14    #   end
  15    def synchronize(*methods)
  16      options = methods.extract_options!
  17      unless options.is_a?(Hash) && with = options[:with]
  18        raise ArgumentError, "Synchronization needs a mutex. Supply an options hash with a :with key as the last argument (e.g. synchronize :hello, :with => :@mutex)."
  19      end
  20 
  21      methods.each do |method|
  22        aliased_method, punctuation = method.to_s.sub(/([?!=])$/, ''), $1
  23 
  24        if method_defined?("#{aliased_method}_without_synchronization#{punctuation}")
  25          raise ArgumentError, "#{method} is already synchronized. Double synchronization is not currently supported."
  26        end
  27 
  28        module_eval(<<-EOS, __FILE__, __LINE__ + 1)
  29          def #{aliased_method}_with_synchronization#{punctuation}(*args, &block)     # def expire_with_synchronization(*args, &block)
  30            #{with}.synchronize do                                                    #   @@lock.synchronize do
  31              #{aliased_method}_without_synchronization#{punctuation}(*args, &block)  #     expire_without_synchronization(*args, &block)
  32            end                                                                       #   end
  33          end                                                                         # end
  34        EOS
  35 
  36        alias_method_chain method, :synchronization
  37      end
  38    end
  39  end