OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 BLIMP_COMMON_MANDATORY_CALLBACK_H_ | |
6 #define BLIMP_COMMON_MANDATORY_CALLBACK_H_ | |
7 | |
8 #include <utility> | |
9 | |
10 #include "base/callback.h" | |
11 #include "base/logging.h" | |
12 | |
13 namespace blimp { | |
14 | |
15 // Adds a leak-detection wrapper to base::Callback objects. | |
16 // | |
17 // When a wrapped Callback is destroyed without being Run first, the checker | |
18 // will DCHECK-crash the program with a stack trace, so that developers can | |
19 // pinpoint the site of the leak. | |
20 // | |
21 // The MandatoryCallback may be passed using std::move; leak detection occurs | |
22 // when the MandatoryCallback is finally destroyed. | |
23 // | |
24 // Usage: | |
25 // void DoStuff(int d) { ... } | |
26 // ... | |
27 // base::Closure my_callback = base::Bind(&DoStuff); | |
28 // MandatoryCallback<void(int)> leak_checked_callback = | |
29 // CreateMandatoryCallback(my_callback); | |
30 // | |
31 // Note that MandatoryCallbacks lack some functionality from | |
32 // base::CallbackInternal. | |
33 // * They can only be invoked once. | |
34 // * They do not support parameter currying with additional Bind() calls.[1] | |
35 // * They cannot be Reset(). | |
36 // | |
37 // [1] Mandatory invocation support would need to be plumbed in to | |
38 // base::CallbackInternal and base::Bind for this to work, | |
39 // which is feasible but low-priority for the owners of the callback | |
40 // libraries. | |
41 | |
42 template <typename SignatureType> | |
43 class MandatoryCallback; | |
44 | |
45 // Template specialization for extracting the function signature data types. | |
46 template <typename ReturnType, typename... ArgTypes> | |
47 class MandatoryCallback<ReturnType(ArgTypes...)> { | |
48 public: | |
49 using CallbackType = base::Callback<ReturnType(ArgTypes...)>; | |
50 | |
51 explicit MandatoryCallback(const CallbackType& callback) : cb_(callback) { | |
52 DCHECK(!cb_.is_null()); | |
53 } | |
54 | |
55 MandatoryCallback(MandatoryCallback&& other) { | |
56 cb_ = other.cb_; | |
57 other.cb_.Reset(); | |
58 | |
59 #if DCHECK_IS_ON() | |
60 was_run_ = other.was_run_; | |
61 other.was_run_ = false; | |
62 #endif | |
63 } | |
64 | |
65 ~MandatoryCallback() { | |
66 #if DCHECK_IS_ON() | |
67 DCHECK(cb_.is_null() || was_run_); | |
68 #endif | |
69 } | |
70 | |
71 // This a overload that handles the case where there are no arguments provided | |
72 template <typename...> | |
73 ReturnType Run() { | |
74 DCHECK(cb_); // Can't be run following std::move. | |
75 | |
76 #if DCHECK_IS_ON() | |
77 DCHECK(!was_run_); | |
78 was_run_ = true; | |
79 #endif | |
80 | |
81 cb_.Run(); | |
82 } | |
83 | |
84 template <typename... RunArgs> | |
85 ReturnType Run(RunArgs... args) { | |
86 DCHECK(cb_); // Can't be run following std::move. | |
87 | |
88 #if DCHECK_IS_ON() | |
89 DCHECK(!was_run_); | |
90 was_run_ = true; | |
91 #endif | |
92 | |
93 cb_.Run(std::forward<RunArgs...>(args...)); | |
94 } | |
95 | |
96 private: | |
97 // Nulled after being moved. | |
98 CallbackType cb_; | |
99 | |
100 #if DCHECK_IS_ON() | |
101 bool was_run_ = false; | |
102 #endif | |
103 | |
104 DISALLOW_COPY_AND_ASSIGN(MandatoryCallback); | |
105 }; | |
106 | |
107 // Creates a leak-checking proxy callback around |callback|. | |
108 template <typename SignatureType> | |
109 MandatoryCallback<SignatureType> CreateMandatoryCallback( | |
110 const base::Callback<SignatureType>& callback) { | |
111 return MandatoryCallback<SignatureType>(callback); | |
112 } | |
113 | |
114 using MandatoryClosure = MandatoryCallback<void()>; | |
115 | |
116 } // namespace blimp | |
117 | |
118 #endif // BLIMP_COMMON_MANDATORY_CALLBACK_H_ | |
OLD | NEW |