summaryrefslogtreecommitdiff
path: root/include/mbgl/util/uv.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/util/uv.hpp')
-rw-r--r--include/mbgl/util/uv.hpp141
1 files changed, 141 insertions, 0 deletions
diff --git a/include/mbgl/util/uv.hpp b/include/mbgl/util/uv.hpp
new file mode 100644
index 0000000000..f36da83e4d
--- /dev/null
+++ b/include/mbgl/util/uv.hpp
@@ -0,0 +1,141 @@
+#ifndef MBGL_UTIL_UV
+#define MBGL_UTIL_UV
+
+#include <uv.h>
+#include <functional>
+#include <cassert>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#endif
+
+#include <boost/lockfree/queue.hpp>
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+
+namespace uv {
+
+class loop {
+public:
+ inline loop() : l(uv_loop_new()) {}
+ inline ~loop() { uv_loop_delete(l); }
+
+ inline uv_loop_t *operator*() { return l; }
+
+private:
+ uv_loop_t *l;
+};
+
+class mutex {
+public:
+ inline mutex() {
+ if (uv_mutex_init(&mtx) != 0) {
+ throw std::runtime_error("failed to initialize mutex");
+ }
+ }
+ inline ~mutex() { uv_mutex_destroy(&mtx); }
+ inline void lock() { uv_mutex_lock(&mtx); }
+ inline void unlock() { uv_mutex_unlock(&mtx); }
+
+private:
+ uv_mutex_t mtx;
+};
+
+class lock {
+public:
+ lock(mutex &mtx) : mtx(mtx) { mtx.lock(); }
+ ~lock() { mtx.unlock(); }
+
+private:
+ mutex &mtx;
+};
+
+class rwlock {
+public:
+ inline rwlock() {
+ if (uv_rwlock_init(&mtx) != 0) {
+ throw std::runtime_error("failed to initialize read-write lock");
+ }
+ }
+ inline ~rwlock() { uv_rwlock_destroy(&mtx); }
+ inline void rdlock() { uv_rwlock_rdlock(&mtx); }
+ inline void wrlock() { uv_rwlock_wrlock(&mtx); }
+ inline void rdunlock() { uv_rwlock_rdunlock(&mtx); }
+ inline void wrunlock() { uv_rwlock_wrunlock(&mtx); }
+
+private:
+ uv_rwlock_t mtx;
+};
+
+class readlock {
+public:
+ inline readlock(rwlock &mtx) : mtx(mtx) { mtx.rdlock(); }
+ inline ~readlock() { mtx.rdunlock(); }
+
+private:
+ rwlock &mtx;
+};
+
+class writelock {
+public:
+ inline writelock(rwlock &mtx) : mtx(mtx) { mtx.wrlock(); }
+ inline ~writelock() { mtx.wrunlock(); }
+
+private:
+ rwlock &mtx;
+};
+
+class once {
+public:
+ typedef void (*callback)();
+ void operator()(void (*callback)(void)) {
+ uv_once(&o, callback);
+ }
+
+private:
+ uv_once_t o = UV_ONCE_INIT;
+};
+
+template <typename T>
+class work {
+public:
+ typedef void (*work_callback)(T &object);
+ typedef void (*after_work_callback)(T &object);
+
+ template<typename... Args>
+ work(const std::shared_ptr<loop> &loop, work_callback work_cb, after_work_callback after_work_cb, Args&&... args)
+ : loop(loop),
+ data(std::forward<Args>(args)...),
+ work_cb(work_cb),
+ after_work_cb(after_work_cb) {
+ req.data = this;
+ uv_queue_work(**loop, &req, do_work, after_work);
+ }
+
+private:
+ static void do_work(uv_work_t *req) {
+ work<T> *w = static_cast<work<T> *>(req->data);
+ w->work_cb(w->data);
+ }
+
+ static void after_work(uv_work_t *req, int) {
+ work<T> *w = static_cast<work<T> *>(req->data);
+ w->after_work_cb(w->data);
+ delete w;
+ }
+
+private:
+ std::shared_ptr<uv::loop> loop;
+ uv_work_t req;
+ T data;
+ work_callback work_cb;
+ after_work_callback after_work_cb;
+};
+
+}
+
+#endif