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

Side by Side Diff: mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc

Issue 2707483002: Mojo C++ bindings: change some std::unique_ptr<base::Lock> to base::Optional<base::Lock>. (Closed)
Patch Set: Created 3 years, 10 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 | « mojo/public/cpp/bindings/lib/multiplex_router.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" 5 #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/synchronization/lock.h" 9 #include "base/synchronization/lock.h"
11 #include "mojo/public/cpp/bindings/associated_group_controller.h" 10 #include "mojo/public/cpp/bindings/associated_group_controller.h"
12 #include "mojo/public/cpp/bindings/lib/may_auto_lock.h" 11 #include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
13 12
14 namespace mojo { 13 namespace mojo {
15 14
16 // ScopedInterfaceEndpointHandle::State ---------------------------------------- 15 // ScopedInterfaceEndpointHandle::State ----------------------------------------
17 16
18 // State could be called from multiple threads. 17 // State could be called from multiple threads.
19 class ScopedInterfaceEndpointHandle::State 18 class ScopedInterfaceEndpointHandle::State
20 : public base::RefCountedThreadSafe<State> { 19 : public base::RefCountedThreadSafe<State> {
21 public: 20 public:
22 State() = default; 21 State() = default;
23 22
24 State(InterfaceId id, 23 State(InterfaceId id,
25 scoped_refptr<AssociatedGroupController> group_controller) 24 scoped_refptr<AssociatedGroupController> group_controller)
26 : id_(id), group_controller_(group_controller) {} 25 : id_(id), group_controller_(group_controller) {}
27 26
28 void InitPendingState(scoped_refptr<State> peer) { 27 void InitPendingState(scoped_refptr<State> peer) {
29 DCHECK(!lock_); 28 DCHECK(!lock_);
30 DCHECK(!pending_association_); 29 DCHECK(!pending_association_);
31 30
32 lock_ = base::MakeUnique<base::Lock>(); 31 lock_.emplace();
33 pending_association_ = true; 32 pending_association_ = true;
34 peer_state_ = std::move(peer); 33 peer_state_ = std::move(peer);
35 } 34 }
36 35
37 void Close(const base::Optional<DisconnectReason>& reason) { 36 void Close(const base::Optional<DisconnectReason>& reason) {
38 scoped_refptr<AssociatedGroupController> cached_group_controller; 37 scoped_refptr<AssociatedGroupController> cached_group_controller;
39 InterfaceId cached_id = kInvalidInterfaceId; 38 InterfaceId cached_id = kInvalidInterfaceId;
40 scoped_refptr<State> cached_peer_state; 39 scoped_refptr<State> cached_peer_state;
41 40
42 { 41 {
43 internal::MayAutoLock locker(lock_.get()); 42 internal::MayAutoLock locker(&lock_);
44 43
45 if (!association_event_handler_.is_null()) { 44 if (!association_event_handler_.is_null()) {
46 association_event_handler_.Reset(); 45 association_event_handler_.Reset();
47 runner_ = nullptr; 46 runner_ = nullptr;
48 } 47 }
49 48
50 if (!pending_association_) { 49 if (!pending_association_) {
51 if (IsValidInterfaceId(id_)) { 50 if (IsValidInterfaceId(id_)) {
52 // Intentionally keep |group_controller_| unchanged. 51 // Intentionally keep |group_controller_| unchanged.
53 // That is because the callback created by 52 // That is because the callback created by
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 85 }
87 86
88 if (cached_group_controller) { 87 if (cached_group_controller) {
89 cached_group_controller->CloseEndpointHandle(cached_id, reason); 88 cached_group_controller->CloseEndpointHandle(cached_id, reason);
90 } else if (cached_peer_state) { 89 } else if (cached_peer_state) {
91 cached_peer_state->OnPeerClosedBeforeAssociation(reason); 90 cached_peer_state->OnPeerClosedBeforeAssociation(reason);
92 } 91 }
93 } 92 }
94 93
95 void SetAssociationEventHandler(AssociationEventCallback handler) { 94 void SetAssociationEventHandler(AssociationEventCallback handler) {
96 internal::MayAutoLock locker(lock_.get()); 95 internal::MayAutoLock locker(&lock_);
97 96
98 if (!pending_association_ && !IsValidInterfaceId(id_)) 97 if (!pending_association_ && !IsValidInterfaceId(id_))
99 return; 98 return;
100 99
101 association_event_handler_ = std::move(handler); 100 association_event_handler_ = std::move(handler);
102 if (association_event_handler_.is_null()) { 101 if (association_event_handler_.is_null()) {
103 runner_ = nullptr; 102 runner_ = nullptr;
104 return; 103 return;
105 } 104 }
106 105
(...skipping 11 matching lines...) Expand all
118 &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler, 117 &ScopedInterfaceEndpointHandle::State::RunAssociationEventHandler,
119 this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION)); 118 this, runner_, PEER_CLOSED_BEFORE_ASSOCIATION));
120 } 119 }
121 } 120 }
122 121
123 bool NotifyAssociation( 122 bool NotifyAssociation(
124 InterfaceId id, 123 InterfaceId id,
125 scoped_refptr<AssociatedGroupController> peer_group_controller) { 124 scoped_refptr<AssociatedGroupController> peer_group_controller) {
126 scoped_refptr<State> cached_peer_state; 125 scoped_refptr<State> cached_peer_state;
127 { 126 {
128 internal::MayAutoLock locker(lock_.get()); 127 internal::MayAutoLock locker(&lock_);
129 128
130 DCHECK(pending_association_); 129 DCHECK(pending_association_);
131 pending_association_ = false; 130 pending_association_ = false;
132 cached_peer_state = std::move(peer_state_); 131 cached_peer_state = std::move(peer_state_);
133 } 132 }
134 133
135 if (cached_peer_state) { 134 if (cached_peer_state) {
136 cached_peer_state->OnAssociated(id, std::move(peer_group_controller)); 135 cached_peer_state->OnAssociated(id, std::move(peer_group_controller));
137 return true; 136 return true;
138 } 137 }
139 return false; 138 return false;
140 } 139 }
141 140
142 bool is_valid() const { 141 bool is_valid() const {
143 internal::MayAutoLock locker(lock_.get()); 142 internal::MayAutoLock locker(&lock_);
144 return pending_association_ || IsValidInterfaceId(id_); 143 return pending_association_ || IsValidInterfaceId(id_);
145 } 144 }
146 145
147 bool pending_association() const { 146 bool pending_association() const {
148 internal::MayAutoLock locker(lock_.get()); 147 internal::MayAutoLock locker(&lock_);
149 return pending_association_; 148 return pending_association_;
150 } 149 }
151 150
152 InterfaceId id() const { 151 InterfaceId id() const {
153 internal::MayAutoLock locker(lock_.get()); 152 internal::MayAutoLock locker(&lock_);
154 return id_; 153 return id_;
155 } 154 }
156 155
157 AssociatedGroupController* group_controller() const { 156 AssociatedGroupController* group_controller() const {
158 internal::MayAutoLock locker(lock_.get()); 157 internal::MayAutoLock locker(&lock_);
159 return group_controller_.get(); 158 return group_controller_.get();
160 } 159 }
161 160
162 const base::Optional<DisconnectReason>& disconnect_reason() const { 161 const base::Optional<DisconnectReason>& disconnect_reason() const {
163 internal::MayAutoLock locker(lock_.get()); 162 internal::MayAutoLock locker(&lock_);
164 return disconnect_reason_; 163 return disconnect_reason_;
165 } 164 }
166 165
167 private: 166 private:
168 friend class base::RefCountedThreadSafe<State>; 167 friend class base::RefCountedThreadSafe<State>;
169 168
170 ~State() { 169 ~State() {
171 DCHECK(!pending_association_); 170 DCHECK(!pending_association_);
172 DCHECK(!IsValidInterfaceId(id_)); 171 DCHECK(!IsValidInterfaceId(id_));
173 } 172 }
174 173
175 // Called by the peer, maybe from a different thread. 174 // Called by the peer, maybe from a different thread.
176 void OnAssociated(InterfaceId id, 175 void OnAssociated(InterfaceId id,
177 scoped_refptr<AssociatedGroupController> group_controller) { 176 scoped_refptr<AssociatedGroupController> group_controller) {
178 AssociationEventCallback handler; 177 AssociationEventCallback handler;
179 { 178 {
180 internal::MayAutoLock locker(lock_.get()); 179 internal::MayAutoLock locker(&lock_);
181 180
182 // There may be race between Close() of endpoint A and 181 // There may be race between Close() of endpoint A and
183 // NotifyPeerAssociation() of endpoint A_peer on different threads. 182 // NotifyPeerAssociation() of endpoint A_peer on different threads.
184 // Therefore, it is possible that endpoint A has been closed but it 183 // Therefore, it is possible that endpoint A has been closed but it
185 // still gets OnAssociated() call from its peer. 184 // still gets OnAssociated() call from its peer.
186 if (!pending_association_) 185 if (!pending_association_)
187 return; 186 return;
188 187
189 pending_association_ = false; 188 pending_association_ = false;
190 peer_state_ = nullptr; 189 peer_state_ = nullptr;
(...skipping 15 matching lines...) Expand all
206 205
207 if (!handler.is_null()) 206 if (!handler.is_null())
208 std::move(handler).Run(ASSOCIATED); 207 std::move(handler).Run(ASSOCIATED);
209 } 208 }
210 209
211 // Called by the peer, maybe from a different thread. 210 // Called by the peer, maybe from a different thread.
212 void OnPeerClosedBeforeAssociation( 211 void OnPeerClosedBeforeAssociation(
213 const base::Optional<DisconnectReason>& reason) { 212 const base::Optional<DisconnectReason>& reason) {
214 AssociationEventCallback handler; 213 AssociationEventCallback handler;
215 { 214 {
216 internal::MayAutoLock locker(lock_.get()); 215 internal::MayAutoLock locker(&lock_);
217 216
218 // There may be race between Close()/NotifyPeerAssociation() of endpoint 217 // There may be race between Close()/NotifyPeerAssociation() of endpoint
219 // A and Close() of endpoint A_peer on different threads. 218 // A and Close() of endpoint A_peer on different threads.
220 // Therefore, it is possible that endpoint A is not in pending association 219 // Therefore, it is possible that endpoint A is not in pending association
221 // state but still gets OnPeerClosedBeforeAssociation() call from its 220 // state but still gets OnPeerClosedBeforeAssociation() call from its
222 // peer. 221 // peer.
223 if (!pending_association_) 222 if (!pending_association_)
224 return; 223 return;
225 224
226 disconnect_reason_ = reason; 225 disconnect_reason_ = reason;
(...skipping 17 matching lines...) Expand all
244 if (!handler.is_null()) 243 if (!handler.is_null())
245 std::move(handler).Run(PEER_CLOSED_BEFORE_ASSOCIATION); 244 std::move(handler).Run(PEER_CLOSED_BEFORE_ASSOCIATION);
246 } 245 }
247 246
248 void RunAssociationEventHandler( 247 void RunAssociationEventHandler(
249 scoped_refptr<base::SingleThreadTaskRunner> posted_to_runner, 248 scoped_refptr<base::SingleThreadTaskRunner> posted_to_runner,
250 AssociationEvent event) { 249 AssociationEvent event) {
251 AssociationEventCallback handler; 250 AssociationEventCallback handler;
252 251
253 { 252 {
254 internal::MayAutoLock locker(lock_.get()); 253 internal::MayAutoLock locker(&lock_);
255 if (posted_to_runner == runner_) { 254 if (posted_to_runner == runner_) {
256 runner_ = nullptr; 255 runner_ = nullptr;
257 handler = std::move(association_event_handler_); 256 handler = std::move(association_event_handler_);
258 } 257 }
259 } 258 }
260 259
261 if (!handler.is_null()) 260 if (!handler.is_null())
262 std::move(handler).Run(event); 261 std::move(handler).Run(event);
263 } 262 }
264 263
265 // Protects the following members if the handle is initially set to pending 264 // Protects the following members if the handle is initially set to pending
266 // association. 265 // association.
267 std::unique_ptr<base::Lock> lock_; 266 mutable base::Optional<base::Lock> lock_;
268 267
269 bool pending_association_ = false; 268 bool pending_association_ = false;
270 base::Optional<DisconnectReason> disconnect_reason_; 269 base::Optional<DisconnectReason> disconnect_reason_;
271 270
272 scoped_refptr<State> peer_state_; 271 scoped_refptr<State> peer_state_;
273 272
274 AssociationEventCallback association_event_handler_; 273 AssociationEventCallback association_event_handler_;
275 scoped_refptr<base::SingleThreadTaskRunner> runner_; 274 scoped_refptr<base::SingleThreadTaskRunner> runner_;
276 275
277 InterfaceId id_ = kInvalidInterfaceId; 276 InterfaceId id_ = kInvalidInterfaceId;
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 373
375 base::Callback<AssociatedGroupController*()> 374 base::Callback<AssociatedGroupController*()>
376 ScopedInterfaceEndpointHandle::CreateGroupControllerGetter() const { 375 ScopedInterfaceEndpointHandle::CreateGroupControllerGetter() const {
377 // We allow this callback to be run on any thread. If this handle is created 376 // We allow this callback to be run on any thread. If this handle is created
378 // in non-pending state, we don't have a lock but it should still be safe 377 // in non-pending state, we don't have a lock but it should still be safe
379 // because the group controller never changes. 378 // because the group controller never changes.
380 return base::Bind(&State::group_controller, state_); 379 return base::Bind(&State::group_controller, state_);
381 } 380 }
382 381
383 } // namespace mojo 382 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/lib/multiplex_router.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698