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/dispatcher.h" | 5 #include "mojo/system/dispatcher.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "mojo/system/constants.h" | 8 #include "mojo/system/constants.h" |
9 #include "mojo/system/message_pipe_dispatcher.h" | 9 #include "mojo/system/message_pipe_dispatcher.h" |
10 | 10 |
(...skipping 22 matching lines...) Expand all Loading... |
33 | 33 |
34 // We shouldn't race with things that close dispatchers, since closing can | 34 // We shouldn't race with things that close dispatchers, since closing can |
35 // only take place either under |handle_table_lock_| or when the handle is | 35 // only take place either under |handle_table_lock_| or when the handle is |
36 // marked as busy. | 36 // marked as busy. |
37 DCHECK(!dispatcher->is_closed_); | 37 DCHECK(!dispatcher->is_closed_); |
38 | 38 |
39 return DispatcherTransport(dispatcher); | 39 return DispatcherTransport(dispatcher); |
40 } | 40 } |
41 | 41 |
42 // static | 42 // static |
43 size_t Dispatcher::MessageInTransitAccess::GetMaximumSerializedSize( | 43 void Dispatcher::MessageInTransitAccess::StartSerialize( |
44 const Dispatcher* dispatcher, | 44 Dispatcher* dispatcher, |
45 const Channel* channel) { | 45 Channel* channel, |
| 46 size_t* max_size, |
| 47 size_t* max_platform_handles) { |
46 DCHECK(dispatcher); | 48 DCHECK(dispatcher); |
47 return dispatcher->GetMaximumSerializedSize(channel); | 49 dispatcher->StartSerialize(channel, max_size, max_platform_handles); |
48 } | 50 } |
49 | 51 |
50 // static | 52 // static |
51 bool Dispatcher::MessageInTransitAccess::SerializeAndClose( | 53 bool Dispatcher::MessageInTransitAccess::EndSerializeAndClose( |
52 Dispatcher* dispatcher, | 54 Dispatcher* dispatcher, |
53 Channel* channel, | 55 Channel* channel, |
54 void* destination, | 56 void* destination, |
55 size_t* actual_size) { | 57 size_t* actual_size, |
| 58 std::vector<embedder::PlatformHandle>* platform_handles) { |
56 DCHECK(dispatcher); | 59 DCHECK(dispatcher); |
57 return dispatcher->SerializeAndClose(channel, destination, actual_size); | 60 return dispatcher->EndSerializeAndClose(channel, destination, actual_size, |
| 61 platform_handles); |
58 } | 62 } |
59 | 63 |
60 // static | 64 // static |
61 scoped_refptr<Dispatcher> Dispatcher::MessageInTransitAccess::Deserialize( | 65 scoped_refptr<Dispatcher> Dispatcher::MessageInTransitAccess::Deserialize( |
62 Channel* channel, | 66 Channel* channel, |
63 int32_t type, | 67 int32_t type, |
64 const void* source, | 68 const void* source, |
65 size_t size) { | 69 size_t size) { |
66 switch (static_cast<int32_t>(type)) { | 70 switch (static_cast<int32_t>(type)) { |
67 case kTypeUnknown: | 71 case kTypeUnknown: |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 return MOJO_RESULT_FAILED_PRECONDITION; | 348 return MOJO_RESULT_FAILED_PRECONDITION; |
345 } | 349 } |
346 | 350 |
347 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/) { | 351 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/) { |
348 lock_.AssertAcquired(); | 352 lock_.AssertAcquired(); |
349 DCHECK(!is_closed_); | 353 DCHECK(!is_closed_); |
350 // By default, waiting isn't supported. Only dispatchers that can be waited on | 354 // By default, waiting isn't supported. Only dispatchers that can be waited on |
351 // will do something nontrivial. | 355 // will do something nontrivial. |
352 } | 356 } |
353 | 357 |
354 size_t Dispatcher::GetMaximumSerializedSizeImplNoLock( | 358 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/, |
355 const Channel* /*channel*/) const { | 359 size_t* max_size, |
| 360 size_t* max_platform_handles) { |
356 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 361 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
357 DCHECK(!is_closed_); | 362 DCHECK(!is_closed_); |
358 // By default, serializing isn't supported. | 363 *max_size = 0; |
359 return 0; | 364 *max_platform_handles = 0; |
360 } | 365 } |
361 | 366 |
362 bool Dispatcher::SerializeAndCloseImplNoLock(Channel* /*channel*/, | 367 bool Dispatcher::EndSerializeAndCloseImplNoLock( |
363 void* /*destination*/, | 368 Channel* /*channel*/, |
364 size_t* /*actual_size*/) { | 369 void* /*destination*/, |
| 370 size_t* /*actual_size*/, |
| 371 std::vector<embedder::PlatformHandle>* /*platform_handles*/) { |
365 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 372 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
366 DCHECK(is_closed_); | 373 DCHECK(is_closed_); |
367 // By default, serializing isn't supported, so just close. | 374 // By default, serializing isn't supported, so just close. |
368 CloseImplNoLock(); | 375 CloseImplNoLock(); |
369 return 0; | 376 return false; |
370 } | 377 } |
371 | 378 |
372 bool Dispatcher::IsBusyNoLock() const { | 379 bool Dispatcher::IsBusyNoLock() const { |
373 lock_.AssertAcquired(); | 380 lock_.AssertAcquired(); |
374 DCHECK(!is_closed_); | 381 DCHECK(!is_closed_); |
375 // Most dispatchers support only "atomic" operations, so they are never busy | 382 // Most dispatchers support only "atomic" operations, so they are never busy |
376 // (in this sense). | 383 // (in this sense). |
377 return false; | 384 return false; |
378 } | 385 } |
379 | 386 |
380 void Dispatcher::CloseNoLock() { | 387 void Dispatcher::CloseNoLock() { |
381 lock_.AssertAcquired(); | 388 lock_.AssertAcquired(); |
382 DCHECK(!is_closed_); | 389 DCHECK(!is_closed_); |
383 | 390 |
384 is_closed_ = true; | 391 is_closed_ = true; |
385 CancelAllWaitersNoLock(); | 392 CancelAllWaitersNoLock(); |
386 CloseImplNoLock(); | 393 CloseImplNoLock(); |
387 } | 394 } |
388 | 395 |
389 scoped_refptr<Dispatcher> | 396 scoped_refptr<Dispatcher> |
390 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { | 397 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { |
391 lock_.AssertAcquired(); | 398 lock_.AssertAcquired(); |
392 DCHECK(!is_closed_); | 399 DCHECK(!is_closed_); |
393 | 400 |
394 is_closed_ = true; | 401 is_closed_ = true; |
395 CancelAllWaitersNoLock(); | 402 CancelAllWaitersNoLock(); |
396 return CreateEquivalentDispatcherAndCloseImplNoLock(); | 403 return CreateEquivalentDispatcherAndCloseImplNoLock(); |
397 } | 404 } |
398 | 405 |
399 size_t Dispatcher::GetMaximumSerializedSize(const Channel* channel) const { | 406 void Dispatcher::StartSerialize(Channel* channel, |
| 407 size_t* max_size, |
| 408 size_t* max_platform_handles) { |
400 DCHECK(channel); | 409 DCHECK(channel); |
| 410 DCHECK(max_size); |
| 411 DCHECK(max_platform_handles); |
401 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 412 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
402 DCHECK(!is_closed_); | 413 DCHECK(!is_closed_); |
403 return GetMaximumSerializedSizeImplNoLock(channel); | 414 StartSerializeImplNoLock(channel, max_size, max_platform_handles); |
404 } | 415 } |
405 | 416 |
406 bool Dispatcher::SerializeAndClose(Channel* channel, | 417 bool Dispatcher::EndSerializeAndClose( |
407 void* destination, | 418 Channel* channel, |
408 size_t* actual_size) { | 419 void* destination, |
409 DCHECK(destination); | 420 size_t* actual_size, |
| 421 std::vector<embedder::PlatformHandle>* platform_handles) { |
410 DCHECK(channel); | 422 DCHECK(channel); |
411 DCHECK(actual_size); | 423 DCHECK(actual_size); |
412 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 424 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
413 DCHECK(!is_closed_); | 425 DCHECK(!is_closed_); |
414 | 426 |
415 // We have to call |GetMaximumSerializedSizeImplNoLock()| first, because we | |
416 // leave it to |SerializeAndCloseImplNoLock()| to close the thing. | |
417 #if DCHECK_IS_ON | |
418 size_t max_size = GetMaximumSerializedSizeImplNoLock(channel); | |
419 #else | |
420 size_t max_size = static_cast<size_t>(-1); | |
421 #endif | |
422 | |
423 // Like other |...Close()| methods, we mark ourselves as closed before calling | 427 // Like other |...Close()| methods, we mark ourselves as closed before calling |
424 // the impl. | 428 // the impl. |
425 is_closed_ = true; | 429 is_closed_ = true; |
426 // No need to cancel waiters: we shouldn't have any (and shouldn't be in | 430 // No need to cancel waiters: we shouldn't have any (and shouldn't be in |
427 // |Core|'s handle table. | 431 // |Core|'s handle table. |
428 | 432 |
429 if (!SerializeAndCloseImplNoLock(channel, destination, actual_size)) | 433 #if !defined(NDEBUG) |
430 return false; | 434 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking |
| 435 // isn't actually needed, but we need to satisfy assertions (which we don't |
| 436 // want to remove or weaken). |
| 437 base::AutoLock locker(lock_); |
| 438 #endif |
431 | 439 |
432 DCHECK_LE(*actual_size, max_size); | 440 return EndSerializeAndCloseImplNoLock(channel, destination, actual_size, |
433 return true; | 441 platform_handles); |
434 } | 442 } |
435 | 443 |
436 // DispatcherTransport --------------------------------------------------------- | 444 // DispatcherTransport --------------------------------------------------------- |
437 | 445 |
438 void DispatcherTransport::End() { | 446 void DispatcherTransport::End() { |
439 DCHECK(dispatcher_); | 447 DCHECK(dispatcher_); |
440 dispatcher_->lock_.Release(); | 448 dispatcher_->lock_.Release(); |
441 dispatcher_ = NULL; | 449 dispatcher_ = NULL; |
442 } | 450 } |
443 | 451 |
444 } // namespace system | 452 } // namespace system |
445 } // namespace mojo | 453 } // namespace mojo |
OLD | NEW |