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 | |
21 | namespace Poco { |
22 | |
23 | |
24 | PriorityNotificationQueue::PriorityNotificationQueue() |
25 | { |
26 | } |
27 | |
28 | |
29 | PriorityNotificationQueue::~PriorityNotificationQueue() |
30 | { |
31 | try |
32 | { |
33 | clear(); |
34 | } |
35 | catch (...) |
36 | { |
37 | poco_unexpected(); |
38 | } |
39 | } |
40 | |
41 | |
42 | void 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 | |
61 | Notification* PriorityNotificationQueue::dequeueNotification() |
62 | { |
63 | FastMutex::ScopedLock lock(_mutex); |
64 | return dequeueOne().duplicate(); |
65 | } |
66 | |
67 | |
68 | Notification* 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 | |
86 | Notification* 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 | |
119 | void 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 | |
131 | void 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 | |
142 | bool PriorityNotificationQueue::empty() const |
143 | { |
144 | FastMutex::ScopedLock lock(_mutex); |
145 | return _nfQueue.empty(); |
146 | } |
147 | |
148 | |
149 | int PriorityNotificationQueue::size() const |
150 | { |
151 | FastMutex::ScopedLock lock(_mutex); |
152 | return static_cast<int>(_nfQueue.size()); |
153 | } |
154 | |
155 | |
156 | void PriorityNotificationQueue::clear() |
157 | { |
158 | FastMutex::ScopedLock lock(_mutex); |
159 | _nfQueue.clear(); |
160 | } |
161 | |
162 | |
163 | bool PriorityNotificationQueue::hasIdleThreads() const |
164 | { |
165 | FastMutex::ScopedLock lock(_mutex); |
166 | return !_waitQueue.empty(); |
167 | } |
168 | |
169 | |
170 | Notification::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 | |
183 | namespace |
184 | { |
185 | static SingletonHolder<PriorityNotificationQueue> sh; |
186 | } |
187 | |
188 | |
189 | PriorityNotificationQueue& PriorityNotificationQueue::defaultQueue() |
190 | { |
191 | return *sh.get(); |
192 | } |
193 | |
194 | |
195 | } // namespace Poco |
196 |