#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace util { using LOOP_HANDLE = void *; class RunLoop : public Scheduler, private util::noncopyable { public: enum class Type : uint8_t { Default, New, }; enum class Event : uint8_t { None = 0, Read = 1, Write = 2, ReadWrite = Read | Write, }; RunLoop(Type type = Type::Default); ~RunLoop() override; static RunLoop* Get(); static LOOP_HANDLE getLoopHandle(); void run(); void runOnce(); void stop(); // So far only needed by the libcurl backend. void addWatch(int fd, Event, std::function&& callback); void removeWatch(int fd); // Invoke fn(args...) on this RunLoop. template void invoke(Fn&& fn, Args&&... args) { std::shared_ptr task = WorkTask::make(std::forward(fn), std::forward(args)...); push(task); } // Post the cancellable work fn(args...) to this RunLoop. template std::unique_ptr invokeCancellable(Fn&& fn, Args&&... args) { std::shared_ptr task = WorkTask::make(std::forward(fn), std::forward(args)...); push(task); return std::make_unique(task); } void schedule(std::weak_ptr mailbox) override { invoke([mailbox] () { Mailbox::maybeReceive(mailbox); }); } class Impl; private: MBGL_STORE_THREAD(tid) using Queue = std::queue>; void push(std::shared_ptr); void withMutex(std::function&& fn) { std::lock_guard lock(mutex); fn(); } void process() { Queue queue_; withMutex([&] { queue_.swap(queue); }); while (!queue_.empty()) { (*(queue_.front()))(); queue_.pop(); } } Queue queue; std::mutex mutex; std::unique_ptr impl; }; } // namespace util } // namespace mbgl #include