summaryrefslogtreecommitdiff
path: root/include/mbgl/util
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/util')
-rw-r--r--include/mbgl/util/run_loop.hpp52
-rw-r--r--include/mbgl/util/thread.hpp52
2 files changed, 104 insertions, 0 deletions
diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp
new file mode 100644
index 0000000000..f0318d2026
--- /dev/null
+++ b/include/mbgl/util/run_loop.hpp
@@ -0,0 +1,52 @@
+#ifndef MBGL_UTIL_RUN_LOOP
+#define MBGL_UTIL_RUN_LOOP
+
+#include <mutex>
+#include <functional>
+#include <queue>
+
+namespace uv {
+class async;
+class loop;
+}
+
+namespace mbgl {
+namespace util {
+
+template <typename T> class Thread;
+
+class RunLoop {
+ friend Thread<RunLoop>;
+
+protected:
+ // These are called by the Thread<> wrapper.
+ RunLoop();
+ ~RunLoop();
+
+ // Called by the Thread<> wrapper to start the loop. When you implement this
+ // method in a child class, you *must* call this function as the last action.
+ void start();
+
+protected:
+ // Called by the Thread<> wrapper to terminate this loop.
+ void stop();
+
+private:
+ // Invokes function in the run loop.
+ void process();
+
+public:
+ // Schedules a function to be executed as part of this run loop.
+ void invoke(std::function<void()> fn);
+
+private:
+ const std::unique_ptr<uv::loop> runloop;
+ const std::unique_ptr<uv::async> runloopAsync;
+ std::mutex runloopMutex;
+ std::queue<std::function<void()>> runloopQueue;
+};
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp
new file mode 100644
index 0000000000..943039c5d6
--- /dev/null
+++ b/include/mbgl/util/thread.hpp
@@ -0,0 +1,52 @@
+#ifndef MBGL_UTIL_THREAD
+#define MBGL_UTIL_THREAD
+
+#include <future>
+#include <thread>
+
+namespace mbgl {
+namespace util {
+
+template <class Object>
+class Thread {
+public:
+ template <class... Args>
+ Thread(Args&&... args);
+ Thread(const Thread&) = delete;
+ Thread(Thread&&) = delete;
+ Thread& operator=(const Thread&) = delete;
+ Thread& operator=(Thread&&) = delete;
+ ~Thread();
+
+ inline Object* operator->() const { return &object; }
+ inline operator Object*() const { return &object; }
+
+private:
+ std::thread thread;
+ Object& object;
+};
+
+template <class Object>
+template <class... Args>
+Thread<Object>::Thread(Args&&... args)
+ : object([&]() -> Object& {
+ std::promise<Object&> promise;
+ thread = std::thread([&] {
+ Object context(::std::forward<Args>(args)...);
+ promise.set_value(context);
+ context.start();
+ });
+ return promise.get_future().get();
+ }()) {
+}
+
+template <class Object>
+Thread<Object>::~Thread() {
+ object.stop();
+ thread.join();
+}
+
+}
+}
+
+#endif