• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef MEDIA_BASE_CALLBACK_HOLDER_H_
6 #define MEDIA_BASE_CALLBACK_HOLDER_H_
7 
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/callback_helpers.h"
11 #include "media/base/bind_to_loop.h"
12 
13 namespace media {
14 
15 // A helper class that can hold a callback from being fired.
16 template <typename CB> class CallbackHolder {
17  public:
CallbackHolder()18   CallbackHolder() : hold_(false) {}
19 
~CallbackHolder()20   ~CallbackHolder() {
21     // Make sure all callbacks are satisfied!
22     DCHECK(!hold_);
23     DCHECK(original_cb_.is_null());
24     DCHECK(held_cb_.is_null());
25   }
26 
27   // Sets the callback to be potentially held.
SetCallback(const CB & cb)28   void SetCallback(const CB& cb) {
29     DCHECK(original_cb_.is_null());
30     DCHECK(held_cb_.is_null());
31     original_cb_ = cb;
32   }
33 
IsNull()34   bool IsNull() const {
35     return original_cb_.is_null() && held_cb_.is_null();
36   }
37 
38   // Holds the callback when Run() is called.
HoldCallback()39   void HoldCallback() { hold_ = true; }
40 
41   // Runs or holds the callback as specified by |hold_|.
42   // This method has overloaded versions to support different types of CB.
RunOrHold()43   void RunOrHold() {
44     DCHECK(held_cb_.is_null());
45     if (hold_)
46       held_cb_ = base::ResetAndReturn(&original_cb_);
47     else
48       base::ResetAndReturn(&original_cb_).Run();
49   }
50 
RunOrHold(A1 a1)51   template <typename A1> void RunOrHold(A1 a1) {
52     DCHECK(held_cb_.is_null());
53     if (hold_) {
54       held_cb_ = base::Bind(base::ResetAndReturn(&original_cb_),
55                             internal::TrampolineForward(a1));
56     } else {
57       base::ResetAndReturn(&original_cb_).Run(a1);
58     }
59   }
60 
RunOrHold(A1 a1,A2 a2)61   template <typename A1, typename A2> void RunOrHold(A1 a1, A2 a2) {
62     DCHECK(held_cb_.is_null());
63     if (hold_) {
64       held_cb_ = base::Bind(base::ResetAndReturn(&original_cb_),
65                             internal::TrampolineForward(a1),
66                             internal::TrampolineForward(a2));
67     } else {
68       base::ResetAndReturn(&original_cb_).Run(a1, a2);
69     }
70   }
71 
72   // Releases and runs the held callback.
RunHeldCallback()73   void RunHeldCallback() {
74     DCHECK(hold_);
75     DCHECK(!held_cb_.is_null());
76     hold_ = false;
77     base::ResetAndReturn(&held_cb_).Run();
78   }
79 
80  private:
81   bool hold_;
82   CB original_cb_;
83   base::Closure held_cb_;
84 };
85 
86 }  // namespace media
87 
88 #endif  // MEDIA_BASE_CALLBACK_HOLDER_H_
89