TaskFactory.h (2881B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_plugins_TaskFactory_h 8 #define mozilla_plugins_TaskFactory_h 9 10 #include <base/task.h> 11 12 #include <utility> 13 14 /* 15 * This is based on the ScopedRunnableMethodFactory from 16 * ipc/chromium/src/base/task.h Chromium's factories assert if tasks are created 17 * and run on different threads, which is something we need to do in 18 * PluginModuleParent (hang UI vs. main thread). TaskFactory just provides 19 * cancellable tasks that don't assert this. This version also allows both 20 * ScopedMethod and regular Tasks to be generated by the same Factory object. 21 */ 22 23 namespace mozilla { 24 namespace ipc { 25 26 template <class T> 27 class TaskFactory : public RevocableStore { 28 private: 29 template <class TaskType> 30 class TaskWrapper : public TaskType { 31 public: 32 template <typename... Args> 33 explicit TaskWrapper(RevocableStore* store, Args&&... args) 34 : TaskType(std::forward<Args>(args)...), revocable_(store) {} 35 36 NS_IMETHOD Run() override { 37 if (!revocable_.revoked()) TaskType::Run(); 38 return NS_OK; 39 } 40 41 private: 42 Revocable revocable_; 43 }; 44 45 public: 46 explicit TaskFactory(T* object) : object_(object) {} 47 48 template <typename TaskParamType, typename... Args> 49 inline already_AddRefed<TaskParamType> NewTask(Args&&... args) { 50 typedef TaskWrapper<TaskParamType> TaskWrapper; 51 RefPtr<TaskWrapper> task = 52 new TaskWrapper(this, std::forward<Args>(args)...); 53 return task.forget(); 54 } 55 56 template <class Method, typename... Args> 57 inline already_AddRefed<Runnable> NewRunnableMethod(Method method, 58 Args&&... args) { 59 typedef decltype(base::MakeTuple(std::forward<Args>(args)...)) ArgTuple; 60 typedef RunnableMethod<Method, ArgTuple> RunnableMethod; 61 typedef TaskWrapper<RunnableMethod> TaskWrapper; 62 63 RefPtr<TaskWrapper> task = new TaskWrapper( 64 this, object_, method, base::MakeTuple(std::forward<Args>(args)...)); 65 66 return task.forget(); 67 } 68 69 protected: 70 template <class Method, class Params> 71 class RunnableMethod : public Runnable { 72 public: 73 RunnableMethod(T* obj, Method meth, const Params& params) 74 : Runnable("ipc::TaskFactory::RunnableMethod"), 75 obj_(obj), 76 meth_(meth), 77 params_(params) {} 78 79 NS_IMETHOD Run() override { 80 DispatchToMethod(obj_, meth_, params_); 81 return NS_OK; 82 } 83 84 private: 85 T* obj_; 86 Method meth_; 87 Params params_; 88 }; 89 90 private: 91 T* object_; 92 }; 93 94 } // namespace ipc 95 } // namespace mozilla 96 97 #endif // mozilla_plugins_TaskFactory_h