1 #include "run_loop_impl.hpp"
2
3 #include <mbgl/actor/scheduler.hpp>
4
5 #include <QCoreApplication>
6
7 #include <cassert>
8 #include <functional>
9 #include <utility>
10
11 namespace mbgl {
12 namespace util {
13
onReadEvent(int fd)14 void RunLoop::Impl::onReadEvent(int fd) {
15 readPoll[fd].second(fd, Event::Read);
16 }
17
onWriteEvent(int fd)18 void RunLoop::Impl::onWriteEvent(int fd) {
19 writePoll[fd].second(fd, Event::Write);
20 }
21
Get()22 RunLoop* RunLoop::Get() {
23 assert(static_cast<RunLoop*>(Scheduler::GetCurrent()));
24 return static_cast<RunLoop*>(Scheduler::GetCurrent());
25 }
26
RunLoop(Type type)27 RunLoop::RunLoop(Type type) : impl(std::make_unique<Impl>()) {
28 switch (type) {
29 case Type::New:
30 impl->loop = std::make_unique<QEventLoop>();
31 break;
32 case Type::Default:
33 // Use QCoreApplication::instance().
34 break;
35 }
36
37 impl->type = type;
38
39 Scheduler::SetCurrent(this);
40 impl->async = std::make_unique<AsyncTask>(std::bind(&RunLoop::process, this));
41 }
42
~RunLoop()43 RunLoop::~RunLoop() {
44 MBGL_VERIFY_THREAD(tid);
45
46 Scheduler::SetCurrent(nullptr);
47 }
48
getLoopHandle()49 LOOP_HANDLE RunLoop::getLoopHandle() {
50 throw std::runtime_error("Should not be used in Qt.");
51
52 return nullptr;
53 }
54
wake()55 void RunLoop::wake() {
56 impl->async->send();
57 }
58
run()59 void RunLoop::run() {
60 assert(QCoreApplication::instance());
61 MBGL_VERIFY_THREAD(tid);
62
63 if (impl->type == Type::Default) {
64 QCoreApplication::instance()->exec();
65 } else {
66 impl->loop->exec();
67 }
68 }
69
stop()70 void RunLoop::stop() {
71 assert(QCoreApplication::instance());
72 invoke([&] {
73 if (impl->type == Type::Default) {
74 QCoreApplication::instance()->exit();
75 } else {
76 impl->loop->exit();
77 }
78 });
79 }
80
runOnce()81 void RunLoop::runOnce() {
82 assert(QCoreApplication::instance());
83 MBGL_VERIFY_THREAD(tid);
84
85 if (impl->type == Type::Default) {
86 QCoreApplication::instance()->processEvents();
87 } else {
88 impl->loop->processEvents();
89 }
90 }
91
addWatch(int fd,Event event,std::function<void (int,Event)> && cb)92 void RunLoop::addWatch(int fd, Event event, std::function<void(int, Event)>&& cb) {
93 MBGL_VERIFY_THREAD(tid);
94
95 if (event == Event::Read || event == Event::ReadWrite) {
96 auto notifier = std::make_unique<QSocketNotifier>(fd, QSocketNotifier::Read);
97 QObject::connect(notifier.get(), SIGNAL(activated(int)), impl.get(), SLOT(onReadEvent(int)));
98 impl->readPoll[fd] = WatchPair(std::move(notifier), std::move(cb));
99 }
100
101 if (event == Event::Write || event == Event::ReadWrite) {
102 auto notifier = std::make_unique<QSocketNotifier>(fd, QSocketNotifier::Write);
103 QObject::connect(notifier.get(), SIGNAL(activated(int)), impl.get(), SLOT(onWriteEvent(int)));
104 impl->writePoll[fd] = WatchPair(std::move(notifier), std::move(cb));
105 }
106 }
107
removeWatch(int fd)108 void RunLoop::removeWatch(int fd) {
109 MBGL_VERIFY_THREAD(tid);
110
111 auto writePollIter = impl->writePoll.find(fd);
112 if (writePollIter != impl->writePoll.end()) {
113 impl->writePoll.erase(writePollIter);
114 }
115
116 auto readPollIter = impl->readPoll.find(fd);
117 if (readPollIter != impl->readPoll.end()) {
118 impl->readPoll.erase(readPollIter);
119 }
120 }
121
122 }
123 }
124