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