@@ -29,6 +29,56 @@ DispatchQueue::~DispatchQueue(void) {
29
29
}
30
30
}
31
31
32
+ void DispatchQueue::ClearQueueInternal (bool executeDispatchers) {
33
+ // Do not permit any more lambdas to be pended to our queue
34
+ DispatchThunkBase* pHead;
35
+ {
36
+ std::priority_queue<autowiring::DispatchThunkDelayed> delayedQueue;
37
+ std::lock_guard<std::mutex> lk (m_dispatchLock);
38
+ onAborted ();
39
+ m_dispatchCap = 0 ;
40
+ pHead = m_pHead;
41
+ m_pHead = nullptr ;
42
+ m_pTail = nullptr ;
43
+ delayedQueue = std::move (m_delayedQueue);
44
+ }
45
+
46
+ // Execute dispatchers if asked to do so
47
+ if (executeDispatchers)
48
+ while (pHead)
49
+ try {
50
+ auto next = pHead->m_pFlink ;
51
+ (*pHead)();
52
+ delete pHead;
53
+ pHead = next;
54
+
55
+ // Need to update this as we go along due to the requirements of rundown behavior
56
+ m_count--;
57
+ }
58
+ catch (dispatch_aborted_exception&) {
59
+ // Silently ignore, as per documentation
60
+ } catch (...) {
61
+ // Stop executing dispatchers, nothing we can do here
62
+ break ;
63
+ }
64
+
65
+ // Destroy everything else. Do so in an unsynchronized context in order to prevent reentrancy.
66
+ size_t nTraversed = 0 ;
67
+ for (auto cur = pHead; cur;) {
68
+ auto next = cur->m_pFlink ;
69
+ delete cur;
70
+ cur = next;
71
+ nTraversed++;
72
+ }
73
+
74
+ // Decrement the count by the number of entries we actually traversed. Abort may potentially
75
+ // be called from a lambda function, so assigning this value directly to zero would be an error.
76
+ m_count -= nTraversed;
77
+
78
+ // Wake up anyone who is still waiting:
79
+ m_queueUpdated.notify_all ();
80
+ }
81
+
32
82
bool DispatchQueue::PromoteReadyDispatchersUnsafe (void ) {
33
83
// Move all ready elements out of the delayed queue and into the dispatch queue:
34
84
size_t nInitial = m_delayedQueue.size ();
@@ -97,35 +147,11 @@ void DispatchQueue::TryDispatchEventUnsafe(std::unique_lock<std::mutex>& lk) {
97
147
}
98
148
99
149
void DispatchQueue::Abort (void ) {
100
- // Do not permit any more lambdas to be pended to our queue
101
- DispatchThunkBase* pHead;
102
- {
103
- std::priority_queue<autowiring::DispatchThunkDelayed> delayedQueue;
104
- std::lock_guard<std::mutex> lk (m_dispatchLock);
105
- onAborted ();
106
- m_dispatchCap = 0 ;
107
- pHead = m_pHead;
108
- m_pHead = nullptr ;
109
- m_pTail = nullptr ;
110
- delayedQueue = std::move (m_delayedQueue);
111
- }
112
-
113
- // Destroy the whole dispatch queue. Do so in an unsynchronized context in order to prevent
114
- // reentrancy.
115
- size_t nTraversed = 0 ;
116
- for (auto cur = pHead; cur;) {
117
- auto next = cur->m_pFlink ;
118
- delete cur;
119
- cur = next;
120
- nTraversed++;
121
- }
122
-
123
- // Decrement the count by the number of entries we actually traversed. Abort may potentially
124
- // be called from a lambda function, so assigning this value directly to zero would be an error.
125
- m_count -= nTraversed;
150
+ ClearQueueInternal (false );
151
+ }
126
152
127
- // Wake up anyone who is still waiting:
128
- m_queueUpdated. notify_all ( );
153
+ void DispatchQueue::Rundown ( void ) {
154
+ ClearQueueInternal ( true );
129
155
}
130
156
131
157
bool DispatchQueue::Cancel (void ) {
0 commit comments