| 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/system/raw_channel.h" | 5 #include "mojo/system/raw_channel.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" |
| 15 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 17 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
| 18 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
| 19 #include "mojo/embedder/platform_handle.h" | 20 #include "mojo/embedder/platform_handle.h" |
| 20 | 21 |
| 21 namespace mojo { | 22 namespace mojo { |
| 22 namespace system { | 23 namespace system { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 scoped_ptr<WriteBuffer> write_buffer); | 118 scoped_ptr<WriteBuffer> write_buffer); |
| 118 | 119 |
| 119 private: | 120 private: |
| 120 virtual ~RawChannelIOHandler(); | 121 virtual ~RawChannelIOHandler(); |
| 121 | 122 |
| 122 // Returns true if |owner_| has been reset and there is not pending read or | 123 // Returns true if |owner_| has been reset and there is not pending read or |
| 123 // write. | 124 // write. |
| 124 // Must be called on the I/O thread. | 125 // Must be called on the I/O thread. |
| 125 bool ShouldSelfDestruct() const; | 126 bool ShouldSelfDestruct() const; |
| 126 | 127 |
| 127 // Must be called on the I/O thread. It could be called before or after | 128 // Must be called on the I/O thread. It may be called before or after |
| 128 // detached from the owner. | 129 // detaching from the owner. |
| 129 void OnReadCompleted(DWORD bytes_read, DWORD error); | 130 void OnReadCompleted(DWORD bytes_read, DWORD error); |
| 130 // Must be called on the I/O thread. It could be called before or after | 131 // Must be called on the I/O thread. It may be called before or after |
| 131 // detached from the owner. | 132 // detaching from the owner. |
| 132 void OnWriteCompleted(DWORD bytes_written, DWORD error); | 133 void OnWriteCompleted(DWORD bytes_written, DWORD error); |
| 133 | 134 |
| 134 embedder::ScopedPlatformHandle handle_; | 135 embedder::ScopedPlatformHandle handle_; |
| 135 | 136 |
| 136 // |owner_| is reset on the I/O thread under |owner_->write_lock()|. | 137 // |owner_| is reset on the I/O thread under |owner_->write_lock()|. |
| 137 // Therefore, it may be used on any thread under lock; or on the I/O thread | 138 // Therefore, it may be used on any thread under lock; or on the I/O thread |
| 138 // without locking. | 139 // without locking. |
| 139 RawChannelWin* owner_; | 140 RawChannelWin* owner_; |
| 140 | 141 |
| 141 // The following members must be used on the I/O thread. | 142 // The following members must be used on the I/O thread. |
| 142 scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; | 143 scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; |
| 143 scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; | 144 scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; |
| 145 bool suppress_self_destruct_; |
| 144 | 146 |
| 145 bool pending_read_; | 147 bool pending_read_; |
| 146 base::MessageLoopForIO::IOContext read_context_; | 148 base::MessageLoopForIO::IOContext read_context_; |
| 147 | 149 |
| 148 // The following members must be used under |owner_->write_lock()| while the | 150 // The following members must be used under |owner_->write_lock()| while the |
| 149 // object is still attached to the owner, and only on the I/O thread | 151 // object is still attached to the owner, and only on the I/O thread |
| 150 // afterwards. | 152 // afterwards. |
| 151 bool pending_write_; | 153 bool pending_write_; |
| 152 base::MessageLoopForIO::IOContext write_context_; | 154 base::MessageLoopForIO::IOContext write_context_; |
| 153 | 155 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 171 | 173 |
| 172 const bool skip_completion_port_on_success_; | 174 const bool skip_completion_port_on_success_; |
| 173 | 175 |
| 174 DISALLOW_COPY_AND_ASSIGN(RawChannelWin); | 176 DISALLOW_COPY_AND_ASSIGN(RawChannelWin); |
| 175 }; | 177 }; |
| 176 | 178 |
| 177 RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( | 179 RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( |
| 178 RawChannelWin* owner, | 180 RawChannelWin* owner, |
| 179 embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()), | 181 embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()), |
| 180 owner_(owner), | 182 owner_(owner), |
| 183 suppress_self_destruct_(false), |
| 181 pending_read_(false), | 184 pending_read_(false), |
| 182 pending_write_(false) { | 185 pending_write_(false) { |
| 183 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); | 186 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
| 184 read_context_.handler = this; | 187 read_context_.handler = this; |
| 185 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); | 188 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); |
| 186 write_context_.handler = this; | 189 write_context_.handler = this; |
| 187 | 190 |
| 188 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); | 191 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); |
| 189 } | 192 } |
| 190 | 193 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 pending_write_ = true; | 235 pending_write_ = true; |
| 233 } | 236 } |
| 234 | 237 |
| 235 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( | 238 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( |
| 236 base::MessageLoopForIO::IOContext* context, | 239 base::MessageLoopForIO::IOContext* context, |
| 237 DWORD bytes_transferred, | 240 DWORD bytes_transferred, |
| 238 DWORD error) { | 241 DWORD error) { |
| 239 DCHECK(!owner_ || | 242 DCHECK(!owner_ || |
| 240 base::MessageLoop::current() == owner_->message_loop_for_io()); | 243 base::MessageLoop::current() == owner_->message_loop_for_io()); |
| 241 | 244 |
| 242 if (context == &read_context_) | 245 { |
| 243 OnReadCompleted(bytes_transferred, error); | 246 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they |
| 244 else if (context == &write_context_) | 247 // result in a call to |Shutdown()|). |
| 245 OnWriteCompleted(bytes_transferred, error); | 248 base::AutoReset<bool> resetter(&suppress_self_destruct_, true); |
| 246 else | 249 |
| 247 NOTREACHED(); | 250 if (context == &read_context_) |
| 251 OnReadCompleted(bytes_transferred, error); |
| 252 else if (context == &write_context_) |
| 253 OnWriteCompleted(bytes_transferred, error); |
| 254 else |
| 255 NOTREACHED(); |
| 256 } |
| 248 | 257 |
| 249 if (ShouldSelfDestruct()) | 258 if (ShouldSelfDestruct()) |
| 250 delete this; | 259 delete this; |
| 251 } | 260 } |
| 252 | 261 |
| 253 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( | 262 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( |
| 254 scoped_ptr<ReadBuffer> read_buffer, | 263 scoped_ptr<ReadBuffer> read_buffer, |
| 255 scoped_ptr<WriteBuffer> write_buffer) { | 264 scoped_ptr<WriteBuffer> write_buffer) { |
| 256 DCHECK(owner_); | 265 DCHECK(owner_); |
| 257 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 266 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
| 258 owner_->write_lock().AssertAcquired(); | 267 owner_->write_lock().AssertAcquired(); |
| 259 | 268 |
| 260 // If read/write is pending, we have to retain the corresponding buffer. | 269 // If read/write is pending, we have to retain the corresponding buffer. |
| 261 if (pending_read_) | 270 if (pending_read_) |
| 262 preserved_read_buffer_after_detach_ = read_buffer.Pass(); | 271 preserved_read_buffer_after_detach_ = read_buffer.Pass(); |
| 263 if (pending_write_) | 272 if (pending_write_) |
| 264 preserved_write_buffer_after_detach_ = write_buffer.Pass(); | 273 preserved_write_buffer_after_detach_ = write_buffer.Pass(); |
| 265 | 274 |
| 266 owner_ = NULL; | 275 owner_ = NULL; |
| 267 if (ShouldSelfDestruct()) | 276 if (ShouldSelfDestruct()) |
| 268 delete this; | 277 delete this; |
| 269 } | 278 } |
| 270 | 279 |
| 271 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { | 280 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { |
| 272 if (owner_) | 281 if (owner_ || suppress_self_destruct_) |
| 273 return false; | 282 return false; |
| 274 | 283 |
| 275 // Note: Detached, hence no lock needed for |pending_write_|. | 284 // Note: Detached, hence no lock needed for |pending_write_|. |
| 276 return !pending_read_ && !pending_write_; | 285 return !pending_read_ && !pending_write_; |
| 277 } | 286 } |
| 278 | 287 |
| 279 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, | 288 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, |
| 280 DWORD error) { | 289 DWORD error) { |
| 281 DCHECK(!owner_ || | 290 DCHECK(!owner_ || |
| 282 base::MessageLoop::current() == owner_->message_loop_for_io()); | 291 base::MessageLoop::current() == owner_->message_loop_for_io()); |
| 292 DCHECK(suppress_self_destruct_); |
| 283 | 293 |
| 284 CHECK(pending_read_); | 294 CHECK(pending_read_); |
| 285 pending_read_ = false; | 295 pending_read_ = false; |
| 286 if (!owner_) | 296 if (!owner_) |
| 287 return; | 297 return; |
| 288 | 298 |
| 289 if (error != ERROR_SUCCESS) { | 299 if (error != ERROR_SUCCESS) { |
| 290 DCHECK_EQ(bytes_read, 0u); | 300 DCHECK_EQ(bytes_read, 0u); |
| 291 PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile"; | 301 PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile"; |
| 292 owner_->OnReadCompleted(false, 0); | 302 owner_->OnReadCompleted(false, 0); |
| 293 } else { | 303 } else { |
| 294 DCHECK_GT(bytes_read, 0u); | 304 DCHECK_GT(bytes_read, 0u); |
| 295 owner_->OnReadCompleted(true, bytes_read); | 305 owner_->OnReadCompleted(true, bytes_read); |
| 296 } | 306 } |
| 297 } | 307 } |
| 298 | 308 |
| 299 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, | 309 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, |
| 300 DWORD error) { | 310 DWORD error) { |
| 301 DCHECK(!owner_ || | 311 DCHECK(!owner_ || |
| 302 base::MessageLoop::current() == owner_->message_loop_for_io()); | 312 base::MessageLoop::current() == owner_->message_loop_for_io()); |
| 313 DCHECK(suppress_self_destruct_); |
| 303 | 314 |
| 304 if (!owner_) { | 315 if (!owner_) { |
| 305 // No lock needed. | 316 // No lock needed. |
| 306 CHECK(pending_write_); | 317 CHECK(pending_write_); |
| 307 pending_write_ = false; | 318 pending_write_ = false; |
| 308 return; | 319 return; |
| 309 } | 320 } |
| 310 | 321 |
| 311 { | 322 { |
| 312 base::AutoLock locker(owner_->write_lock()); | 323 base::AutoLock locker(owner_->write_lock()); |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 | 527 |
| 517 // Static factory method declared in raw_channel.h. | 528 // Static factory method declared in raw_channel.h. |
| 518 // static | 529 // static |
| 519 scoped_ptr<RawChannel> RawChannel::Create( | 530 scoped_ptr<RawChannel> RawChannel::Create( |
| 520 embedder::ScopedPlatformHandle handle) { | 531 embedder::ScopedPlatformHandle handle) { |
| 521 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); | 532 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); |
| 522 } | 533 } |
| 523 | 534 |
| 524 } // namespace system | 535 } // namespace system |
| 525 } // namespace mojo | 536 } // namespace mojo |
| OLD | NEW |