blob: c939b1a607b30ed3997749d302a8998fd7865f54 [file] [log] [blame]
Guido van Rossume2e162e1991-04-21 19:32:43 +00001# Mutual exclusion -- for use with module sched
2
3# A mutex has two pieces of state -- a 'locked' bit and a queue.
4# When the mutex is not locked, the queue is empty.
5# Otherwise, the queue contains 0 or more (function, argument) pairs
6# representing functions (or methods) waiting to acquire the lock.
7# When the mutex is unlocked while the queue is not empty,
8# the first queue entry is removed and its function(argument) pair called,
9# implying it now has the lock.
10#
11# Of course, no multi-threading is implied -- hence the funny interface
12# for lock, where a function is called once the lock is aquired.
13#
Guido van Rossumce084481991-12-26 13:06:29 +000014class mutex:
Guido van Rossume2e162e1991-04-21 19:32:43 +000015 #
16 # Create a new mutex -- initially unlocked
17 #
18 def init(self):
19 self.locked = 0
20 self.queue = []
21 return self
22 #
23 # Test the locked bit of the mutex
24 #
25 def test(self):
26 return self.locked
27 #
28 # Atomic test-and-set -- grab the lock if it is not set,
29 # return true if it succeeded
30 #
31 def testandset(self):
32 if not self.locked:
33 self.locked = 1
34 return 1
35 else:
36 return 0
37 #
38 # Lock a mutex, call the function with supplied argument
39 # when it is acquired.
40 # If the mutex is already locked, place function and argument
41 # in the queue.
42 #
43 def lock(self, (function, argument)):
44 if self.testandset():
45 function(argument)
46 else:
47 self.queue.append(function, argument)
48 #
49 # Unlock a mutex. If the queue is not empty, call the next
50 # function with its argument.
51 #
52 def unlock(self):
53 if self.queue:
54 function, argument = self.queue[0]
55 del self.queue[0]
56 function(argument)
57 else:
58 self.locked = 0
59 #