Platform integration callback for platforms that do not have full run loop integration or don't want to block at the Mapbox GL Native loop. It will be called from any thread and is up to the platform to, after receiving the callback, call RunLoop::runOnce() from the same thread as the Map object lives.
144 lines
4.1 KiB
C++
144 lines
4.1 KiB
C++
#pragma once
|
|
|
|
#include <mbgl/actor/scheduler.hpp>
|
|
#include <mbgl/actor/mailbox.hpp>
|
|
#include <mbgl/util/noncopyable.hpp>
|
|
#include <mbgl/util/util.hpp>
|
|
#include <mbgl/util/work_task.hpp>
|
|
#include <mbgl/util/work_request.hpp>
|
|
|
|
#include <atomic>
|
|
#include <functional>
|
|
#include <utility>
|
|
#include <queue>
|
|
#include <mutex>
|
|
|
|
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 Priority : bool {
|
|
Default = false,
|
|
High = true,
|
|
};
|
|
|
|
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();
|
|
|
|
using PlatformCallback = std::function<void()>;
|
|
|
|
// Platform integration callback for platforms that do not have full
|
|
// run loop integration or don't want to block at the Mapbox GL Native
|
|
// loop. It will be called from any thread and is up to the platform
|
|
// to, after receiving the callback, call RunLoop::runOnce() from the
|
|
// same thread as the Map object lives.
|
|
void setPlatformCallback(PlatformCallback&& callback) { platformCallback = std::move(callback); }
|
|
|
|
// So far only needed by the libcurl backend.
|
|
void addWatch(int fd, Event, std::function<void(int, Event)>&& callback);
|
|
void removeWatch(int fd);
|
|
|
|
// Invoke fn(args...) on this RunLoop.
|
|
template <class Fn, class... Args>
|
|
void invoke(Priority priority, Fn&& fn, Args&&... args) {
|
|
push(priority, WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...));
|
|
}
|
|
|
|
// Invoke fn(args...) on this RunLoop.
|
|
template <class Fn, class... Args>
|
|
void invoke(Fn&& fn, Args&&... args) {
|
|
invoke(Priority::Default, std::forward<Fn>(fn), std::forward<Args>(args)...);
|
|
}
|
|
|
|
// Post the cancellable work fn(args...) to this RunLoop.
|
|
template <class Fn, class... Args>
|
|
std::unique_ptr<AsyncRequest>
|
|
invokeCancellable(Fn&& fn, Args&&... args) {
|
|
std::shared_ptr<WorkTask> task = WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...);
|
|
push(Priority::Default, task);
|
|
return std::make_unique<WorkRequest>(task);
|
|
}
|
|
|
|
void schedule(std::function<void()> fn) override { invoke(std::move(fn)); }
|
|
::mapbox::base::WeakPtr<Scheduler> makeWeakPtr() override { return weakFactory.makeWeakPtr(); }
|
|
|
|
class Impl;
|
|
|
|
private:
|
|
MBGL_STORE_THREAD(tid)
|
|
|
|
using Queue = std::queue<std::shared_ptr<WorkTask>>;
|
|
|
|
// Wakes up the RunLoop so that it starts processing items in the queue.
|
|
void wake();
|
|
|
|
// Adds a WorkTask to the queue, and wakes it up.
|
|
void push(Priority priority, std::shared_ptr<WorkTask> task) {
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
if (priority == Priority::High) {
|
|
highPriorityQueue.emplace(std::move(task));
|
|
} else {
|
|
defaultQueue.emplace(std::move(task));
|
|
}
|
|
wake();
|
|
platformCallback();
|
|
}
|
|
|
|
void process() {
|
|
std::shared_ptr<WorkTask> task;
|
|
std::unique_lock<std::mutex> lock(mutex);
|
|
while (true) {
|
|
if (!highPriorityQueue.empty()) {
|
|
task = std::move(highPriorityQueue.front());
|
|
highPriorityQueue.pop();
|
|
} else if (!defaultQueue.empty()) {
|
|
task = std::move(defaultQueue.front());
|
|
defaultQueue.pop();
|
|
} else {
|
|
break;
|
|
}
|
|
lock.unlock();
|
|
(*task)();
|
|
task.reset();
|
|
lock.lock();
|
|
}
|
|
}
|
|
|
|
PlatformCallback platformCallback = [] {};
|
|
|
|
Queue defaultQueue;
|
|
Queue highPriorityQueue;
|
|
std::mutex mutex;
|
|
|
|
std::unique_ptr<Impl> impl;
|
|
::mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
|
|
};
|
|
|
|
} // namespace util
|
|
} // namespace mbgl
|
|
|
|
#include <mbgl/util/work_task_impl.hpp>
|