module Synchronizer_m

A module that provides a two-phase lock with a counter.

Constants

EX
SH
UN

lock mode

Attributes

sync_ex_count[RW]
sync_ex_locker[RW]
sync_mode[RW]
sync_sh_locker[RW]
sync_upgrade_waiting[RW]
sync_waiting[RW]

Public Class Methods

append_features(cl) click to toggle source
Calls superclass method
# File lib/sync.rb, line 89
def Sync_m.append_features(cl)
 super
 # do nothing for Modules
 # make aliases for Classes.
 define_aliases(cl) unless cl.instance_of?(Module)
 self
end
define_aliases(cl) click to toggle source
# File lib/sync.rb, line 77
def Sync_m.define_aliases(cl)
 cl.module_eval %q{
 alias locked? sync_locked?
 alias shared? sync_shared?
 alias exclusive? sync_exclusive?
 alias lock sync_lock
 alias unlock sync_unlock
 alias try_lock sync_try_lock
 alias synchronize sync_synchronize
 }
end
extend_object(obj) click to toggle source
Calls superclass method
# File lib/sync.rb, line 97
def Sync_m.extend_object(obj)
 super
 obj.sync_extend
end
new(*args) click to toggle source
Calls superclass method
# File lib/sync.rb, line 266
def initialize(*args)
 super
 sync_initialize
end

Public Instance Methods

sync_exclusive?() click to toggle source
# File lib/sync.rb, line 124
def sync_exclusive?
 sync_mode == EX
end
sync_extend() click to toggle source
# File lib/sync.rb, line 102
def sync_extend
 unless (defined? locked? and
 defined? shared? and
 defined? exclusive? and
 defined? lock and
 defined? unlock and
 defined? try_lock and
 defined? synchronize)
 Sync_m.define_aliases(singleton_class)
 end
 sync_initialize
end
sync_inspect() click to toggle source
# File lib/sync.rb, line 248
def sync_inspect
 sync_iv = instance_variables.select{|iv| /^@sync_/ =~ iv.id2name}.collect{|iv| iv.id2name + '=' + instance_eval(iv.id2name).inspect}.join(",")
 print "<#{self.class}.extend Sync_m: #{inspect}, <Sync_m: #{sync_iv}>"
end
sync_lock(m = EX) click to toggle source
# File lib/sync.rb, line 136
def sync_lock(m = EX)
 return unlock if m == UN
 Thread.handle_interrupt(StandardError => :on_blocking) do
 while true
 @sync_mutex.synchronize do
 begin
 if sync_try_lock_sub(m)
 return self
 else
 if sync_sh_locker[Thread.current]
 sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
 sync_sh_locker.delete(Thread.current)
 else
 unless sync_waiting.include?(Thread.current) || sync_upgrade_waiting.reverse_each.any?{|w| w.first == Thread.current }
 sync_waiting.push Thread.current
 end
 end
 @sync_mutex.sleep
 end
 ensure
 sync_waiting.delete(Thread.current)
 end
 end
 end
 end
 self
end
sync_locked?() click to toggle source

accessing

# File lib/sync.rb, line 116
def sync_locked?
 sync_mode != UN
end
sync_shared?() click to toggle source
# File lib/sync.rb, line 120
def sync_shared?
 sync_mode == SH
end
sync_synchronize(mode = EX) { || ... } click to toggle source
# File lib/sync.rb, line 229
def sync_synchronize(mode = EX)
 Thread.handle_interrupt(StandardError => :on_blocking) do
 sync_lock(mode)
 begin
 yield
 ensure
 sync_unlock
 end
 end
end
sync_try_lock(mode = EX) click to toggle source

locking methods.

# File lib/sync.rb, line 129
def sync_try_lock(mode = EX)
 return unlock if mode == UN
 @sync_mutex.synchronize do
 sync_try_lock_sub(mode)
 end
end
sync_unlock(m = EX) click to toggle source
# File lib/sync.rb, line 164
def sync_unlock(m = EX)
 wakeup_threads = []
 @sync_mutex.synchronize do
 if sync_mode == UN
 Err::UnknownLocker.Fail(Thread.current)
 end
 m = sync_mode if m == EX and sync_mode == SH
 runnable = false
 case m
 when UN
 Err::UnknownLocker.Fail(Thread.current)
 when EX
 if sync_ex_locker == Thread.current
 if (self.sync_ex_count = sync_ex_count - 1) == 0
 self.sync_ex_locker = nil
 if sync_sh_locker.include?(Thread.current)
 self.sync_mode = SH
 else
 self.sync_mode = UN
 end
 runnable = true
 end
 else
 Err::UnknownLocker.Fail(Thread.current)
 end
 when SH
 if (count = sync_sh_locker[Thread.current]).nil?
 Err::UnknownLocker.Fail(Thread.current)
 else
 if (sync_sh_locker[Thread.current] = count - 1) == 0
 sync_sh_locker.delete(Thread.current)
 if sync_sh_locker.empty? and sync_ex_count == 0
 self.sync_mode = UN
 runnable = true
 end
 end
 end
 end
 if runnable
 if sync_upgrade_waiting.size > 0
 th, count = sync_upgrade_waiting.shift
 sync_sh_locker[th] = count
 th.wakeup
 wakeup_threads.push th
 else
 wait = sync_waiting
 self.sync_waiting = []
 for th in wait
 th.wakeup
 wakeup_threads.push th
 end
 end
 end
 end
 for th in wakeup_threads
 th.run
 end
 self
end

Private Instance Methods

sync_initialize() click to toggle source
# File lib/sync.rb, line 255
def sync_initialize
 @sync_mode = UN
 @sync_waiting = []
 @sync_upgrade_waiting = []
 @sync_sh_locker = Hash.new
 @sync_ex_locker = nil
 @sync_ex_count = 0
 @sync_mutex = Mutex.new
end
sync_try_lock_sub(m) click to toggle source
# File lib/sync.rb, line 271
def sync_try_lock_sub(m)
 case m
 when SH
 case sync_mode
 when UN
 self.sync_mode = m
 sync_sh_locker[Thread.current] = 1
 ret = true
 when SH
 count = 0 unless count = sync_sh_locker[Thread.current]
 sync_sh_locker[Thread.current] = count + 1
 ret = true
 when EX
 # in EX mode, lock will upgrade to EX lock
 if sync_ex_locker == Thread.current
 self.sync_ex_count = sync_ex_count + 1
 ret = true
 else
 ret = false
 end
 end
 when EX
 if sync_mode == UN or
 sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
 self.sync_mode = m
 self.sync_ex_locker = Thread.current
 self.sync_ex_count = 1
 ret = true
 elsif sync_mode == EX && sync_ex_locker == Thread.current
 self.sync_ex_count = sync_ex_count + 1
 ret = true
 else
 ret = false
 end
 else
 Err::LockModeFailer.Fail mode
 end
 return ret
end