Sha256: 95f071d95a1e592b2104781d9798596da8ec7b662fe18522d1f28a3f090c86a0

Contents?: true

Size: 1.12 KB

Versions: 1

Compression:

Stored size: 1.12 KB

Contents

require 'monitor'
require 'synchronizable/version'

# Synchronizable is intended to be injected into objects via Object#extend.
# After Object#extend(Synchronizable) is performed, the object's original
# methods will become synchronized via a per-instance lock.
module Synchronizable
  IGNORABLE_METHOD_OWNERS = [Object, Kernel, BasicObject]

  def self.extended(obj)
    # immediately create object-level lock
    obj.send(:__lock)

    # redefine all user-defined methods to utilize lock
    obj.methods.each do |m|
      original_method = obj.method(m)
      next if IGNORABLE_METHOD_OWNERS.include?(original_method.owner)

      obj.define_singleton_method(m) do |*args, &block|
        __lock.synchronize do
          original_method.call(*args, &block)
        end
      end
    end

    # define synchronize method that executes a block
    # protected with the internal instance lock
    obj.define_singleton_method(:synchronize) do |&block|
      __lock.synchronize(&block)
    end
  end

  private

  def __lock
    # Monitor is used instead of Mutex in order to support
    # re-entrant locking
    @__lock ||= Monitor.new
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
synchronizable-0.0.4 lib/synchronizable.rb