2 # sync.rb - 2 phase lock with counter
3 # $Release Version: 1.0$
5 # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
6 # by Keiju ISHITSUKA(keiju@ishitsuka.com)
9 # Sync_m, Synchronizer_m
19 # Sync_m#sync_locked?, locked?
20 # Sync_m#sync_shared?, shared?
21 # Sync_m#sync_exclusive?, sync_exclusive?
22 # Sync_m#sync_try_lock, try_lock
23 # Sync_m#sync_lock, lock
24 # Sync_m#sync_unlock, unlock
35 # Sync#try_lock(mode) -- mode = :EX, :SH, :UN
36 # Sync#lock(mode) -- mode = :EX, :SH, :UN
38 # Sync#synchronize(mode) {...}
42 unless defined? Thread
43 fail "Thread not available for this ruby interpreter"
55 class Err < StandardError
57 fail self, sprintf(self::Message, *opt)
60 class UnknownLocker < Err
61 Message = "Thread(%s) not locked."
62 def UnknownLocker.Fail(th)
67 class LockModeFailer < Err
68 Message = "Unknown lock mode(%s)"
69 def LockModeFailer.Fail(mode)
78 def Sync_m.define_aliases(cl)
80 alias locked? sync_locked?
81 alias shared? sync_shared?
82 alias exclusive? sync_exclusive?
84 alias unlock sync_unlock
85 alias try_lock sync_try_lock
86 alias synchronize sync_synchronize
90 def Sync_m.append_features(cl)
92 unless cl.instance_of?(Module)
93 # do nothing for Modules
94 # make aliases and include the proper module.
99 def Sync_m.extend_object(obj)
105 unless (defined? locked? and
107 defined? exclusive? and
110 defined? try_lock and
111 defined? synchronize)
112 Sync_m.define_aliases(class<<self;self;end)
131 def sync_try_lock(mode = EX)
132 return unlock if sync_mode == UN
134 Thread.critical = true
135 ret = sync_try_lock_sub(sync_mode)
136 Thread.critical = false
140 def sync_lock(m = EX)
141 return unlock if m == UN
143 until (Thread.critical = true; sync_try_lock_sub(m))
144 if sync_sh_locker[Thread.current]
145 sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
146 sync_sh_locker.delete(Thread.current)
148 sync_waiting.push Thread.current
152 Thread.critical = false
156 def sync_unlock(m = EX)
157 Thread.critical = true
159 Thread.critical = false
160 Err::UnknownLocker.Fail(Thread.current)
163 m = sync_mode if m == EX and sync_mode == SH
168 Thread.critical = false
169 Err::UnknownLocker.Fail(Thread.current)
172 if sync_ex_locker == Thread.current
173 if (self.sync_ex_count = sync_ex_count - 1) == 0
174 self.sync_ex_locker = nil
175 if sync_sh_locker.include?(Thread.current)
183 Err::UnknownLocker.Fail(Thread.current)
187 if (count = sync_sh_locker[Thread.current]).nil?
188 Err::UnknownLocker.Fail(Thread.current)
190 if (sync_sh_locker[Thread.current] = count - 1) == 0
191 sync_sh_locker.delete(Thread.current)
192 if sync_sh_locker.empty? and sync_ex_count == 0
201 if sync_upgrade_waiting.size > 0
202 for k, v in sync_upgrade_waiting
203 sync_sh_locker[k] = v
205 wait = sync_upgrade_waiting
206 self.sync_upgrade_waiting = []
207 Thread.critical = false
214 self.sync_waiting = []
215 Thread.critical = false
222 Thread.critical = false
226 def sync_synchronize(mode = EX)
235 attr :sync_mode, true
237 attr :sync_waiting, true
238 attr :sync_upgrade_waiting, true
239 attr :sync_sh_locker, true
240 attr :sync_ex_locker, true
241 attr :sync_ex_count, true
248 @sync_upgrade_waiting = []
249 @sync_sh_locker = Hash.new
250 @sync_ex_locker = nil
254 def initialize(*args)
259 def sync_try_lock_sub(m)
265 sync_sh_locker[Thread.current] = 1
268 count = 0 unless count = sync_sh_locker[Thread.current]
269 sync_sh_locker[Thread.current] = count + 1
272 # in EX mode, lock will upgrade to EX lock
273 if sync_ex_locker == Thread.current
274 self.sync_ex_count = sync_ex_count + 1
281 if sync_mode == UN or
282 sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current)
284 self.sync_ex_locker = Thread.current
285 self.sync_ex_count = 1
287 elsif sync_mode == EX && sync_ex_locker == Thread.current
288 self.sync_ex_count = sync_ex_count + 1
294 Thread.critical = false
295 Err::LockModeFailer.Fail mode
300 Synchronizer_m = Sync_m
303 #Sync_m.extend_class self