Index: media/base/run_on_destruction.h |
diff --git a/media/base/run_on_destruction.h b/media/base/run_on_destruction.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..646a4dafeb114901b6352004ce14d5a69410fc80 |
--- /dev/null |
+++ b/media/base/run_on_destruction.h |
@@ -0,0 +1,92 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef MEDIA_BASE_RUN_ON_DESTRUCTION_H_ |
+#define MEDIA_BASE_RUN_ON_DESTRUCTION_H_ |
+ |
+#include <memory> |
+ |
+#include "base/callback_forward.h" |
+#include "base/bind.h" |
+#include "base/tuple.h" |
+#include "base/memory/ptr_util.h" |
+ |
+// This is a helper utility to wrap a base::Callback such that if the |
+// callback is destructed before it has a chance to run (e.g. the callback is |
+// bound into a task in a task runner and the task is dropped), it will be run |
+// with a set of parameters passed into RunOnDestruction. |
+// |
+// Typical usage: |
+// foo->DoWorkAndReturnResult( |
+// media::RunOnDestruction(base::Bind(&Foo::OnResult, this), false)); |
+// |
+// If the callback is destructed without running, it'll be called with "false". |
+ |
+// TODO(xhwang): This class really only makes sense for base::OnceCallback. |
+// However, mojo uses base::Callback in generated interfaces. |
+ |
+ |
+namespace media { |
+namespace internal { |
+ |
+template <typename CallbackType, typename Tuple, size_t... Ns> |
+inline void DispatchToCallbackImpl(CallbackType callback, |
+ Tuple&& args, |
+ base::IndexSequence<Ns...>) { |
+ std::move(callback).Run(base::get<Ns>(std::forward<Tuple>(args))...); |
+} |
+ |
+template <typename CallbackType, typename Tuple> |
+inline void DispatchToCallback(CallbackType callback, Tuple&& args) { |
+ DispatchToCallbackImpl(std::move(callback), std::forward<Tuple>(args), |
+ base::MakeIndexSequenceForTuple<Tuple>()); |
+} |
+ |
+// First, tell the compiler RunOnDestructionHelper 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 Signature> |
+class RunOnDestructionHelper; |
+ |
+template <typename... Args> |
+class RunOnDestructionHelper<void(Args...)> { |
+ public: |
+ using CallbackType = base::Callback<void(Args...)>; |
+ |
+ RunOnDestructionHelper(CallbackType callback, Args... args) |
+ : callback_(std::move(callback)), |
+ args_(std::make_tuple(args...)) { |
+ DCHECK(callback_); |
+ } |
+ |
+ inline void Run(Args... args); |
+ |
+ ~RunOnDestructionHelper() { |
+ if (callback_) |
+ DispatchToCallback(std::move(callback_), args_); |
+ } |
+ |
+ private: |
+ CallbackType callback_; |
+ std::tuple<Args...> args_; |
+}; |
+ |
+template <typename... Args> |
+inline void RunOnDestructionHelper<void(Args...)>::Run(Args... args) { |
+ std::move(callback_).Run(args...); |
+} |
+ |
+} // namespace internal |
+ |
+template <typename T, typename... Args> |
+inline base::Callback<T> RunOnDestruction(base::Callback<T> cb, Args... args) { |
+ return base::Bind( |
+ &internal::RunOnDestructionHelper<T>::Run, |
+ base::MakeUnique<internal::RunOnDestructionHelper<T>>( |
+ std::move(cb), args...)); |
+} |
+ |
+} // namespace media |
+ |
+#endif // MEDIA_BASE_RUN_ON_DESTRUCTION_H_ |