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