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 |
---|