OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/lib/connector.h" | 5 #include "mojo/public/cpp/bindings/lib/connector.h" |
6 | 6 |
| 7 #include "base/macros.h" |
| 8 #include "base/synchronization/lock.h" |
7 #include "mojo/public/cpp/environment/logging.h" | 9 #include "mojo/public/cpp/environment/logging.h" |
8 | 10 |
9 namespace mojo { | 11 namespace mojo { |
10 namespace internal { | 12 namespace internal { |
11 | 13 |
| 14 namespace { |
| 15 |
| 16 // Similar to base::AutoLock, except that it does nothing if |lock| passed into |
| 17 // the constructor is null. |
| 18 class MayAutoLock { |
| 19 public: |
| 20 explicit MayAutoLock(base::Lock* lock) : lock_(lock) { |
| 21 if (lock_) |
| 22 lock_->Acquire(); |
| 23 } |
| 24 |
| 25 ~MayAutoLock() { |
| 26 if (lock_) { |
| 27 lock_->AssertAcquired(); |
| 28 lock_->Release(); |
| 29 } |
| 30 } |
| 31 |
| 32 private: |
| 33 base::Lock* lock_; |
| 34 DISALLOW_COPY_AND_ASSIGN(MayAutoLock); |
| 35 }; |
| 36 |
| 37 } // namespace |
| 38 |
12 // ---------------------------------------------------------------------------- | 39 // ---------------------------------------------------------------------------- |
13 | 40 |
14 Connector::Connector(ScopedMessagePipeHandle message_pipe, | 41 Connector::Connector(ScopedMessagePipeHandle message_pipe, |
| 42 SendingThreadSaftyType sending_thread_safty_type, |
15 const MojoAsyncWaiter* waiter) | 43 const MojoAsyncWaiter* waiter) |
16 : waiter_(waiter), | 44 : waiter_(waiter), |
17 message_pipe_(message_pipe.Pass()), | 45 message_pipe_(message_pipe.Pass()), |
18 incoming_receiver_(nullptr), | 46 incoming_receiver_(nullptr), |
19 async_wait_id_(0), | 47 async_wait_id_(0), |
20 error_(false), | 48 error_(false), |
21 drop_writes_(false), | 49 drop_writes_(false), |
22 enforce_errors_from_incoming_receiver_(true), | 50 enforce_errors_from_incoming_receiver_(true), |
23 paused_(false), | 51 paused_(false), |
24 destroyed_flag_(nullptr) { | 52 destroyed_flag_(nullptr), |
| 53 lock_(sending_thread_safty_type == MULTI_THREADED_SEND ? new base::Lock |
| 54 : nullptr) { |
25 // Even though we don't have an incoming receiver, we still want to monitor | 55 // Even though we don't have an incoming receiver, we still want to monitor |
26 // the message pipe to know if is closed or encounters an error. | 56 // the message pipe to know if is closed or encounters an error. |
27 WaitToReadMore(); | 57 WaitToReadMore(); |
28 } | 58 } |
29 | 59 |
30 Connector::~Connector() { | 60 Connector::~Connector() { |
31 if (destroyed_flag_) | 61 if (destroyed_flag_) |
32 *destroyed_flag_ = true; | 62 *destroyed_flag_ = true; |
33 | 63 |
34 CancelWait(); | 64 CancelWait(); |
35 } | 65 } |
36 | 66 |
37 void Connector::CloseMessagePipe() { | 67 void Connector::CloseMessagePipe() { |
38 CancelWait(); | 68 CancelWait(); |
| 69 MayAutoLock locker(lock_.get()); |
39 Close(message_pipe_.Pass()); | 70 Close(message_pipe_.Pass()); |
40 } | 71 } |
41 | 72 |
42 ScopedMessagePipeHandle Connector::PassMessagePipe() { | 73 ScopedMessagePipeHandle Connector::PassMessagePipe() { |
43 CancelWait(); | 74 CancelWait(); |
| 75 MayAutoLock locker(lock_.get()); |
44 return message_pipe_.Pass(); | 76 return message_pipe_.Pass(); |
45 } | 77 } |
46 | 78 |
47 void Connector::RaiseError() { | 79 void Connector::RaiseError() { |
48 HandleError(true, true); | 80 HandleError(true, true); |
49 } | 81 } |
50 | 82 |
51 bool Connector::WaitForIncomingMessage(MojoDeadline deadline) { | 83 bool Connector::WaitForIncomingMessage(MojoDeadline deadline) { |
52 if (error_) | 84 if (error_) |
53 return false; | 85 return false; |
(...skipping 24 matching lines...) Expand all Loading... |
78 | 110 |
79 void Connector::ResumeIncomingMethodCallProcessing() { | 111 void Connector::ResumeIncomingMethodCallProcessing() { |
80 if (!paused_) | 112 if (!paused_) |
81 return; | 113 return; |
82 | 114 |
83 paused_ = false; | 115 paused_ = false; |
84 WaitToReadMore(); | 116 WaitToReadMore(); |
85 } | 117 } |
86 | 118 |
87 bool Connector::Accept(Message* message) { | 119 bool Connector::Accept(Message* message) { |
| 120 // It shouldn't hurt even if |error_| may be changed by a different thread at |
| 121 // the same time. The outcome is that we may write into |message_pipe_| after |
| 122 // encountering an error, which should be fine. |
88 if (error_) | 123 if (error_) |
89 return false; | 124 return false; |
90 | 125 |
91 MOJO_CHECK(message_pipe_.is_valid()); | 126 MayAutoLock locker(lock_.get()); |
92 if (drop_writes_) | 127 |
| 128 if (!message_pipe_.is_valid() || drop_writes_) |
93 return true; | 129 return true; |
94 | 130 |
95 MojoResult rv = | 131 MojoResult rv = |
96 WriteMessageRaw(message_pipe_.get(), | 132 WriteMessageRaw(message_pipe_.get(), |
97 message->data(), | 133 message->data(), |
98 message->data_num_bytes(), | 134 message->data_num_bytes(), |
99 message->mutable_handles()->empty() | 135 message->mutable_handles()->empty() |
100 ? nullptr | 136 ? nullptr |
101 : reinterpret_cast<const MojoHandle*>( | 137 : reinterpret_cast<const MojoHandle*>( |
102 &message->mutable_handles()->front()), | 138 &message->mutable_handles()->front()), |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 force_pipe_reset = true; | 266 force_pipe_reset = true; |
231 | 267 |
232 if (paused_) { | 268 if (paused_) { |
233 // If the user has paused receiving messages, we shouldn't call the error | 269 // If the user has paused receiving messages, we shouldn't call the error |
234 // handler right away. We need to wait until the user starts receiving | 270 // handler right away. We need to wait until the user starts receiving |
235 // messages again. | 271 // messages again. |
236 force_async_handler = true; | 272 force_async_handler = true; |
237 } | 273 } |
238 | 274 |
239 if (force_pipe_reset) { | 275 if (force_pipe_reset) { |
240 CloseMessagePipe(); | 276 CancelWait(); |
| 277 MayAutoLock locker(lock_.get()); |
| 278 Close(message_pipe_.Pass()); |
241 MessagePipe dummy_pipe; | 279 MessagePipe dummy_pipe; |
242 message_pipe_ = dummy_pipe.handle0.Pass(); | 280 message_pipe_ = dummy_pipe.handle0.Pass(); |
243 } else { | 281 } else { |
244 CancelWait(); | 282 CancelWait(); |
245 } | 283 } |
246 | 284 |
247 if (force_async_handler) { | 285 if (force_async_handler) { |
248 // |dummy_pipe.handle1| has been destructed. Reading the pipe will | 286 // |dummy_pipe.handle1| has been destructed. Reading the pipe will |
249 // eventually cause a read error on |message_pipe_| and set error state. | 287 // eventually cause a read error on |message_pipe_| and set error state. |
250 if (!paused_) | 288 if (!paused_) |
251 WaitToReadMore(); | 289 WaitToReadMore(); |
252 } else { | 290 } else { |
253 error_ = true; | 291 error_ = true; |
254 connection_error_handler_.Run(); | 292 connection_error_handler_.Run(); |
255 } | 293 } |
256 } | 294 } |
257 | 295 |
258 } // namespace internal | 296 } // namespace internal |
259 } // namespace mojo | 297 } // namespace mojo |
OLD | NEW |