Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 1 | """Mutual exclusion -- for use with module sched |
Guido van Rossum | e2e162e | 1991-04-21 19:32:43 +0000 | [diff] [blame] | 2 | |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 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 | """ |
Brett Cannon | 9d44182 | 2008-05-08 19:26:08 +0000 | [diff] [blame] | 14 | from warnings import warnpy3k |
| 15 | warnpy3k("the mutex module has been removed in Python 3.0", stacklevel=2) |
| 16 | del warnpy3k |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 17 | |
Raymond Hettinger | 756b3f3 | 2004-01-29 06:37:52 +0000 | [diff] [blame] | 18 | from collections import deque |
| 19 | |
Guido van Rossum | ce08448 | 1991-12-26 13:06:29 +0000 | [diff] [blame] | 20 | class mutex: |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 21 | def __init__(self): |
| 22 | """Create a new mutex -- initially unlocked.""" |
Benjamin Peterson | fd0107f | 2009-01-27 23:15:48 +0000 | [diff] [blame] | 23 | self.locked = False |
Raymond Hettinger | 756b3f3 | 2004-01-29 06:37:52 +0000 | [diff] [blame] | 24 | self.queue = deque() |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 25 | |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 26 | def test(self): |
| 27 | """Test the locked bit of the mutex.""" |
| 28 | return self.locked |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 29 | |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 30 | def testandset(self): |
| 31 | """Atomic test-and-set -- grab the lock if it is not set, |
Tim Peters | bc0e910 | 2002-04-04 22:55:58 +0000 | [diff] [blame] | 32 | return True if it succeeded.""" |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 33 | if not self.locked: |
Benjamin Peterson | fd0107f | 2009-01-27 23:15:48 +0000 | [diff] [blame] | 34 | self.locked = True |
Tim Peters | bc0e910 | 2002-04-04 22:55:58 +0000 | [diff] [blame] | 35 | return True |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 36 | else: |
Tim Peters | bc0e910 | 2002-04-04 22:55:58 +0000 | [diff] [blame] | 37 | return False |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 38 | |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 39 | def lock(self, function, argument): |
| 40 | """Lock a mutex, call the function with supplied argument |
| 41 | when it is acquired. If the mutex is already locked, place |
| 42 | function and argument in the queue.""" |
| 43 | if self.testandset(): |
| 44 | function(argument) |
| 45 | else: |
| 46 | self.queue.append((function, argument)) |
Guido van Rossum | 54f22ed | 2000-02-04 15:10:34 +0000 | [diff] [blame] | 47 | |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 48 | def unlock(self): |
| 49 | """Unlock a mutex. If the queue is not empty, call the next |
| 50 | function with its argument.""" |
| 51 | if self.queue: |
Raymond Hettinger | 756b3f3 | 2004-01-29 06:37:52 +0000 | [diff] [blame] | 52 | function, argument = self.queue.popleft() |
Tim Peters | 07e99cb | 2001-01-14 23:47:14 +0000 | [diff] [blame] | 53 | function(argument) |
| 54 | else: |
Benjamin Peterson | fd0107f | 2009-01-27 23:15:48 +0000 | [diff] [blame] | 55 | self.locked = False |