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

Side by Side Diff: base/callback_internal.h

Issue 2747673002: Use base::RefCountedThreadSafe on BindStateBase (Closed)
Patch Set: fix Created 3 years, 9 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 unified diff | Download patch
« no previous file with comments | « no previous file | base/callback_internal.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file contains utility functions and classes that help the 5 // This file contains utility functions and classes that help the
6 // implementation, and management of the Callback objects. 6 // implementation, and management of the Callback objects.
7 7
8 #ifndef BASE_CALLBACK_INTERNAL_H_ 8 #ifndef BASE_CALLBACK_INTERNAL_H_
9 #define BASE_CALLBACK_INTERNAL_H_ 9 #define BASE_CALLBACK_INTERNAL_H_
10 10
11 #include "base/atomic_ref_count.h"
12 #include "base/base_export.h" 11 #include "base/base_export.h"
13 #include "base/callback_forward.h" 12 #include "base/callback_forward.h"
14 #include "base/macros.h" 13 #include "base/macros.h"
15 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
16 15
17 namespace base { 16 namespace base {
17
18 struct FakeBindState;
19
18 namespace internal { 20 namespace internal {
21
19 template <CopyMode copy_mode> 22 template <CopyMode copy_mode>
20 class CallbackBase; 23 class CallbackBase;
21 24
25 class BindStateBase;
26
27 template <typename Functor, typename... BoundArgs>
28 struct BindState;
29
30 struct BindStateBaseRefCountTraits {
31 static void Destruct(const BindStateBase*);
32 };
33
22 // BindStateBase is used to provide an opaque handle that the Callback 34 // BindStateBase is used to provide an opaque handle that the Callback
23 // class can use to represent a function object with bound arguments. It 35 // class can use to represent a function object with bound arguments. It
24 // behaves as an existential type that is used by a corresponding 36 // behaves as an existential type that is used by a corresponding
25 // DoInvoke function to perform the function execution. This allows 37 // DoInvoke function to perform the function execution. This allows
26 // us to shield the Callback class from the types of the bound argument via 38 // us to shield the Callback class from the types of the bound argument via
27 // "type erasure." 39 // "type erasure."
28 // At the base level, the only task is to add reference counting data. Don't use 40 // At the base level, the only task is to add reference counting data. Don't use
29 // RefCountedThreadSafe since it requires the destructor to be a virtual method. 41 // RefCountedThreadSafe since it requires the destructor to be a virtual method.
30 // Creating a vtable for every BindState template instantiation results in a lot 42 // Creating a vtable for every BindState template instantiation results in a lot
31 // of bloat. Its only task is to call the destructor which can be done with a 43 // of bloat. Its only task is to call the destructor which can be done with a
32 // function pointer. 44 // function pointer.
33 class BASE_EXPORT BindStateBase { 45 class BASE_EXPORT BindStateBase
46 : public RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits> {
34 public: 47 public:
35 using InvokeFuncStorage = void(*)(); 48 using InvokeFuncStorage = void(*)();
36 49
37 protected: 50 private:
38 BindStateBase(InvokeFuncStorage polymorphic_invoke, 51 BindStateBase(InvokeFuncStorage polymorphic_invoke,
39 void (*destructor)(const BindStateBase*)); 52 void (*destructor)(const BindStateBase*));
40 BindStateBase(InvokeFuncStorage polymorphic_invoke, 53 BindStateBase(InvokeFuncStorage polymorphic_invoke,
41 void (*destructor)(const BindStateBase*), 54 void (*destructor)(const BindStateBase*),
42 bool (*is_cancelled)(const BindStateBase*)); 55 bool (*is_cancelled)(const BindStateBase*));
56
43 ~BindStateBase() = default; 57 ~BindStateBase() = default;
44 58
45 private: 59 friend struct BindStateBaseRefCountTraits;
46 friend class scoped_refptr<BindStateBase>; 60 friend class RefCountedThreadSafe<BindStateBase, BindStateBaseRefCountTraits>;
61
47 template <CopyMode copy_mode> 62 template <CopyMode copy_mode>
48 friend class CallbackBase; 63 friend class CallbackBase;
49 64
65 // Whitelist subclasses that access the destructor of BindStateBase.
dcheng 2017/03/22 00:26:17 Hmm, wouldn't it be easier just to keep the destru
tzik 2017/03/22 01:50:05 That hits our clang plugin check. It requires the
dcheng 2017/03/27 07:15:26 Hmm... so this seems pretty dangerous (though it's
tzik 2017/03/29 08:29:47 Do we have a pitfall where we may easily fall into
dcheng 2017/03/29 17:38:00 Right, this is the thing I'm concerned about. I do
tzik 2017/03/29 18:25:26 CallbackBase holds it as a scoped_refptr of BindSt
dcheng 2017/03/30 04:11:02 Ah... right. This is a bit subtle, but I guess it'
66 template <typename Functor, typename... BoundArgs>
67 friend struct BindState;
68 friend struct ::base::FakeBindState;
69
50 bool IsCancelled() const { 70 bool IsCancelled() const {
51 return is_cancelled_(this); 71 return is_cancelled_(this);
52 } 72 }
53 73
54 void AddRef() const;
55 void Release() const;
56
57 // In C++, it is safe to cast function pointers to function pointers of 74 // In C++, it is safe to cast function pointers to function pointers of
58 // another type. It is not okay to use void*. We create a InvokeFuncStorage 75 // another type. It is not okay to use void*. We create a InvokeFuncStorage
59 // that that can store our function pointer, and then cast it back to 76 // that that can store our function pointer, and then cast it back to
60 // the original type on usage. 77 // the original type on usage.
61 InvokeFuncStorage polymorphic_invoke_; 78 InvokeFuncStorage polymorphic_invoke_;
62 79
63 mutable AtomicRefCount ref_count_;
64
65 // Pointer to a function that will properly destroy |this|. 80 // Pointer to a function that will properly destroy |this|.
66 void (*destructor_)(const BindStateBase*); 81 void (*destructor_)(const BindStateBase*);
67 bool (*is_cancelled_)(const BindStateBase*); 82 bool (*is_cancelled_)(const BindStateBase*);
68 83
69 DISALLOW_COPY_AND_ASSIGN(BindStateBase); 84 DISALLOW_COPY_AND_ASSIGN(BindStateBase);
70 }; 85 };
71 86
72 // Holds the Callback methods that don't require specialization to reduce 87 // Holds the Callback methods that don't require specialization to reduce
73 // template bloat. 88 // template bloat.
74 // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and 89 // CallbackBase<MoveOnly> is a direct base class of MoveOnly callbacks, and
75 // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation. 90 // CallbackBase<Copyable> uses CallbackBase<MoveOnly> for its implementation.
76 template <> 91 template <>
77 class BASE_EXPORT CallbackBase<CopyMode::MoveOnly> { 92 class BASE_EXPORT CallbackBase<CopyMode::MoveOnly> {
78 public: 93 public:
79 CallbackBase(CallbackBase&& c); 94 CallbackBase(CallbackBase&& c);
80 CallbackBase& operator=(CallbackBase&& c); 95 CallbackBase& operator=(CallbackBase&& c);
81 96
82 explicit CallbackBase(const CallbackBase<CopyMode::Copyable>& c); 97 explicit CallbackBase(const CallbackBase<CopyMode::Copyable>& c);
83 CallbackBase& operator=(const CallbackBase<CopyMode::Copyable>& c); 98 CallbackBase& operator=(const CallbackBase<CopyMode::Copyable>& c);
84 99
85 explicit CallbackBase(CallbackBase<CopyMode::Copyable>&& c); 100 explicit CallbackBase(CallbackBase<CopyMode::Copyable>&& c);
86 CallbackBase& operator=(CallbackBase<CopyMode::Copyable>&& c); 101 CallbackBase& operator=(CallbackBase<CopyMode::Copyable>&& c);
87 102
88 // Returns true if Callback is null (doesn't refer to anything). 103 // Returns true if Callback is null (doesn't refer to anything).
89 bool is_null() const { return bind_state_.get() == NULL; } 104 bool is_null() const { return !bind_state_; }
90 explicit operator bool() const { return !is_null(); } 105 explicit operator bool() const { return !is_null(); }
91 106
92 // Returns true if the callback invocation will be nop due to an cancellation. 107 // Returns true if the callback invocation will be nop due to an cancellation.
93 // It's invalid to call this on uninitialized callback. 108 // It's invalid to call this on uninitialized callback.
94 bool IsCancelled() const; 109 bool IsCancelled() const;
95 110
96 // Returns the Callback into an uninitialized state. 111 // Returns the Callback into an uninitialized state.
97 void Reset(); 112 void Reset();
98 113
99 protected: 114 protected:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 ~CallbackBase() {} 148 ~CallbackBase() {}
134 }; 149 };
135 150
136 extern template class CallbackBase<CopyMode::MoveOnly>; 151 extern template class CallbackBase<CopyMode::MoveOnly>;
137 extern template class CallbackBase<CopyMode::Copyable>; 152 extern template class CallbackBase<CopyMode::Copyable>;
138 153
139 } // namespace internal 154 } // namespace internal
140 } // namespace base 155 } // namespace base
141 156
142 #endif // BASE_CALLBACK_INTERNAL_H_ 157 #endif // BASE_CALLBACK_INTERNAL_H_
OLDNEW
« no previous file with comments | « no previous file | base/callback_internal.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698