Chromium Code Reviews| 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/edk/system/core.h" | 5 #include "mojo/edk/system/core.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 // |MessagePipeDispatcher|) for each handle, with each handle having a strong | 40 // |MessagePipeDispatcher|) for each handle, with each handle having a strong |
| 41 // reference to the common "secondary" object (e.g., |MessagePipe|). This | 41 // reference to the common "secondary" object (e.g., |MessagePipe|). This |
| 42 // secondary object does NOT have any references to the |Dispatcher|s (even if | 42 // secondary object does NOT have any references to the |Dispatcher|s (even if |
| 43 // it did, it wouldn't be able to do anything with them due to lock order | 43 // it did, it wouldn't be able to do anything with them due to lock order |
| 44 // requirements -- see below). | 44 // requirements -- see below). |
| 45 // | 45 // |
| 46 // Waiting is implemented by having the thread that wants to wait call the | 46 // Waiting is implemented by having the thread that wants to wait call the |
| 47 // |Dispatcher|s for the handles that it wants to wait on with a |Waiter| | 47 // |Dispatcher|s for the handles that it wants to wait on with a |Waiter| |
| 48 // object; this |Waiter| object may be created on the stack of that thread or be | 48 // object; this |Waiter| object may be created on the stack of that thread or be |
| 49 // kept in thread local storage for that thread (TODO(vtl): future improvement). | 49 // kept in thread local storage for that thread (TODO(vtl): future improvement). |
| 50 // The |Dispatcher| then adds the |Waiter| to a |WaiterList| that's either owned | 50 // The |Dispatcher| then adds the |Waiter| to a |AwakableList| that's either |
|
viettrungluu
2014/12/03 22:31:27
"a" -> "an"
Hajime Morrita
2014/12/03 22:47:11
Done.
| |
| 51 // by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object (e.g., | 51 // owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object |
| 52 // |MessagePipe|). To signal/wake a |Waiter|, the object in question -- either a | 52 // (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question -- |
| 53 // |SimpleDispatcher| or a secondary object -- talks to its |WaiterList|. | 53 // either a |SimpleDispatcher| or a secondary object -- talks to its |
| 54 // |AwakableList|. | |
| 54 | 55 |
| 55 // Thread-safety notes | 56 // Thread-safety notes |
| 56 // | 57 // |
| 57 // Mojo primitives calls are thread-safe. We achieve this with relatively | 58 // Mojo primitives calls are thread-safe. We achieve this with relatively |
| 58 // fine-grained locking. There is a global handle table lock. This lock should | 59 // fine-grained locking. There is a global handle table lock. This lock should |
| 59 // be held as briefly as possible (TODO(vtl): a future improvement would be to | 60 // be held as briefly as possible (TODO(vtl): a future improvement would be to |
| 60 // switch it to a reader-writer lock). Each |Dispatcher| object then has a lock | 61 // switch it to a reader-writer lock). Each |Dispatcher| object then has a lock |
| 61 // (which subclasses can use to protect their data). | 62 // (which subclasses can use to protect their data). |
| 62 // | 63 // |
| 63 // The lock ordering is as follows: | 64 // The lock ordering is as follows: |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 dispatchers.push_back(dispatcher); | 555 dispatchers.push_back(dispatcher); |
| 555 } | 556 } |
| 556 | 557 |
| 557 // TODO(vtl): Should make the waiter live (permanently) in TLS. | 558 // TODO(vtl): Should make the waiter live (permanently) in TLS. |
| 558 Waiter waiter; | 559 Waiter waiter; |
| 559 waiter.Init(); | 560 waiter.Init(); |
| 560 | 561 |
| 561 uint32_t i; | 562 uint32_t i; |
| 562 MojoResult rv = MOJO_RESULT_OK; | 563 MojoResult rv = MOJO_RESULT_OK; |
| 563 for (i = 0; i < num_handles; i++) { | 564 for (i = 0; i < num_handles; i++) { |
| 564 rv = dispatchers[i]->AddWaiter( | 565 rv = dispatchers[i]->AddAwakable( |
| 565 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); | 566 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); |
| 566 if (rv != MOJO_RESULT_OK) { | 567 if (rv != MOJO_RESULT_OK) { |
| 567 *result_index = i; | 568 *result_index = i; |
| 568 break; | 569 break; |
| 569 } | 570 } |
| 570 } | 571 } |
| 571 uint32_t num_added = i; | 572 uint32_t num_added = i; |
| 572 | 573 |
| 573 if (rv == MOJO_RESULT_ALREADY_EXISTS) | 574 if (rv == MOJO_RESULT_ALREADY_EXISTS) |
| 574 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". | 575 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". |
| 575 else if (rv == MOJO_RESULT_OK) | 576 else if (rv == MOJO_RESULT_OK) |
| 576 rv = waiter.Wait(deadline, result_index); | 577 rv = waiter.Wait(deadline, result_index); |
| 577 | 578 |
| 578 // Make sure no other dispatchers try to wake |waiter| for the current | 579 // Make sure no other dispatchers try to wake |waiter| for the current |
| 579 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | 580 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
| 580 // destroyed, but this would still be required if the waiter were in TLS.) | 581 // destroyed, but this would still be required if the waiter were in TLS.) |
| 581 for (i = 0; i < num_added; i++) { | 582 for (i = 0; i < num_added; i++) { |
| 582 dispatchers[i]->RemoveWaiter(&waiter, | 583 dispatchers[i]->RemoveAwakable( |
| 583 signals_states ? &signals_states[i] : nullptr); | 584 &waiter, signals_states ? &signals_states[i] : nullptr); |
| 584 } | 585 } |
| 585 if (signals_states) { | 586 if (signals_states) { |
| 586 for (; i < num_handles; i++) | 587 for (; i < num_handles; i++) |
| 587 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); | 588 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
| 588 } | 589 } |
| 589 | 590 |
| 590 return rv; | 591 return rv; |
| 591 } | 592 } |
| 592 | 593 |
| 593 } // namespace system | 594 } // namespace system |
| 594 } // namespace mojo | 595 } // namespace mojo |
| OLD | NEW |