Skip to content

Commit

Permalink
can reject doWhile loop
Browse files Browse the repository at this point in the history
  • Loading branch information
xhawk18 committed Jun 18, 2021
1 parent f4bd4c4 commit c01c20e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 21 deletions.
48 changes: 33 additions & 15 deletions add_ons/qt/promise_qt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <chrono>
#include <QObject>
#include <QTimerEvent>
#include <QApplication>

namespace promise {

Expand Down Expand Up @@ -75,28 +76,31 @@ class PromiseEventFilter : public QObject {
protected:
bool eventFilter(QObject *object, QEvent *event) {
std::pair<QObject *, QEvent::Type> key = { object, event->type() };
Listeners::iterator itr = listeners_.find(key);
if (itr != listeners_.end()) {
return itr->second(object, event);

// may not safe if one handler is removed by other
std::list<Listeners::iterator> itrs;
for(Listeners::iterator itr = listeners_.lower_bound(key);
itr != listeners_.end() && key == itr->first; ++itr) {
itrs.push_back(itr);
}
for(Listeners::iterator itr: itrs) {
itr->second(object, event);
}

if (event->type() == QEvent::Destroy) {
return removeObjectFilters(object);
removeObjectFilters(object);
}

return false;
return QObject::eventFilter(object, event);
}

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

std::list<Listeners::iterator> deletes;


// checked one by one for safety (others may be removed)
while(true) {
Listeners::iterator itr = listeners_.lower_bound(key);
if(itr != listeners_.end() && itr->first.first == object) {
// one by one for safety
itr->second(object, nullptr);
}
else {
Expand All @@ -112,20 +116,34 @@ class PromiseEventFilter : public QObject {

// Wait event will wait the event for only once
inline Defer waitEvent(QObject *object,
QEvent::Type eventType) {
QEvent::Type eventType,
bool callSysHandler = false) {
Defer promise = newPromise();

std::shared_ptr<bool> disableFilter = std::make_shared<bool>(false);
auto listener = PromiseEventFilter::getSingleInstance().addEventListener(
object, eventType, [promise](QObject *object, QEvent *event) {
object, eventType, [promise, callSysHandler, disableFilter](QObject *object, QEvent *event) {
(void)object;
if (event == nullptr)
if (event == nullptr) {
promise->reject();
return false;
}
// The next then function will be call immediately
// Be care that do not use event in the next event loop
else if (*disableFilter) {
return false;
}
else if (callSysHandler) {
*disableFilter = true;
QApplication::sendEvent(object, event);
*disableFilter = false;
promise->resolve(event);
return true;
}
else {
// The next then function will be call immediately
// Be care that do not use event in the next event loop
promise->resolve(event);
return false;
}
return false;
}
);

Expand Down
34 changes: 28 additions & 6 deletions promise.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ class pm_shared_ptr {
return object_;
}

inline T &operator*() const {
return *object_;
}

inline T *obtain_rawptr() {
pm_allocator::add_ref(object_);
return object_;
Expand Down Expand Up @@ -1331,20 +1335,24 @@ inline Defer newPromise(FUNC func) {
* if the returned Defer object was obtained by other and not released.
*/
template <typename FUNC>
inline Defer doWhile_unsafe(FUNC func) {
return newPromise(func).then([func]() {
return doWhile_unsafe(func);
inline Defer doWhile_unsafe(FUNC func, pm_shared_ptr<Defer> current) {
*current = newPromise(func).then([current, func]() {
return doWhile_unsafe(func, current);
});
return *current;
}

/* While loop func call resolved */
template <typename FUNC>
inline Defer doWhile(FUNC func) {
return newPromise([func](Defer d) {
doWhile_unsafe(func).then(d);
}).fail([](Defer &self, Promise *caller) -> BypassAndResolve {
pm_shared_ptr<Defer> currnet = pm_shared_ptr<Defer>(pm_new<Defer>());

return newPromise([func, currnet](Defer d) {
doWhile_unsafe(func, currnet).then(d);
}).fail([currnet](Defer &self, Promise *caller) -> BypassAndResolve {
(void)self;
(void)caller;
currnet->doBreak();
return BypassAndResolve();
});
}
Expand Down Expand Up @@ -1450,6 +1458,20 @@ inline Defer raceAndReject(PROMISE_LIST ...promise_list) {
return raceAndReject({ promise_list ... });
}

inline Defer raceAndResolve(const std::initializer_list<Defer> &promise_list) {
std::vector<Defer> copy_list = promise_list;
return race(promise_list).finally([copy_list] {
for (auto defer : copy_list) {
defer.resolve();
}
});
}

template <typename ... PROMISE_LIST>
inline Defer raceAndResolve(PROMISE_LIST ...promise_list) {
return raceAndReject({ promise_list ... });
}


#ifndef PM_EMBED
inline void handleUncaughtException(const FnOnUncaughtException &onUncaughtException) {
Expand Down

0 comments on commit c01c20e

Please sign in to comment.