Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 1 | # 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 Rossum | ce08448 | 1991-12-26 13:06:29 +0000 | [diff] [blame] | 14 | class mutex: |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 15 | # |
| 16 | # Create a new mutex -- initially unlocked |
| 17 | # |
Guido van Rossum | 7bc817d | 1993-12-17 15:25:27 +0000 | [diff] [blame] | 18 | def __init__(self): |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 19 | self.locked = 0 |
| 20 | self.queue = [] |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 21 | # |
| 22 | # Test the locked bit of the mutex |
| 23 | # |
| 24 | def test(self): |
| 25 | return self.locked |
| 26 | # |
| 27 | # Atomic test-and-set -- grab the lock if it is not set, |
| 28 | # return true if it succeeded |
| 29 | # |
| 30 | def testandset(self): |
| 31 | if not self.locked: |
| 32 | self.locked = 1 |
| 33 | return 1 |
| 34 | else: |
| 35 | return 0 |
| 36 | # |
| 37 | # Lock a mutex, call the function with supplied argument |
| 38 | # when it is acquired. |
| 39 | # If the mutex is already locked, place function and argument |
| 40 | # in the queue. |
| 41 | # |
Guido van Rossum | 89a7869 | 1992-12-14 12:57:56 +0000 | [diff] [blame] | 42 | def lock(self, function, argument): |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 43 | if self.testandset(): |
| 44 | function(argument) |
| 45 | else: |
Guido van Rossum | b7f48e3 | 1996-10-08 14:06:17 +0000 | [diff] [blame] | 46 | self.queue.append((function, argument)) |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 47 | # |
| 48 | # Unlock a mutex. If the queue is not empty, call the next |
| 49 | # function with its argument. |
| 50 | # |
| 51 | def unlock(self): |
| 52 | if self.queue: |
| 53 | function, argument = self.queue[0] |
| 54 | del self.queue[0] |
| 55 | function(argument) |
| 56 | else: |
| 57 | self.locked = 0 |
| 58 | # |