Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View synchronization.rb
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.