Create a gist now

Instantly share code, notes, and snippets.

require "thread"
module Synchronization
class Proxy
instance_methods.each { |m| undef_method m unless m =~ /^__|extend/ }
def initialize(target)
@__target__ = target
end
def __mutex__
@__mutex__ ||= Mutex.new
end
end
module GenericSynchronization
def method_missing(meth_id, *args)
if @__target__.respond_to?(meth_id)
__mutex__.synchronize do
@__target__.send(meth_id, *args)
end
else
@__target__.send(:method_missing, meth_id, *args)
end
end
end
def self.SpecializedSynchronization(methods)
ext = Module.new
methods.each do |meth|
ext.send(:define_method, meth) do |*args|
__mutex__.synchronize do
@__target__.send(meth, *args)
end
end
end
return ext
end
end
def synchronized(object, *methods)
ext = if methods.empty?
Synchronization::GenericSynchronization
else
Synchronization::SpecializedSynchronization(methods)
end
proxy = Synchronization::Proxy.new(object)
proxy.extend(ext)
return proxy
end
if __FILE__ == $0
class Account
attr_reader :balance
def initialize
@balance = 0.0
end
def credit(amount, t)
@amount = amount
sleep(t)
@balance += @amount
puts "CREDIT: #{amount}/#{@amount}"
end
end
acct = synchronized Account.new
# or:
# acct = synchronized Account.new, :credit
t1 = Thread.new(acct) do |account|
account.credit(10, 5)
end
t2 = Thread.new(acct) do |account|
account.credit(20, 10)
end
t1.join; t2.join
puts acct.balance
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment