// Copyright 2013 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_CALLBACK_HOLDER_H_ #define MEDIA_BASE_CALLBACK_HOLDER_H_ #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" #include "media/base/bind_to_current_loop.h" namespace media { // A helper class that can hold a callback from being fired. template <typename CB> class CallbackHolder { public: CallbackHolder() : hold_(false) {} ~CallbackHolder() { // Make sure all callbacks are satisfied! DCHECK(!hold_); DCHECK(original_cb_.is_null()); DCHECK(held_cb_.is_null()); } // Sets the callback to be potentially held. void SetCallback(const CB& cb) { DCHECK(original_cb_.is_null()); DCHECK(held_cb_.is_null()); original_cb_ = cb; } bool IsNull() const { return original_cb_.is_null() && held_cb_.is_null(); } // Holds the callback when Run() is called. void HoldCallback() { hold_ = true; } // Runs or holds the callback as specified by |hold_|. // This method has overloaded versions to support different types of CB. void RunOrHold() { DCHECK(held_cb_.is_null()); if (hold_) held_cb_ = base::ResetAndReturn(&original_cb_); else base::ResetAndReturn(&original_cb_).Run(); } template <typename A1> void RunOrHold(A1 a1) { DCHECK(held_cb_.is_null()); if (hold_) { held_cb_ = base::Bind(base::ResetAndReturn(&original_cb_), internal::TrampolineForward(a1)); } else { base::ResetAndReturn(&original_cb_).Run(a1); } } template <typename A1, typename A2> void RunOrHold(A1 a1, A2 a2) { DCHECK(held_cb_.is_null()); if (hold_) { held_cb_ = base::Bind(base::ResetAndReturn(&original_cb_), internal::TrampolineForward(a1), internal::TrampolineForward(a2)); } else { base::ResetAndReturn(&original_cb_).Run(a1, a2); } } // Releases and runs the held callback. void RunHeldCallback() { DCHECK(hold_); DCHECK(!held_cb_.is_null()); hold_ = false; base::ResetAndReturn(&held_cb_).Run(); } private: bool hold_; CB original_cb_; base::Closure held_cb_; }; } // namespace media #endif // MEDIA_BASE_CALLBACK_HOLDER_H_