summaryrefslogtreecommitdiff
path: root/include/mbgl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-09-02 16:52:25 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-09-08 16:36:47 -0700
commite4995e8d3a38dfd2ed64337e712ecf701af37454 (patch)
tree234490c1f4e93afb99738d6790be46ea1fe9c1c8 /include/mbgl
parenta85f7540c7f4ac289abba1dc3aa71058bc820b05 (diff)
downloadqtlocation-mapboxgl-e4995e8d3a38dfd2ed64337e712ecf701af37454.tar.gz
[core] Extract WorkTaskImpl from run_loop.hpp
Diffstat (limited to 'include/mbgl')
-rw-r--r--include/mbgl/util/run_loop.hpp88
-rw-r--r--include/mbgl/util/work_task.hpp8
-rw-r--r--include/mbgl/util/work_task_impl.hpp92
3 files changed, 105 insertions, 83 deletions
diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp
index 25f07c0312..af1053dfdc 100644
--- a/include/mbgl/util/run_loop.hpp
+++ b/include/mbgl/util/run_loop.hpp
@@ -47,11 +47,7 @@ public:
// Invoke fn(args...) on this RunLoop.
template <class Fn, class... Args>
void invoke(Fn&& fn, Args&&... args) {
- auto tuple = std::make_tuple(std::move(args)...);
- auto task = std::make_shared<Invoker<Fn, decltype(tuple)>>(
- std::move(fn),
- std::move(tuple));
-
+ std::shared_ptr<WorkTask> task = WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...);
push(task);
}
@@ -59,17 +55,8 @@ public:
template <class Fn, class... Args>
std::unique_ptr<AsyncRequest>
invokeCancellable(Fn&& fn, Args&&... args) {
- auto flag = std::make_shared<std::atomic<bool>>();
- *flag = false;
-
- auto tuple = std::make_tuple(std::move(args)...);
- auto task = std::make_shared<Invoker<Fn, decltype(tuple)>>(
- std::move(fn),
- std::move(tuple),
- flag);
-
+ std::shared_ptr<WorkTask> task = WorkTask::make(std::forward<Fn>(fn), std::forward<Args>(args)...);
push(task);
-
return std::make_unique<WorkRequest>(task);
}
@@ -77,32 +64,8 @@ public:
template <class Fn, class Cb, class... Args>
std::unique_ptr<AsyncRequest>
invokeWithCallback(Fn&& fn, Cb&& callback, Args&&... args) {
- auto flag = std::make_shared<std::atomic<bool>>();
- *flag = false;
-
- // Create a lambda L1 that invokes another lambda L2 on the current RunLoop R, that calls
- // the callback C. Both lambdas check the flag before proceeding. L1 needs to check the flag
- // because if the request was cancelled, then R might have been destroyed. L2 needs to check
- // the flag because the request may have been cancelled after L2 was invoked but before it
- // began executing.
- auto after = [flag, current = RunLoop::Get(), callback1 = std::move(callback)] (auto&&... results1) {
- if (!*flag) {
- current->invoke([flag, callback2 = std::move(callback1)] (auto&&... results2) {
- if (!*flag) {
- callback2(std::move(results2)...);
- }
- }, std::move(results1)...);
- }
- };
-
- auto tuple = std::make_tuple(std::move(args)..., after);
- auto task = std::make_shared<Invoker<Fn, decltype(tuple)>>(
- std::move(fn),
- std::move(tuple),
- flag);
-
+ std::shared_ptr<WorkTask> task = WorkTask::makeWithCallback(std::forward<Fn>(fn), std::forward<Cb>(callback), std::forward<Args>(args)...);
push(task);
-
return std::make_unique<WorkRequest>(task);
}
@@ -111,49 +74,6 @@ public:
private:
MBGL_STORE_THREAD(tid)
- template <class F, class P>
- class Invoker : public WorkTask {
- public:
- Invoker(F&& f, P&& p, std::shared_ptr<std::atomic<bool>> canceled_ = nullptr)
- : canceled(std::move(canceled_)),
- func(std::move(f)),
- params(std::move(p)) {
- }
-
- void operator()() override {
- // Lock the mutex while processing so that cancel() will block.
- std::lock_guard<std::recursive_mutex> lock(mutex);
- if (!canceled || !*canceled) {
- invoke(std::make_index_sequence<std::tuple_size<P>::value>{});
- }
- }
-
- // If the task has not yet begun, this will cancel it.
- // If the task is in progress, this will block until it completed. (Currently
- // necessary because of shared state, but should be removed.) It will also
- // cancel the after callback.
- // If the task has completed, but the after callback has not executed, this
- // will cancel the after callback.
- // If the task has completed and the after callback has executed, this will
- // do nothing.
- void cancel() override {
- std::lock_guard<std::recursive_mutex> lock(mutex);
- *canceled = true;
- }
-
- private:
- template <std::size_t... I>
- void invoke(std::index_sequence<I...>) {
- func(std::move(std::get<I>(std::forward<P>(params)))...);
- }
-
- std::recursive_mutex mutex;
- std::shared_ptr<std::atomic<bool>> canceled;
-
- F func;
- P params;
- };
-
using Queue = std::queue<std::shared_ptr<WorkTask>>;
void push(std::shared_ptr<WorkTask>);
@@ -181,3 +101,5 @@ private:
} // namespace util
} // namespace mbgl
+
+#include <mbgl/util/work_task_impl.hpp>
diff --git a/include/mbgl/util/work_task.hpp b/include/mbgl/util/work_task.hpp
index 43f4810b43..e9c2062d9c 100644
--- a/include/mbgl/util/work_task.hpp
+++ b/include/mbgl/util/work_task.hpp
@@ -2,6 +2,8 @@
#include <mbgl/util/noncopyable.hpp>
+#include <memory>
+
namespace mbgl {
// A movable type-erasing function wrapper. This allows to store arbitrary invokable
@@ -13,6 +15,12 @@ public:
virtual void operator()() = 0;
virtual void cancel() = 0;
+
+ template <class Fn, class... Args>
+ static std::shared_ptr<WorkTask> make(Fn&& fn, Args&&... args);
+
+ template <class Fn, class Cb, class... Args>
+ static std::shared_ptr<WorkTask> makeWithCallback(Fn&& fn, Cb&& callback, Args&&... args);
};
} // namespace mbgl
diff --git a/include/mbgl/util/work_task_impl.hpp b/include/mbgl/util/work_task_impl.hpp
new file mode 100644
index 0000000000..2c016601bb
--- /dev/null
+++ b/include/mbgl/util/work_task_impl.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <mbgl/util/work_task.hpp>
+#include <mbgl/util/run_loop.hpp>
+
+#include <mutex>
+
+namespace mbgl {
+
+template <class F, class P>
+class WorkTaskImpl : public WorkTask {
+public:
+ WorkTaskImpl(F&& f, P&& p, std::shared_ptr<std::atomic<bool>> canceled_)
+ : canceled(std::move(canceled_)),
+ func(std::move(f)),
+ params(std::move(p)) {
+ }
+
+ void operator()() override {
+ // Lock the mutex while processing so that cancel() will block.
+ std::lock_guard<std::recursive_mutex> lock(mutex);
+ if (!*canceled) {
+ invoke(std::make_index_sequence<std::tuple_size<P>::value>{});
+ }
+ }
+
+ // If the task has not yet begun, this will cancel it.
+ // If the task is in progress, this will block until it completed. (Currently
+ // necessary because of shared state, but should be removed.) It will also
+ // cancel the after callback.
+ // If the task has completed, but the after callback has not executed, this
+ // will cancel the after callback.
+ // If the task has completed and the after callback has executed, this will
+ // do nothing.
+ void cancel() override {
+ std::lock_guard<std::recursive_mutex> lock(mutex);
+ *canceled = true;
+ }
+
+private:
+ template <std::size_t... I>
+ void invoke(std::index_sequence<I...>) {
+ func(std::move(std::get<I>(std::forward<P>(params)))...);
+ }
+
+ std::recursive_mutex mutex;
+ std::shared_ptr<std::atomic<bool>> canceled;
+
+ F func;
+ P params;
+};
+
+template <class Fn, class... Args>
+std::shared_ptr<WorkTask> WorkTask::make(Fn&& fn, Args&&... args) {
+ auto flag = std::make_shared<std::atomic<bool>>();
+ *flag = false;
+
+ auto tuple = std::make_tuple(std::move(args)...);
+ return std::make_shared<WorkTaskImpl<Fn, decltype(tuple)>>(
+ std::move(fn),
+ std::move(tuple),
+ flag);
+}
+
+template <class Fn, class Cb, class... Args>
+std::shared_ptr<WorkTask> WorkTask::makeWithCallback(Fn&& fn, Cb&& callback, Args&&... args) {
+ auto flag = std::make_shared<std::atomic<bool>>();
+ *flag = false;
+
+ // Create a lambda L1 that invokes another lambda L2 on the current RunLoop R, that calls
+ // the callback C. Both lambdas check the flag before proceeding. L1 needs to check the flag
+ // because if the request was cancelled, then R might have been destroyed. L2 needs to check
+ // the flag because the request may have been cancelled after L2 was invoked but before it
+ // began executing.
+ auto after = [flag, current = util::RunLoop::Get(), callback1 = std::move(callback)] (auto&&... results1) {
+ if (!*flag) {
+ current->invoke([flag, callback2 = std::move(callback1)] (auto&&... results2) {
+ if (!*flag) {
+ callback2(std::move(results2)...);
+ }
+ }, std::move(results1)...);
+ }
+ };
+
+ auto tuple = std::make_tuple(std::move(args)..., after);
+ return std::make_shared<WorkTaskImpl<Fn, decltype(tuple)>>(
+ std::move(fn),
+ std::move(tuple),
+ flag);
+}
+
+} // namespace mbgl