[3c0760f] | 1 | import threading |
---|
| 2 | from . import sync |
---|
| 3 | |
---|
| 4 | class InterruptException(Exception): |
---|
| 5 | pass |
---|
| 6 | |
---|
| 7 | class PausingQueue(object): |
---|
| 8 | def __init__(self, lock=None): |
---|
| 9 | self._items = [] |
---|
| 10 | if lock: |
---|
| 11 | self.lock = lock |
---|
| 12 | else: |
---|
| 13 | self.lock = threading.RLock() |
---|
| 14 | self._ready = threading.Condition(self.lock) |
---|
| 15 | self._interrupted = False |
---|
| 16 | self._paused = False |
---|
| 17 | |
---|
| 18 | @sync |
---|
| 19 | def interrupt(self): |
---|
| 20 | self._interrupted = True |
---|
| 21 | self._ready.notifyAll() |
---|
| 22 | |
---|
| 23 | def wait_ready(func): |
---|
| 24 | @sync |
---|
| 25 | def do(self, *args, **kwargs): |
---|
| 26 | while self.paused or not self._items: |
---|
| 27 | self._ready.wait() |
---|
| 28 | if self._interrupted: |
---|
| 29 | raise InterruptException() |
---|
| 30 | return func(self, *args, **kwargs) |
---|
| 31 | return do |
---|
| 32 | |
---|
| 33 | def notify_ready(func): |
---|
| 34 | @sync |
---|
| 35 | def do(self, *args, **kwargs): |
---|
| 36 | if not self.paused: |
---|
| 37 | ret = func(self, *args, **kwargs) |
---|
| 38 | self._ready.notifyAll() |
---|
| 39 | return ret |
---|
| 40 | return do |
---|
| 41 | |
---|
| 42 | @property |
---|
| 43 | @sync |
---|
| 44 | def paused(self): |
---|
| 45 | return self._paused |
---|
| 46 | @paused.setter |
---|
| 47 | @sync |
---|
| 48 | def paused(self, val): |
---|
| 49 | self._paused = val |
---|
| 50 | if not self._paused: |
---|
| 51 | self._ready.notifyAll() |
---|
| 52 | |
---|
| 53 | |
---|
| 54 | @wait_ready |
---|
| 55 | def pop(self): |
---|
| 56 | return self._items.pop(0) |
---|
| 57 | |
---|
| 58 | @notify_ready |
---|
| 59 | def push(self, item): |
---|
| 60 | self._items.insert(0, item) |
---|
| 61 | |
---|
| 62 | @notify_ready |
---|
| 63 | def append(self, item): |
---|
| 64 | self._items.append(item) |
---|
| 65 | |
---|
| 66 | @notify_ready |
---|
| 67 | def insert(self, index, item): |
---|
| 68 | self._items.insert(index, item) |
---|
| 69 | |
---|
| 70 | @sync |
---|
| 71 | def promote(self, item): |
---|
| 72 | self.move(0, item) |
---|
| 73 | |
---|
| 74 | @sync |
---|
| 75 | def move(self, index, item): |
---|
| 76 | self._items.remove(item) |
---|
| 77 | self._items.insert(index, item) |
---|
| 78 | |
---|
| 79 | @sync |
---|
| 80 | def copy(self): |
---|
| 81 | return self._items[:] |
---|
| 82 | |
---|
| 83 | @sync |
---|
| 84 | def empty(self): |
---|
| 85 | return not bool(self._items) |
---|
| 86 | |
---|
| 87 | @sync |
---|
| 88 | def __len__(self): |
---|
| 89 | return len(self._items) |
---|
| 90 | |
---|
| 91 | @sync |
---|
| 92 | def __contains__(self, val): |
---|
| 93 | return val in self._items |
---|