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
21namespace Poco {
22
23
24NotificationQueue::NotificationQueue()
25{
26}
27
28
29NotificationQueue::~NotificationQueue()
30{
31 try
32 {
33 clear();
34 }
35 catch (...)
36 {
37 poco_unexpected();
38 }
39}
40
41
42void 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
60void 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
78Notification* NotificationQueue::dequeueNotification()
79{
80 FastMutex::ScopedLock lock(_mutex);
81 return dequeueOne().duplicate();
82}
83
84
85Notification* 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
103Notification* 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
136void 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
148void 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
159bool NotificationQueue::empty() const
160{
161 FastMutex::ScopedLock lock(_mutex);
162 return _nfQueue.empty();
163}
164
165
166int NotificationQueue::size() const
167{
168 FastMutex::ScopedLock lock(_mutex);
169 return static_cast<int>(_nfQueue.size());
170}
171
172
173void NotificationQueue::clear()
174{
175 FastMutex::ScopedLock lock(_mutex);
176 _nfQueue.clear();
177}
178
179
180bool 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
193bool NotificationQueue::hasIdleThreads() const
194{
195 FastMutex::ScopedLock lock(_mutex);
196 return !_waitQueue.empty();
197}
198
199
200Notification::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
212namespace
213{
214 static SingletonHolder<NotificationQueue> sh;
215}
216
217
218NotificationQueue& NotificationQueue::defaultQueue()
219{
220 return *sh.get();
221}
222
223
224} // namespace Poco
225