Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: media/base/bind_to_current_loop.h

Issue 2712603002: Destroy bound callback to BindToCurrentLoop on the target task runner (2) (Closed)
Patch Set: +inline Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | media/base/bind_to_current_loop_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/bind_to_current_loop.h
diff --git a/media/base/bind_to_current_loop.h b/media/base/bind_to_current_loop.h
index b4dbb2d3dbeb1ea4d2d7a04037bd592f630bdfde..b7c90f6d757ac3feee07d19366be6f81fb42bcd8 100644
--- a/media/base/bind_to_current_loop.h
+++ b/media/base/bind_to_current_loop.h
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/memory/scoped_vector.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -21,61 +21,73 @@
// Typical usage: request to be called back on the current thread:
// other->StartAsyncProcessAndCallMeBack(
// media::BindToCurrentLoop(base::Bind(&MyClass::MyMethod, this)));
-//
-// Note that like base::Bind(), BindToCurrentLoop() can't bind non-constant
-// references, and that *unlike* base::Bind(), BindToCurrentLoop() makes copies
-// of its arguments, and thus can't be used with arrays.
namespace media {
-
-// Mimic base::internal::CallbackForward, replacing std::move(p) with
-// base::Passed(&p) to account for the extra layer of indirection.
namespace internal {
-template <typename T>
-T& TrampolineForward(T& t) { return t; }
-
-template <typename T, typename R>
-base::internal::PassedWrapper<std::unique_ptr<T, R>> TrampolineForward(
- std::unique_ptr<T, R>& p) {
- return base::Passed(&p);
-}
-
-template <typename T>
-base::internal::PassedWrapper<ScopedVector<T> > TrampolineForward(
- ScopedVector<T>& p) { return base::Passed(&p); }
// First, tell the compiler TrampolineHelper is a struct template with one
// type parameter. Then define specializations where the type is a function
// returning void and taking zero or more arguments.
-template <typename Sig> struct TrampolineHelper;
+template <typename Signature>
+class TrampolineHelper;
-template <>
-struct TrampolineHelper<void()> {
- static void Run(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const base::Closure& cb) {
- task_runner->PostTask(FROM_HERE, cb);
+template <typename... Args>
+class TrampolineHelper<void(Args...)> {
+ public:
+ using CallbackType = base::Callback<void(Args...)>;
+
+ TrampolineHelper(const tracked_objects::Location& posted_from,
+ scoped_refptr<base::SequencedTaskRunner> task_runner,
+ CallbackType callback)
+ : posted_from_(posted_from),
+ task_runner_(std::move(task_runner)),
+ callback_(std::move(callback)) {
+ DCHECK(task_runner_);
+ DCHECK(callback_);
}
-};
-template <typename... Args>
-struct TrampolineHelper<void(Args...)> {
- static void Run(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- const base::Callback<void(Args...)>& cb,
- Args... args) {
- task_runner->PostTask(FROM_HERE,
- base::Bind(cb, TrampolineForward(args)...));
+ inline void Run(Args... args);
+
+ ~TrampolineHelper() {
+ task_runner_->PostTask(
+ posted_from_,
+ base::Bind(&TrampolineHelper::ClearCallbackOnTargetTaskRunner,
+ base::Passed(&callback_)));
}
+
+ private:
+ static void ClearCallbackOnTargetTaskRunner(CallbackType) {}
+ static void RunOnceClosure(base::OnceClosure cb) { std::move(cb).Run(); }
+
+ tracked_objects::Location posted_from_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ CallbackType callback_;
};
+template <>
+inline void TrampolineHelper<void()>::Run() {
+ task_runner_->PostTask(posted_from_, callback_);
+}
+
+template <typename... Args>
+inline void TrampolineHelper<void(Args...)>::Run(Args... args) {
+ // TODO(tzik): Use OnceCallback directly without RunOnceClosure, once
+ // TaskRunner::PostTask migrates to OnceClosure.
+ base::OnceClosure cb = base::BindOnce(callback_, std::forward<Args>(args)...);
+ task_runner_->PostTask(
+ posted_from_,
+ base::Bind(&TrampolineHelper::RunOnceClosure, base::Passed(&cb)));
+}
+
} // namespace internal
-template<typename T>
-static base::Callback<T> BindToCurrentLoop(
- const base::Callback<T>& cb) {
- return base::Bind(&internal::TrampolineHelper<T>::Run,
- base::ThreadTaskRunnerHandle::Get(), cb);
+template <typename T>
+inline base::Callback<T> BindToCurrentLoop(base::Callback<T> cb) {
+ return base::Bind(
+ &internal::TrampolineHelper<T>::Run,
+ base::MakeUnique<internal::TrampolineHelper<T>>(
+ FROM_HERE, // TODO(tzik): Propagate FROM_HERE from the caller.
+ base::ThreadTaskRunnerHandle::Get(), std::move(cb)));
}
} // namespace media
« no previous file with comments | « no previous file | media/base/bind_to_current_loop_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698