1 | // |
---|---|
2 | // NotificationQueue.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Notifications |
6 | // Module: NotificationQueue |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/NotificationQueue.h" |
16 | #include "Poco/NotificationCenter.h" |
17 | #include "Poco/Notification.h" |
18 | #include "Poco/SingletonHolder.h" |
19 | |
20 | |
21 | namespace Poco { |
22 | |
23 | |
24 | NotificationQueue::NotificationQueue() |
25 | { |
26 | } |
27 | |
28 | |
29 | NotificationQueue::~NotificationQueue() |
30 | { |
31 | try |
32 | { |
33 | clear(); |
34 | } |
35 | catch (...) |
36 | { |
37 | poco_unexpected(); |
38 | } |
39 | } |
40 | |
41 | |
42 | void NotificationQueue::enqueueNotification(Notification::Ptr pNotification) |
43 | { |
44 | poco_check_ptr (pNotification); |
45 | FastMutex::ScopedLock lock(_mutex); |
46 | if (_waitQueue.empty()) |
47 | { |
48 | _nfQueue.push_back(pNotification); |
49 | } |
50 | else |
51 | { |
52 | WaitInfo* pWI = _waitQueue.front(); |
53 | _waitQueue.pop_front(); |
54 | pWI->pNf = pNotification; |
55 | pWI->nfAvailable.set(); |
56 | } |
57 | } |
58 | |
59 | |
60 | void NotificationQueue::enqueueUrgentNotification(Notification::Ptr pNotification) |
61 | { |
62 | poco_check_ptr (pNotification); |
63 | FastMutex::ScopedLock lock(_mutex); |
64 | if (_waitQueue.empty()) |
65 | { |
66 | _nfQueue.push_front(pNotification); |
67 | } |
68 | else |
69 | { |
70 | WaitInfo* pWI = _waitQueue.front(); |
71 | _waitQueue.pop_front(); |
72 | pWI->pNf = pNotification; |
73 | pWI->nfAvailable.set(); |
74 | } |
75 | } |
76 | |
77 | |
78 | Notification* NotificationQueue::dequeueNotification() |
79 | { |
80 | FastMutex::ScopedLock lock(_mutex); |
81 | return dequeueOne().duplicate(); |
82 | } |
83 | |
84 | |
85 | Notification* NotificationQueue::waitDequeueNotification() |
86 | { |
87 | Notification::Ptr pNf; |
88 | WaitInfo* pWI = 0; |
89 | { |
90 | FastMutex::ScopedLock lock(_mutex); |
91 | pNf = dequeueOne(); |
92 | if (pNf) return pNf.duplicate(); |
93 | pWI = new WaitInfo; |
94 | _waitQueue.push_back(pWI); |
95 | } |
96 | pWI->nfAvailable.wait(); |
97 | pNf = pWI->pNf; |
98 | delete pWI; |
99 | return pNf.duplicate(); |
100 | } |
101 | |
102 | |
103 | Notification* NotificationQueue::waitDequeueNotification(long milliseconds) |
104 | { |
105 | Notification::Ptr pNf; |
106 | WaitInfo* pWI = 0; |
107 | { |
108 | FastMutex::ScopedLock lock(_mutex); |
109 | pNf = dequeueOne(); |
110 | if (pNf) return pNf.duplicate(); |
111 | pWI = new WaitInfo; |
112 | _waitQueue.push_back(pWI); |
113 | } |
114 | if (pWI->nfAvailable.tryWait(milliseconds)) |
115 | { |
116 | pNf = pWI->pNf; |
117 | } |
118 | else |
119 | { |
120 | FastMutex::ScopedLock lock(_mutex); |
121 | pNf = pWI->pNf; |
122 | for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it) |
123 | { |
124 | if (*it == pWI) |
125 | { |
126 | _waitQueue.erase(it); |
127 | break; |
128 | } |
129 | } |
130 | } |
131 | delete pWI; |
132 | return pNf.duplicate(); |
133 | } |
134 | |
135 | |
136 | void NotificationQueue::dispatch(NotificationCenter& notificationCenter) |
137 | { |
138 | FastMutex::ScopedLock lock(_mutex); |
139 | Notification::Ptr pNf = dequeueOne(); |
140 | while (pNf) |
141 | { |
142 | notificationCenter.postNotification(pNf); |
143 | pNf = dequeueOne(); |
144 | } |
145 | } |
146 | |
147 | |
148 | void NotificationQueue::wakeUpAll() |
149 | { |
150 | FastMutex::ScopedLock lock(_mutex); |
151 | for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it) |
152 | { |
153 | (*it)->nfAvailable.set(); |
154 | } |
155 | _waitQueue.clear(); |
156 | } |
157 | |
158 | |
159 | bool NotificationQueue::empty() const |
160 | { |
161 | FastMutex::ScopedLock lock(_mutex); |
162 | return _nfQueue.empty(); |
163 | } |
164 | |
165 | |
166 | int NotificationQueue::size() const |
167 | { |
168 | FastMutex::ScopedLock lock(_mutex); |
169 | return static_cast<int>(_nfQueue.size()); |
170 | } |
171 | |
172 | |
173 | void NotificationQueue::clear() |
174 | { |
175 | FastMutex::ScopedLock lock(_mutex); |
176 | _nfQueue.clear(); |
177 | } |
178 | |
179 | |
180 | bool NotificationQueue::remove(Notification::Ptr pNotification) |
181 | { |
182 | FastMutex::ScopedLock lock(_mutex); |
183 | NfQueue::iterator it = std::find(_nfQueue.begin(), _nfQueue.end(), pNotification); |
184 | if (it == _nfQueue.end()) |
185 | { |
186 | return false; |
187 | } |
188 | _nfQueue.erase(it); |
189 | return true; |
190 | } |
191 | |
192 | |
193 | bool NotificationQueue::hasIdleThreads() const |
194 | { |
195 | FastMutex::ScopedLock lock(_mutex); |
196 | return !_waitQueue.empty(); |
197 | } |
198 | |
199 | |
200 | Notification::Ptr NotificationQueue::dequeueOne() |
201 | { |
202 | Notification::Ptr pNf; |
203 | if (!_nfQueue.empty()) |
204 | { |
205 | pNf = _nfQueue.front(); |
206 | _nfQueue.pop_front(); |
207 | } |
208 | return pNf; |
209 | } |
210 | |
211 | |
212 | namespace |
213 | { |
214 | static SingletonHolder<NotificationQueue> sh; |
215 | } |
216 | |
217 | |
218 | NotificationQueue& NotificationQueue::defaultQueue() |
219 | { |
220 | return *sh.get(); |
221 | } |
222 | |
223 | |
224 | } // namespace Poco |
225 |