public
Last active

  • Download Gist
synchronization.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.