0001 """Mutual exclusion -- for use with module sched 0002 0003 A mutex has two pieces of state -- a 'locked' bit and a queue. 0004 When the mutex is not locked, the queue is empty. 0005 Otherwise, the queue contains 0 or more (function, argument) pairs 0006 representing functions (or methods) waiting to acquire the lock. 0007 When the mutex is unlocked while the queue is not empty, 0008 the first queue entry is removed and its function(argument) pair called, 0009 implying it now has the lock. 0010 0011 Of course, no multi-threading is implied -- hence the funny interface 0012 for lock, where a function is called once the lock is aquired. 0013 """ 0014 0015 from collections import deque 0016 0017 class mutex: 0018 def __init__(self): 0019 """Create a new mutex -- initially unlocked.""" 0020 self.locked = 0 0021 self.queue = deque() 0022 0023 def test(self): 0024 """Test the locked bit of the mutex.""" 0025 return self.locked 0026 0027 def testandset(self): 0028 """Atomic test-and-set -- grab the lock if it is not set, 0029 return True if it succeeded.""" 0030 if not self.locked: 0031 self.locked = 1 0032 return True 0033 else: 0034 return False 0035 0036 def lock(self, function, argument): 0037 """Lock a mutex, call the function with supplied argument 0038 when it is acquired. If the mutex is already locked, place 0039 function and argument in the queue.""" 0040 if self.testandset(): 0041 function(argument) 0042 else: 0043 self.queue.append((function, argument)) 0044 0045 def unlock(self): 0046 """Unlock a mutex. If the queue is not empty, call the next 0047 function with its argument.""" 0048 if self.queue: 0049 function, argument = self.queue.popleft() 0050 function(argument) 0051 else: 0052 self.locked = 0 0053
Generated by PyXR 0.9.4