Index: mojo/system/core.cc |
diff --git a/mojo/system/core.cc b/mojo/system/core.cc |
index 46c5bceb4876c7d6f76477386ca193b3c295b288..5b09675d971a9a853ffb4f788446977d046293ed 100644 |
--- a/mojo/system/core.cc |
+++ b/mojo/system/core.cc |
@@ -14,6 +14,7 @@ |
#include "mojo/system/data_pipe_consumer_dispatcher.h" |
#include "mojo/system/data_pipe_producer_dispatcher.h" |
#include "mojo/system/dispatcher.h" |
+#include "mojo/system/handle_signals_state.h" |
#include "mojo/system/local_data_pipe.h" |
#include "mojo/system/memory.h" |
#include "mojo/system/message_pipe.h" |
@@ -118,15 +119,27 @@ MojoResult Core::Close(MojoHandle handle) { |
MojoResult Core::Wait(MojoHandle handle, |
MojoHandleSignals signals, |
- MojoDeadline deadline) { |
+ MojoDeadline deadline, |
+ UserPointer<MojoHandleSignalsState> signals_state) { |
uint32_t unused = static_cast<uint32_t>(-1); |
- return WaitManyInternal(&handle, &signals, 1, deadline, &unused); |
+ HandleSignalsState hss; |
+ MojoResult rv = WaitManyInternal(&handle, |
+ &signals, |
+ 1, |
+ deadline, |
+ &unused, |
+ signals_state.IsNull() ? NULL : &hss); |
+ if (rv != MOJO_RESULT_INVALID_ARGUMENT && !signals_state.IsNull()) |
+ signals_state.Put(hss); |
+ return rv; |
} |
MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, |
UserPointer<const MojoHandleSignals> signals, |
uint32_t num_handles, |
- MojoDeadline deadline) { |
+ MojoDeadline deadline, |
+ UserPointer<uint32_t> result_index, |
+ UserPointer<MojoHandleSignalsState> signals_states) { |
if (num_handles < 1) |
return MOJO_RESULT_INVALID_ARGUMENT; |
if (num_handles > kMaxWaitManyNumHandles) |
@@ -135,14 +148,33 @@ MojoResult Core::WaitMany(UserPointer<const MojoHandle> handles, |
UserPointer<const MojoHandle>::Reader handles_reader(handles, num_handles); |
UserPointer<const MojoHandleSignals>::Reader signals_reader(signals, |
num_handles); |
- uint32_t result_index = static_cast<uint32_t>(-1); |
- MojoResult result = WaitManyInternal(handles_reader.GetPointer(), |
- signals_reader.GetPointer(), |
- num_handles, |
- deadline, |
- &result_index); |
- return (result == MOJO_RESULT_OK) ? static_cast<MojoResult>(result_index) |
- : result; |
+ uint32_t index = static_cast<uint32_t>(-1); |
+ MojoResult rv; |
+ if (signals_states.IsNull()) { |
+ rv = WaitManyInternal(handles_reader.GetPointer(), |
+ signals_reader.GetPointer(), |
+ num_handles, |
+ deadline, |
+ &index, |
+ NULL); |
+ } else { |
+ UserPointer<MojoHandleSignalsState>::Writer signals_states_writer( |
+ signals_states, num_handles); |
+ // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a |
+ // subclass of |MojoHandleSignalsState| that doesn't add any data members. |
+ rv = WaitManyInternal(handles_reader.GetPointer(), |
+ signals_reader.GetPointer(), |
+ num_handles, |
+ deadline, |
+ &index, |
+ reinterpret_cast<HandleSignalsState*>( |
+ signals_states_writer.GetPointer())); |
+ if (rv != MOJO_RESULT_INVALID_ARGUMENT) |
+ signals_states_writer.Commit(); |
+ } |
+ if (index != static_cast<uint32_t>(-1) && !result_index.IsNull()) |
+ result_index.Put(index); |
+ return rv; |
} |
MojoResult Core::CreateMessagePipe( |
@@ -515,7 +547,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
const MojoHandleSignals* signals, |
uint32_t num_handles, |
MojoDeadline deadline, |
- uint32_t* result_index) { |
+ uint32_t* result_index, |
+ HandleSignalsState* signals_states) { |
DCHECK_GT(num_handles, 0u); |
DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); |
@@ -537,7 +570,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
uint32_t i; |
MojoResult rv = MOJO_RESULT_OK; |
for (i = 0; i < num_handles; i++) { |
- rv = dispatchers[i]->AddWaiter(&waiter, signals[i], i, NULL); |
+ rv = dispatchers[i]->AddWaiter( |
+ &waiter, signals[i], i, signals_states ? &signals_states[i] : NULL); |
if (rv != MOJO_RESULT_OK) { |
*result_index = i; |
break; |
@@ -553,8 +587,14 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
// Make sure no other dispatchers try to wake |waiter| for the current |
// |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
// destroyed, but this would still be required if the waiter were in TLS.) |
- for (i = 0; i < num_added; i++) |
- dispatchers[i]->RemoveWaiter(&waiter, NULL); |
+ for (i = 0; i < num_added; i++) { |
+ dispatchers[i]->RemoveWaiter(&waiter, |
+ signals_states ? &signals_states[i] : NULL); |
+ } |
+ if (signals_states) { |
+ for (; i < num_handles; i++) |
+ signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
+ } |
return rv; |
} |