Skip to content

Commit c01c20e

Browse files
committed
can reject doWhile loop
1 parent f4bd4c4 commit c01c20e

File tree

2 files changed

+61
-21
lines changed

2 files changed

+61
-21
lines changed

add_ons/qt/promise_qt.hpp

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <chrono>
4646
#include <QObject>
4747
#include <QTimerEvent>
48+
#include <QApplication>
4849

4950
namespace promise {
5051

@@ -75,28 +76,31 @@ class PromiseEventFilter : public QObject {
7576
protected:
7677
bool eventFilter(QObject *object, QEvent *event) {
7778
std::pair<QObject *, QEvent::Type> key = { object, event->type() };
78-
Listeners::iterator itr = listeners_.find(key);
79-
if (itr != listeners_.end()) {
80-
return itr->second(object, event);
79+
80+
// may not safe if one handler is removed by other
81+
std::list<Listeners::iterator> itrs;
82+
for(Listeners::iterator itr = listeners_.lower_bound(key);
83+
itr != listeners_.end() && key == itr->first; ++itr) {
84+
itrs.push_back(itr);
85+
}
86+
for(Listeners::iterator itr: itrs) {
87+
itr->second(object, event);
8188
}
8289

8390
if (event->type() == QEvent::Destroy) {
84-
return removeObjectFilters(object);
91+
removeObjectFilters(object);
8592
}
8693

87-
return false;
94+
return QObject::eventFilter(object, event);
8895
}
8996

9097
bool removeObjectFilters(QObject *object) {
9198
std::pair<QObject *, QEvent::Type> key = { object, QEvent::None };
9299

93-
std::list<Listeners::iterator> deletes;
94-
95-
100+
// checked one by one for safety (others may be removed)
96101
while(true) {
97102
Listeners::iterator itr = listeners_.lower_bound(key);
98103
if(itr != listeners_.end() && itr->first.first == object) {
99-
// one by one for safety
100104
itr->second(object, nullptr);
101105
}
102106
else {
@@ -112,20 +116,34 @@ class PromiseEventFilter : public QObject {
112116

113117
// Wait event will wait the event for only once
114118
inline Defer waitEvent(QObject *object,
115-
QEvent::Type eventType) {
119+
QEvent::Type eventType,
120+
bool callSysHandler = false) {
116121
Defer promise = newPromise();
117122

123+
std::shared_ptr<bool> disableFilter = std::make_shared<bool>(false);
118124
auto listener = PromiseEventFilter::getSingleInstance().addEventListener(
119-
object, eventType, [promise](QObject *object, QEvent *event) {
125+
object, eventType, [promise, callSysHandler, disableFilter](QObject *object, QEvent *event) {
120126
(void)object;
121-
if (event == nullptr)
127+
if (event == nullptr) {
122128
promise->reject();
129+
return false;
130+
}
131+
// The next then function will be call immediately
132+
// Be care that do not use event in the next event loop
133+
else if (*disableFilter) {
134+
return false;
135+
}
136+
else if (callSysHandler) {
137+
*disableFilter = true;
138+
QApplication::sendEvent(object, event);
139+
*disableFilter = false;
140+
promise->resolve(event);
141+
return true;
142+
}
123143
else {
124-
// The next then function will be call immediately
125-
// Be care that do not use event in the next event loop
126144
promise->resolve(event);
145+
return false;
127146
}
128-
return false;
129147
}
130148
);
131149

promise.hpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,10 @@ class pm_shared_ptr {
303303
return object_;
304304
}
305305

306+
inline T &operator*() const {
307+
return *object_;
308+
}
309+
306310
inline T *obtain_rawptr() {
307311
pm_allocator::add_ref(object_);
308312
return object_;
@@ -1331,20 +1335,24 @@ inline Defer newPromise(FUNC func) {
13311335
* if the returned Defer object was obtained by other and not released.
13321336
*/
13331337
template <typename FUNC>
1334-
inline Defer doWhile_unsafe(FUNC func) {
1335-
return newPromise(func).then([func]() {
1336-
return doWhile_unsafe(func);
1338+
inline Defer doWhile_unsafe(FUNC func, pm_shared_ptr<Defer> current) {
1339+
*current = newPromise(func).then([current, func]() {
1340+
return doWhile_unsafe(func, current);
13371341
});
1342+
return *current;
13381343
}
13391344

13401345
/* While loop func call resolved */
13411346
template <typename FUNC>
13421347
inline Defer doWhile(FUNC func) {
1343-
return newPromise([func](Defer d) {
1344-
doWhile_unsafe(func).then(d);
1345-
}).fail([](Defer &self, Promise *caller) -> BypassAndResolve {
1348+
pm_shared_ptr<Defer> currnet = pm_shared_ptr<Defer>(pm_new<Defer>());
1349+
1350+
return newPromise([func, currnet](Defer d) {
1351+
doWhile_unsafe(func, currnet).then(d);
1352+
}).fail([currnet](Defer &self, Promise *caller) -> BypassAndResolve {
13461353
(void)self;
13471354
(void)caller;
1355+
currnet->doBreak();
13481356
return BypassAndResolve();
13491357
});
13501358
}
@@ -1450,6 +1458,20 @@ inline Defer raceAndReject(PROMISE_LIST ...promise_list) {
14501458
return raceAndReject({ promise_list ... });
14511459
}
14521460

1461+
inline Defer raceAndResolve(const std::initializer_list<Defer> &promise_list) {
1462+
std::vector<Defer> copy_list = promise_list;
1463+
return race(promise_list).finally([copy_list] {
1464+
for (auto defer : copy_list) {
1465+
defer.resolve();
1466+
}
1467+
});
1468+
}
1469+
1470+
template <typename ... PROMISE_LIST>
1471+
inline Defer raceAndResolve(PROMISE_LIST ...promise_list) {
1472+
return raceAndReject({ promise_list ... });
1473+
}
1474+
14531475

14541476
#ifndef PM_EMBED
14551477
inline void handleUncaughtException(const FnOnUncaughtException &onUncaughtException) {

0 commit comments

Comments
 (0)