summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 23:12:50 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-13 23:12:50 +0000
commit1389053dca9b296f74d5704c62f6494aef1cbb63 (patch)
treef1bed144cf559be845c4c031a6ebbf9869b9e70f /mojo
parent4540d58b344a1e284c5fa0224b748612fa9d84c3 (diff)
downloadchromium_src-1389053dca9b296f74d5704c62f6494aef1cbb63.zip
chromium_src-1389053dca9b296f74d5704c62f6494aef1cbb63.tar.gz
chromium_src-1389053dca9b296f74d5704c62f6494aef1cbb63.tar.bz2
Mojo: Update Waiter::Wait() to not put the context into the return value.
(Instead, it puts it into an out parameter.) Also reverse the order of the arguments to Waiter::Awake(). R=davemoore@chromium.org Review URL: https://codereview.chromium.org/337803002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@277119 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
-rw-r--r--mojo/system/channel_unittest.cc2
-rw-r--r--mojo/system/core.cc10
-rw-r--r--mojo/system/local_data_pipe_unittest.cc32
-rw-r--r--mojo/system/message_pipe_dispatcher_unittest.cc32
-rw-r--r--mojo/system/message_pipe_unittest.cc20
-rw-r--r--mojo/system/multiprocess_message_pipe_unittest.cc2
-rw-r--r--mojo/system/remote_message_pipe_unittest.cc39
-rw-r--r--mojo/system/simple_dispatcher_unittest.cc163
-rw-r--r--mojo/system/waiter.cc27
-rw-r--r--mojo/system/waiter.h44
-rw-r--r--mojo/system/waiter_list.cc6
-rw-r--r--mojo/system/waiter_list_unittest.cc112
-rw-r--r--mojo/system/waiter_test_utils.cc17
-rw-r--r--mojo/system/waiter_test_utils.h10
-rw-r--r--mojo/system/waiter_unittest.cc100
15 files changed, 380 insertions, 236 deletions
diff --git a/mojo/system/channel_unittest.cc b/mojo/system/channel_unittest.cc
index 200e7fa..e8c8260 100644
--- a/mojo/system/channel_unittest.cc
+++ b/mojo/system/channel_unittest.cc
@@ -273,7 +273,7 @@ TEST_F(ChannelTest, ShutdownAfterAttach) {
// ... since this |Wait()| should fail once the channel is shut down.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ waiter.Wait(MOJO_DEADLINE_INDEFINITE, NULL));
mp->RemoveWaiter(0, &waiter);
mp->Close(0);
diff --git a/mojo/system/core.cc b/mojo/system/core.cc
index cfa4db7..f670272 100644
--- a/mojo/system/core.cc
+++ b/mojo/system/core.cc
@@ -539,10 +539,14 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles,
}
uint32_t num_added = i;
- if (rv == MOJO_RESULT_ALREADY_EXISTS)
+ if (rv == MOJO_RESULT_ALREADY_EXISTS) {
rv = static_cast<MojoResult>(i); // The i-th one is already "triggered".
- else if (rv == MOJO_RESULT_OK)
- rv = waiter.Wait(deadline);
+ } else if (rv == MOJO_RESULT_OK) {
+ uint32_t context = static_cast<uint32_t>(-1);
+ rv = waiter.Wait(deadline, &context);
+ if (rv == MOJO_RESULT_OK)
+ rv = static_cast<MojoResult>(context);
+ }
// Make sure no other dispatchers try to wake |waiter| for the current
// |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be
diff --git a/mojo/system/local_data_pipe_unittest.cc b/mojo/system/local_data_pipe_unittest.cc
index 3477d65f..391f001 100644
--- a/mojo/system/local_data_pipe_unittest.cc
+++ b/mojo/system/local_data_pipe_unittest.cc
@@ -201,6 +201,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
+ uint32_t context = 0;
// Never readable.
waiter.Init();
@@ -223,7 +224,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
EXPECT_EQ(MOJO_RESULT_OK,
dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 56));
// And it shouldn't be writable yet.
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ProducerRemoveWaiter(&waiter);
// Do it again.
@@ -241,7 +242,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
EXPECT_EQ(-1, elements[1]);
// Waiting should now succeed.
- EXPECT_EQ(78, waiter.Wait(1000));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
+ EXPECT_EQ(78u, context);
dp->ProducerRemoveWaiter(&waiter);
// Try writing, using a two-phase write.
@@ -278,7 +280,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
static_cast<uint32_t>(1u * sizeof(elements[0]))));
// Waiting should succeed.
- EXPECT_EQ(90, waiter.Wait(1000));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
+ EXPECT_EQ(90u, context);
dp->ProducerRemoveWaiter(&waiter);
// Write one element.
@@ -296,7 +299,8 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) {
dp->ConsumerClose();
// It should now be never-writable.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
+ EXPECT_EQ(12u, context);
dp->ProducerRemoveWaiter(&waiter);
dp->ProducerClose();
@@ -316,6 +320,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
{
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
+ uint32_t context = 0;
// Never writable.
waiter.Init();
@@ -326,7 +331,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 34));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ConsumerRemoveWaiter(&waiter);
// Write two elements.
@@ -372,7 +377,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
dp->ProducerWriteData(elements, &num_bytes, true));
// Waiting should now succeed.
- EXPECT_EQ(90, waiter.Wait(1000));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
+ EXPECT_EQ(90u, context);
dp->ConsumerRemoveWaiter(&waiter);
// Close the producer.
@@ -405,6 +411,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
{
scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
Waiter waiter;
+ uint32_t context = 0;
// Write two elements.
int32_t* elements = NULL;
@@ -469,7 +476,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) {
dp->ProducerClose();
// Should be never-readable.
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context));
+ EXPECT_EQ(56u, context);
dp->ConsumerRemoveWaiter(&waiter);
dp->ConsumerClose();
@@ -507,14 +515,14 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ProducerAddWaiter(&waiter, MOJO_WAIT_FLAG_WRITABLE, 1));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ProducerRemoveWaiter(&waiter);
// It shouldn't be readable yet either.
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 2));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ConsumerRemoveWaiter(&waiter);
static_cast<int32_t*>(write_ptr)[0] = 123;
@@ -566,7 +574,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 7));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ConsumerRemoveWaiter(&waiter);
// End the two-phase read without reading anything.
@@ -605,7 +613,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 1));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ConsumerRemoveWaiter(&waiter);
uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t));
@@ -658,7 +666,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dp->ConsumerAddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 7));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
dp->ConsumerRemoveWaiter(&waiter);
dp->ProducerClose();
diff --git a/mojo/system/message_pipe_dispatcher_unittest.cc b/mojo/system/message_pipe_dispatcher_unittest.cc
index 2fc6469..127e34e 100644
--- a/mojo/system/message_pipe_dispatcher_unittest.cc
+++ b/mojo/system/message_pipe_dispatcher_unittest.cc
@@ -48,6 +48,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
d1->Init(mp, i ^ 1); // 1, 0.
}
Waiter w;
+ uint32_t context = 0;
// Try adding a writable waiter when already writable.
w.Init();
@@ -66,7 +67,8 @@ TEST(MessagePipeDispatcherTest, Basic) {
NULL,
MOJO_WRITE_MESSAGE_FLAG_NONE));
stopwatch.Start();
- EXPECT_EQ(1, w.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(1u, context);
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
d0->RemoveWaiter(&w);
@@ -91,7 +93,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_OK,
d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3));
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, NULL));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
d0->RemoveWaiter(&w);
@@ -101,7 +103,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
d0->AddWaiter(&w, MOJO_WAIT_FLAG_READABLE, 3));
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), NULL));
base::TimeDelta elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
@@ -264,6 +266,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
base::TimeDelta elapsed;
bool did_wait;
MojoResult result;
+ uint32_t context;
// Run this test both with |d0| as port 0, |d1| as port 1 and vice versa.
for (unsigned i = 0; i < 2; i++) {
@@ -282,8 +285,8 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d1,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 0,
- &did_wait, &result);
+ 1,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -298,15 +301,16 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
- EXPECT_EQ(0, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(1u, context);
// Now |d1| is already readable. Try waiting for it again.
{
test::WaiterThread thread(d1,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 1,
- &did_wait, &result);
+ 2,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
} // Joins the thread.
@@ -330,8 +334,8 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d1,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 0,
- &did_wait, &result);
+ 3,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -342,6 +346,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(3u, context);
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
}
@@ -363,8 +368,8 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d1,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 0,
- &did_wait, &result);
+ 4,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -375,6 +380,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(4u, context);
EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
}
@@ -469,7 +475,7 @@ class ReaderThread : public base::SimpleThread {
result == MOJO_RESULT_ALREADY_EXISTS) << "result: " << result;
if (result == MOJO_RESULT_OK) {
// Actually need to wait.
- EXPECT_EQ(0, w.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, NULL));
read_dispatcher_->RemoveWaiter(&w);
}
diff --git a/mojo/system/message_pipe_unittest.cc b/mojo/system/message_pipe_unittest.cc
index 8708d9f..73c310f 100644
--- a/mojo/system/message_pipe_unittest.cc
+++ b/mojo/system/message_pipe_unittest.cc
@@ -378,7 +378,7 @@ TEST(MessagePipeTest, BasicWaiting) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
mp->AddWaiter(0, &waiter, MOJO_WAIT_FLAG_READABLE, 1));
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL));
mp->RemoveWaiter(0, &waiter);
// Write from port 0 (to port 1), to make port 1 readable.
@@ -440,15 +440,16 @@ TEST(MessagePipeTest, ThreadedWaiting) {
const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer));
MojoResult result;
+ uint32_t context;
// Write to wake up waiter waiting for read.
{
scoped_refptr<MessagePipe> mp(new MessagePipe());
- test::SimpleWaiterThread thread(&result);
+ test::SimpleWaiterThread thread(&result, &context);
thread.waiter()->Init();
EXPECT_EQ(MOJO_RESULT_OK,
- mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
+ mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 1));
thread.Start();
buffer[0] = 123456789;
@@ -465,16 +466,17 @@ TEST(MessagePipeTest, ThreadedWaiting) {
mp->Close(1);
} // Joins |thread|.
// The waiter should have woken up successfully.
- EXPECT_EQ(0, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(1u, context);
// Close to cancel waiter.
{
scoped_refptr<MessagePipe> mp(new MessagePipe());
- test::SimpleWaiterThread thread(&result);
+ test::SimpleWaiterThread thread(&result, &context);
thread.waiter()->Init();
EXPECT_EQ(MOJO_RESULT_OK,
- mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
+ mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2));
thread.Start();
// Close port 1 first -- this should result in the waiter being cancelled.
@@ -487,15 +489,16 @@ TEST(MessagePipeTest, ThreadedWaiting) {
mp->Close(0);
} // Joins |thread|.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(2u, context);
// Close to make waiter un-wake-up-able.
{
scoped_refptr<MessagePipe> mp(new MessagePipe());
- test::SimpleWaiterThread thread(&result);
+ test::SimpleWaiterThread thread(&result, &context);
thread.waiter()->Init();
EXPECT_EQ(MOJO_RESULT_OK,
- mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0));
+ mp->AddWaiter(1, thread.waiter(), MOJO_WAIT_FLAG_READABLE, 3));
thread.Start();
// Close port 0 first -- this should wake the waiter up, since port 1 will
@@ -509,6 +512,7 @@ TEST(MessagePipeTest, ThreadedWaiting) {
mp->Close(1);
} // Joins |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(3u, context);
}
} // namespace
diff --git a/mojo/system/multiprocess_message_pipe_unittest.cc b/mojo/system/multiprocess_message_pipe_unittest.cc
index 8279196..fa16996 100644
--- a/mojo/system/multiprocess_message_pipe_unittest.cc
+++ b/mojo/system/multiprocess_message_pipe_unittest.cc
@@ -135,7 +135,7 @@ MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, MojoWaitFlags flags) {
add_result;
}
- MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE);
+ MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE, NULL);
mp->RemoveWaiter(0, &waiter);
return wait_result;
}
diff --git a/mojo/system/remote_message_pipe_unittest.cc b/mojo/system/remote_message_pipe_unittest.cc
index 3c5e2a4..f6db49f 100644
--- a/mojo/system/remote_message_pipe_unittest.cc
+++ b/mojo/system/remote_message_pipe_unittest.cc
@@ -177,6 +177,7 @@ TEST_F(RemoteMessagePipeTest, Basic) {
char buffer[100] = { 0 };
uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
Waiter waiter;
+ uint32_t context = 0;
// Connect message pipes. MP 0, port 1 will be attached to channel 0 and
// connected to MP 1, port 0, which will be attached to channel 1. This leaves
@@ -206,7 +207,8 @@ TEST_F(RemoteMessagePipeTest, Basic) {
MOJO_WRITE_MESSAGE_FLAG_NONE));
// Wait.
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Read from MP 1, port 1.
@@ -230,7 +232,8 @@ TEST_F(RemoteMessagePipeTest, Basic) {
NULL,
MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(456, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(456u, context);
mp0->RemoveWaiter(0, &waiter);
buffer_size = static_cast<uint32_t>(sizeof(buffer));
@@ -252,7 +255,8 @@ TEST_F(RemoteMessagePipeTest, Basic) {
MojoResult result = mp1->AddWaiter(1, &waiter, MOJO_WAIT_FLAG_READABLE, 789);
if (result == MOJO_RESULT_OK) {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(789u, context);
mp1->RemoveWaiter(1, &waiter);
} else {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
@@ -268,6 +272,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
char buffer[100] = { 0 };
uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
Waiter waiter;
+ uint32_t context = 0;
// Connect message pipes as in the |Basic| test.
@@ -301,7 +306,8 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
NULL,
MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(789, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(789u, context);
mp3->RemoveWaiter(1, &waiter);
// Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0.
@@ -346,7 +352,8 @@ TEST_F(RemoteMessagePipeTest, Multiplex) {
NULL,
MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Make sure there's nothing on the other ports.
@@ -389,6 +396,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) {
char buffer[100] = { 0 };
uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
Waiter waiter;
+ uint32_t context = 0;
// Connect message pipes. MP 0, port 1 will be attached to channel 0 and
// connected to MP 1, port 0, which will be attached to channel 1. This leaves
@@ -424,7 +432,8 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) {
BootstrapMessagePipeNoWait(1, mp1);
// Wait.
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Read from MP 1, port 1.
@@ -443,6 +452,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) {
TEST_F(RemoteMessagePipeTest, HandlePassing) {
static const char kHello[] = "hello";
Waiter waiter;
+ uint32_t context = 0;
scoped_refptr<MessagePipe> mp0(new MessagePipe(
scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
@@ -484,7 +494,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
}
// Wait.
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Read from MP 1, port 1.
@@ -518,7 +529,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
waiter.Init();
EXPECT_EQ(MOJO_RESULT_OK,
dispatcher->AddWaiter(&waiter, MOJO_WAIT_FLAG_READABLE, 456));
- EXPECT_EQ(456, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(456u, context);
dispatcher->RemoveWaiter(&waiter);
// Read from the dispatcher.
@@ -541,7 +553,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
MOJO_WRITE_MESSAGE_FLAG_NONE));
// Wait.
- EXPECT_EQ(789, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(789u, context);
local_mp->RemoveWaiter(1, &waiter);
// Read from "local_mp", port 1.
@@ -573,6 +586,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) {
TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
static const char kHello[] = "hello";
Waiter waiter;
+ uint32_t context = 0;
scoped_refptr<MessagePipe> mp0(new MessagePipe(
scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
@@ -628,7 +642,8 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) {
}
// Wait.
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Read from MP 1, port 1.
@@ -693,6 +708,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) {
static const char kHello[] = "hello";
static const char kWorld[] = "world";
Waiter waiter;
+ uint32_t context = 0;
scoped_refptr<MessagePipe> mp0(new MessagePipe(
scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()),
@@ -737,7 +753,8 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) {
}
// Wait.
- EXPECT_EQ(123, waiter.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(123u, context);
mp1->RemoveWaiter(1, &waiter);
// Read from MP 1, port 1.
diff --git a/mojo/system/simple_dispatcher_unittest.cc b/mojo/system/simple_dispatcher_unittest.cc
index 26fc277..3b292ddd 100644
--- a/mojo/system/simple_dispatcher_unittest.cc
+++ b/mojo/system/simple_dispatcher_unittest.cc
@@ -92,6 +92,7 @@ TEST(SimpleDispatcherTest, Basic) {
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
Waiter w;
+ uint32_t context = 0;
// Try adding a readable waiter when already readable.
w.Init();
@@ -106,8 +107,9 @@ TEST(SimpleDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 1));
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_WRITABLE);
stopwatch.Start();
- EXPECT_EQ(1, w.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(1u, context);
d->RemoveWaiter(&w);
// Wait for zero time for writable when already writable.
@@ -116,8 +118,9 @@ TEST(SimpleDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 2));
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_WRITABLE);
stopwatch.Start();
- EXPECT_EQ(2, w.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(2u, context);
d->RemoveWaiter(&w);
// Wait for non-zero, finite time for writable when already writable.
@@ -126,8 +129,10 @@ TEST(SimpleDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 3));
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_WRITABLE);
stopwatch.Start();
- EXPECT_EQ(3, w.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(3u, context);
d->RemoveWaiter(&w);
// Wait for zero time for writable when not writable (will time out).
@@ -135,7 +140,7 @@ TEST(SimpleDispatcherTest, Basic) {
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_READABLE);
EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 4));
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, NULL));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
d->RemoveWaiter(&w);
@@ -143,10 +148,10 @@ TEST(SimpleDispatcherTest, Basic) {
// out).
w.Init();
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_READABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 4));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 5));
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), NULL));
base::TimeDelta elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
@@ -160,45 +165,50 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) {
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
Waiter w;
+ uint32_t context = 0;
// Try adding a writable waiter when it can never be writable.
w.Init();
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE);
d->SetSatisfiedFlags(0);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 5));
+ d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 1));
// Shouldn't need to remove the waiter (it was not added).
// Wait (forever) for writable and then it becomes never writable.
w.Init();
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 6));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 2));
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE);
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+ w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(2u, context);
d->RemoveWaiter(&w);
// Wait for zero time for writable and then it becomes never writable.
w.Init();
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 6));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 3));
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE);
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(3u, context);
d->RemoveWaiter(&w);
// Wait for non-zero, finite time for writable and then it becomes never
// writable.
w.Init();
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE);
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 7));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 4));
d->SetSatisfiableFlags(MOJO_WAIT_FLAG_READABLE);
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(4u, context);
d->RemoveWaiter(&w);
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
@@ -209,45 +219,49 @@ TEST(SimpleDispatcherTest, BasicClosed) {
scoped_refptr<MockSimpleDispatcher> d;
Waiter w;
+ uint32_t context = 0;
// Try adding a writable waiter when the dispatcher has been closed.
d = new MockSimpleDispatcher();
w.Init();
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 8));
+ d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 1));
// Shouldn't need to remove the waiter (it was not added).
// Wait (forever) for writable and then the dispatcher is closed.
d = new MockSimpleDispatcher();
w.Init();
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 9));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 2));
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE));
+ EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(2u, context);
// Don't need to remove waiters from closed dispatchers.
// Wait for zero time for writable and then the dispatcher is closed.
d = new MockSimpleDispatcher();
w.Init();
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 10));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 3));
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(3u, context);
// Don't need to remove waiters from closed dispatchers.
// Wait for non-zero, finite time for writable and then the dispatcher is
// closed.
d = new MockSimpleDispatcher();
w.Init();
- EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 11));
+ EXPECT_EQ(MOJO_RESULT_OK, d->AddWaiter(&w, MOJO_WAIT_FLAG_WRITABLE, 4));
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_CANCELLED,
- w.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
+ EXPECT_EQ(4u, context);
// Don't need to remove waiters from closed dispatchers.
}
@@ -255,6 +269,7 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::Stopwatch stopwatch;
bool did_wait;
MojoResult result;
+ uint32_t context;
// Wait for readable (already readable).
{
@@ -264,8 +279,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 0,
- &did_wait, &result);
+ 1,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
} // Joins the thread.
@@ -282,8 +297,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 1,
- &did_wait, &result);
+ 2,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -294,7 +309,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
- EXPECT_EQ(1, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(2u, context);
// Wait for readable and becomes never-readable after some time.
{
@@ -302,8 +318,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 2,
- &did_wait, &result);
+ 3,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -315,6 +331,7 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(3u, context);
// Wait for readable and dispatcher gets closed.
{
@@ -322,8 +339,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- 3,
- &did_wait, &result);
+ 4,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -334,6 +351,7 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(4u, context);
// Wait for readable and times out.
{
@@ -342,8 +360,8 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
test::WaiterThread thread(d,
MOJO_WAIT_FLAG_READABLE,
2 * test::EpsilonTimeout().InMicroseconds(),
- 4,
- &did_wait, &result);
+ 5,
+ &did_wait, &result, &context);
stopwatch.Start();
thread.Start();
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -361,30 +379,34 @@ TEST(SimpleDispatcherTest, BasicThreaded) {
}
TEST(SimpleDispatcherTest, MultipleWaiters) {
- static const size_t kNumWaiters = 20;
+ static const uint32_t kNumWaiters = 20;
bool did_wait[kNumWaiters];
MojoResult result[kNumWaiters];
+ uint32_t context[kNumWaiters];
// All wait for readable and becomes readable after some time.
{
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
ScopedVector<test::WaiterThread> threads;
- for (size_t i = 0; i < kNumWaiters; i++) {
+ for (uint32_t i = 0; i < kNumWaiters; i++) {
threads.push_back(new test::WaiterThread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i],
+ &result[i],
+ &context[i]));
threads.back()->Start();
}
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_READABLE);
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
} // Joins the threads.
- for (size_t i = 0; i < kNumWaiters; i++) {
+ for (uint32_t i = 0; i < kNumWaiters; i++) {
EXPECT_TRUE(did_wait[i]);
- EXPECT_EQ(static_cast<MojoResult>(i), result[i]);
+ EXPECT_EQ(MOJO_RESULT_OK, result[i]);
+ EXPECT_EQ(i, context[i]);
}
// Some wait for readable, some for writable, and becomes readable after some
@@ -392,20 +414,24 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
{
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
ScopedVector<test::WaiterThread> threads;
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
threads.push_back(new test::WaiterThread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i],
+ &result[i],
+ &context[i]));
threads.back()->Start();
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
threads.push_back(new test::WaiterThread(d,
MOJO_WAIT_FLAG_WRITABLE,
MOJO_DEADLINE_INDEFINITE,
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i],
+ &result[i],
+ &context[i]));
threads.back()->Start();
}
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -413,13 +439,15 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
// This will wake up the ones waiting to write.
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
} // Joins the threads.
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
EXPECT_TRUE(did_wait[i]);
- EXPECT_EQ(static_cast<MojoResult>(i), result[i]);
+ EXPECT_EQ(MOJO_RESULT_OK, result[i]);
+ EXPECT_EQ(i, context[i]);
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
EXPECT_TRUE(did_wait[i]);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result[i]);
+ EXPECT_EQ(i, context[i]);
}
// Some wait for readable, some for writable, and becomes readable and
@@ -427,20 +455,24 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
{
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
ScopedVector<test::WaiterThread> threads;
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
threads.push_back(new test::WaiterThread(d,
MOJO_WAIT_FLAG_READABLE,
MOJO_DEADLINE_INDEFINITE,
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i],
+ &result[i],
+ &context[i]));
threads.back()->Start();
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
threads.push_back(new test::WaiterThread(d,
MOJO_WAIT_FLAG_WRITABLE,
MOJO_DEADLINE_INDEFINITE,
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i],
+ &result[i],
+ &context[i]));
threads.back()->Start();
}
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -449,13 +481,15 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
d->SetSatisfiedFlags(MOJO_WAIT_FLAG_READABLE);
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
} // Joins the threads.
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
EXPECT_TRUE(did_wait[i]);
- EXPECT_EQ(static_cast<MojoResult>(i), result[i]);
+ EXPECT_EQ(MOJO_RESULT_OK, result[i]);
+ EXPECT_EQ(i, context[i]);
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
EXPECT_TRUE(did_wait[i]);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result[i]);
+ EXPECT_EQ(i, context[i]);
}
// Some wait for readable, some for writable, and becomes readable after some
@@ -463,22 +497,22 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
{
scoped_refptr<MockSimpleDispatcher> d(new MockSimpleDispatcher());
ScopedVector<test::WaiterThread> threads;
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
threads.push_back(
new test::WaiterThread(d,
MOJO_WAIT_FLAG_READABLE,
3 * test::EpsilonTimeout().InMicroseconds(),
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i], &result[i], &context[i]));
threads.back()->Start();
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
threads.push_back(
new test::WaiterThread(d,
MOJO_WAIT_FLAG_WRITABLE,
1 * test::EpsilonTimeout().InMicroseconds(),
- static_cast<MojoResult>(i),
- &did_wait[i], &result[i]));
+ i,
+ &did_wait[i], &result[i], &context[i]));
threads.back()->Start();
}
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
@@ -486,11 +520,12 @@ TEST(SimpleDispatcherTest, MultipleWaiters) {
// All those waiting for writable should have timed out.
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
} // Joins the threads.
- for (size_t i = 0; i < kNumWaiters / 2; i++) {
+ for (uint32_t i = 0; i < kNumWaiters / 2; i++) {
EXPECT_TRUE(did_wait[i]);
- EXPECT_EQ(static_cast<MojoResult>(i), result[i]);
+ EXPECT_EQ(MOJO_RESULT_OK, result[i]);
+ EXPECT_EQ(i, context[i]);
}
- for (size_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
+ for (uint32_t i = kNumWaiters / 2; i < kNumWaiters; i++) {
EXPECT_TRUE(did_wait[i]);
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result[i]);
}
diff --git a/mojo/system/waiter.cc b/mojo/system/waiter.cc
index a7d18d3..5a3150d 100644
--- a/mojo/system/waiter.cc
+++ b/mojo/system/waiter.cc
@@ -18,8 +18,8 @@ Waiter::Waiter()
initialized_(false),
#endif
awoken_(false),
- awake_context_(static_cast<uint32_t>(-1)),
- awake_result_(MOJO_RESULT_INTERNAL) {
+ awake_result_(MOJO_RESULT_INTERNAL),
+ awake_context_(static_cast<uint32_t>(-1)) {
}
Waiter::~Waiter() {
@@ -36,7 +36,7 @@ void Waiter::Init() {
}
// TODO(vtl): Fast-path the |deadline == 0| case?
-MojoResult Waiter::Wait(MojoDeadline deadline) {
+MojoResult Waiter::Wait(MojoDeadline deadline, uint32_t* context) {
base::AutoLock locker(lock_);
#ifndef NDEBUG
@@ -48,10 +48,9 @@ MojoResult Waiter::Wait(MojoDeadline deadline) {
// Fast-path the already-awoken case:
if (awoken_) {
DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
- // TODO(vtl): This is a temporary hack until I add a |context| out parameter
- // and update all the call sites.
- return (awake_result_ == MOJO_RESULT_OK) ?
- static_cast<MojoResult>(awake_context_) : awake_result_;
+ if (context)
+ *context = awake_context_;
+ return awake_result_;
}
// |MojoDeadline| is actually a |uint64_t|, but we need a signed quantity.
@@ -69,30 +68,28 @@ MojoResult Waiter::Wait(MojoDeadline deadline) {
base::TimeDelta::FromMicroseconds(static_cast<int64_t>(deadline));
do {
base::TimeTicks now_time = base::TimeTicks::HighResNow();
- if (now_time >= end_time) {
+ if (now_time >= end_time)
return MOJO_RESULT_DEADLINE_EXCEEDED;
- }
cv_.TimedWait(end_time - now_time);
} while (!awoken_);
}
DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL);
- // TODO(vtl): This is a temporary hack until I add a |context| out parameter
- // and update all the call sites.
- return (awake_result_ == MOJO_RESULT_OK) ?
- static_cast<MojoResult>(awake_context_) : awake_result_;
+ if (context)
+ *context = awake_context_;
+ return awake_result_;
}
-void Waiter::Awake(uint32_t context, MojoResult result) {
+void Waiter::Awake(MojoResult result, uint32_t context) {
base::AutoLock locker(lock_);
if (awoken_)
return;
awoken_ = true;
- awake_context_ = context;
awake_result_ = result;
+ awake_context_ = context;
cv_.Signal();
// |cv_.Wait()|/|cv_.TimedWait()| will return after |lock_| is released.
}
diff --git a/mojo/system/waiter.h b/mojo/system/waiter.h
index e36cdd1..66fe6e7 100644
--- a/mojo/system/waiter.h
+++ b/mojo/system/waiter.h
@@ -29,23 +29,35 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter {
// each time it's used.
void Init();
- // TODO(vtl): FIXME -- Replace this with a version that has a |context| out
- // parameter (which also doesn't turn the context into a result on success).
- // Waits until a suitable |Awake()| is called.
+ // Waits until a suitable |Awake()| is called. (|context| may be null, in
+ // which case, obviously no context is ever returned.)
// Returns:
- // - The |context| passed to |Dispatcher::AddWaiter()| if it was woken up
- // by that dispatcher for the reason specified by |flags| (in the call to
- // |AddWaiter()|).
- // - |MOJO_RESULT_CANCELLED| if a handle (on which |MojoWait()| was called)
- // was closed; and
- // - |MOJO_RESULT_FAILED_PRECONDITION| if the reasons for being awoken given
- // by |flags| cannot (or can no longer) be satisfied (e.g., if the other
- // end of a pipe is closed).
- MojoResult Wait(MojoDeadline deadline);
+ // - The result given to the first call to |Awake()| (possibly before this
+ // call to |Wait()|); in this case, |*context| is set to the value passed
+ // to that call to |Awake()|.
+ // - |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline was exceeded; in this
+ // case |*context| is not modified.
+ //
+ // Usually, the context passed to |Awake()| will be the value passed to
+ // |Dispatcher::AddWaiter()|, which is usually the index to the array of
+ // handles passed to |MojoWaitMany()| (or 0 for |MojoWait()|).
+ //
+ // Typical |Awake()| results are:
+ // - |MOJO_RESULT_OK| if one of the flags passed to
+ // |MojoWait()|/|MojoWaitMany()| (hence |Dispatcher::AddWaiter()|) was
+ // satisfied;
+ // - |MOJO_RESULT_CANCELLED| if a handle (on which
+ // |MojoWait()|/|MojoWaitMany()| was called) was closed (hence the
+ // dispatcher closed); and
+ // - |MOJO_RESULT_FAILED_PRECONDITION| if one of the set of flags passed to
+ // |MojoWait()|/|MojoWaitMany()| cannot or can no longer be satisfied by
+ // the corresponding handle (e.g., if the other end of a message or data
+ // pipe is closed).
+ MojoResult Wait(MojoDeadline deadline, uint32_t* context);
- // Wake the waiter up with the given result (or no-op if it's been woken up
- // already).
- void Awake(uint32_t context, MojoResult result);
+ // Wake the waiter up with the given result and context (or no-op if it's been
+ // woken up already).
+ void Awake(MojoResult result, uint32_t context);
private:
base::ConditionVariable cv_; // Associated to |lock_|.
@@ -54,11 +66,11 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter {
bool initialized_;
#endif
bool awoken_;
+ MojoResult awake_result_;
// This is a |uint32_t| because we really only need to store an index (for
// |MojoWaitMany()|). But in tests, it's convenient to use this for other
// purposes (e.g., to distinguish between different wake-up reasons).
uint32_t awake_context_;
- MojoResult awake_result_;
DISALLOW_COPY_AND_ASSIGN(Waiter);
};
diff --git a/mojo/system/waiter_list.cc b/mojo/system/waiter_list.cc
index 1a54b0d..e286543 100644
--- a/mojo/system/waiter_list.cc
+++ b/mojo/system/waiter_list.cc
@@ -22,16 +22,16 @@ void WaiterList::AwakeWaitersForStateChange(const WaitFlagsState& state) {
for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end();
++it) {
if (state.satisfies(it->flags))
- it->waiter->Awake(it->context, MOJO_RESULT_OK);
+ it->waiter->Awake(MOJO_RESULT_OK, it->context);
else if (!state.can_satisfy(it->flags))
- it->waiter->Awake(it->context, MOJO_RESULT_FAILED_PRECONDITION);
+ it->waiter->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context);
}
}
void WaiterList::CancelAllWaiters() {
for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end();
++it) {
- it->waiter->Awake(it->context, MOJO_RESULT_CANCELLED);
+ it->waiter->Awake(MOJO_RESULT_CANCELLED, it->context);
}
waiters_.clear();
}
diff --git a/mojo/system/waiter_list_unittest.cc b/mojo/system/waiter_list_unittest.cc
index eb77681..8b9714b 100644
--- a/mojo/system/waiter_list_unittest.cc
+++ b/mojo/system/waiter_list_unittest.cc
@@ -23,61 +23,67 @@ namespace {
TEST(WaiterListTest, BasicCancel) {
MojoResult result;
+ uint32_t context;
// Cancel immediately after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 1);
thread.Start();
waiter_list.CancelAllWaiters();
waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay.
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(1u, context);
// Cancel before after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 2);
waiter_list.CancelAllWaiters();
thread.Start();
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(2u, context);
// Cancel some time after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 3);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.CancelAllWaiters();
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(3u, context);
}
TEST(WaiterListTest, BasicAwakeSatisfied) {
MojoResult result;
+ uint32_t context;
// Awake immediately after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 1);
thread.Start();
waiter_list.AwakeWaitersForStateChange(
WaitFlagsState(MOJO_WAIT_FLAG_READABLE,
MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
- EXPECT_EQ(0, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(1u, context);
// Awake before after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 2);
waiter_list.AwakeWaitersForStateChange(
WaitFlagsState(MOJO_WAIT_FLAG_WRITABLE,
MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
@@ -85,13 +91,14 @@ TEST(WaiterListTest, BasicAwakeSatisfied) {
waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay.
thread.Start();
} // Join |thread|.
- EXPECT_EQ(1, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(2u, context);
// Awake some time after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 3);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.AwakeWaitersForStateChange(
@@ -99,41 +106,45 @@ TEST(WaiterListTest, BasicAwakeSatisfied) {
MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
- EXPECT_EQ(2, result);
+ EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(3u, context);
}
TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
MojoResult result;
+ uint32_t context;
// Awake (for unsatisfiability) immediately after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 1);
thread.Start();
waiter_list.AwakeWaitersForStateChange(
WaitFlagsState(MOJO_WAIT_FLAG_NONE, MOJO_WAIT_FLAG_WRITABLE));
waiter_list.RemoveWaiter(thread.waiter());
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(1u, context);
// Awake (for unsatisfiability) before after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 2);
waiter_list.AwakeWaitersForStateChange(
WaitFlagsState(MOJO_WAIT_FLAG_READABLE, MOJO_WAIT_FLAG_READABLE));
waiter_list.RemoveWaiter(thread.waiter());
thread.Start();
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(2u, context);
// Awake (for unsatisfiability) some time after thread start.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread(&result);
- waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
+ test::SimpleWaiterThread thread(&result, &context);
+ waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 3);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.AwakeWaitersForStateChange(
@@ -142,6 +153,7 @@ TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay.
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(3u, context);
}
TEST(WaiterListTest, MultipleWaiters) {
@@ -149,30 +161,36 @@ TEST(WaiterListTest, MultipleWaiters) {
MojoResult result2;
MojoResult result3;
MojoResult result4;
+ uint32_t context1;
+ uint32_t context2;
+ uint32_t context3;
+ uint32_t context4;
// Cancel two waiters.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread1(&result1);
- waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 0);
+ test::SimpleWaiterThread thread1(&result1, &context1);
+ waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 1);
thread1.Start();
- test::SimpleWaiterThread thread2(&result2);
- waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1);
+ test::SimpleWaiterThread thread2(&result2, &context2);
+ waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 2);
thread2.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.CancelAllWaiters();
} // Join threads.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
+ EXPECT_EQ(1u, context1);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
+ EXPECT_EQ(2u, context2);
// Awake one waiter, cancel other.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread1(&result1);
- waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 2);
+ test::SimpleWaiterThread thread1(&result1, &context1);
+ waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 3);
thread1.Start();
- test::SimpleWaiterThread thread2(&result2);
- waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 3);
+ test::SimpleWaiterThread thread2(&result2, &context2);
+ waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 4);
thread2.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.AwakeWaitersForStateChange(
@@ -181,17 +199,19 @@ TEST(WaiterListTest, MultipleWaiters) {
waiter_list.RemoveWaiter(thread1.waiter());
waiter_list.CancelAllWaiters();
} // Join threads.
- EXPECT_EQ(2, result1);
+ EXPECT_EQ(MOJO_RESULT_OK, result1);
+ EXPECT_EQ(3u, context1);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
+ EXPECT_EQ(4u, context2);
// Cancel one waiter, awake other for unsatisfiability.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread1(&result1);
- waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 4);
+ test::SimpleWaiterThread thread1(&result1, &context1);
+ waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 5);
thread1.Start();
- test::SimpleWaiterThread thread2(&result2);
- waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 5);
+ test::SimpleWaiterThread thread2(&result2, &context2);
+ waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 6);
thread2.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
waiter_list.AwakeWaitersForStateChange(
@@ -200,13 +220,15 @@ TEST(WaiterListTest, MultipleWaiters) {
waiter_list.CancelAllWaiters();
} // Join threads.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
+ EXPECT_EQ(5u, context1);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2);
+ EXPECT_EQ(6u, context2);
// Cancel one waiter, awake other for unsatisfiability.
{
WaiterList waiter_list;
- test::SimpleWaiterThread thread1(&result1);
- waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 6);
+ test::SimpleWaiterThread thread1(&result1, &context1);
+ waiter_list.AddWaiter(thread1.waiter(), MOJO_WAIT_FLAG_READABLE, 7);
thread1.Start();
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -216,8 +238,8 @@ TEST(WaiterListTest, MultipleWaiters) {
WaitFlagsState(MOJO_WAIT_FLAG_NONE,
MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE));
- test::SimpleWaiterThread thread2(&result2);
- waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 7);
+ test::SimpleWaiterThread thread2(&result2, &context2);
+ waiter_list.AddWaiter(thread2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 8);
thread2.Start();
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -230,12 +252,12 @@ TEST(WaiterListTest, MultipleWaiters) {
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- test::SimpleWaiterThread thread3(&result3);
- waiter_list.AddWaiter(thread3.waiter(), MOJO_WAIT_FLAG_WRITABLE, 8);
+ test::SimpleWaiterThread thread3(&result3, &context3);
+ waiter_list.AddWaiter(thread3.waiter(), MOJO_WAIT_FLAG_WRITABLE, 9);
thread3.Start();
- test::SimpleWaiterThread thread4(&result4);
- waiter_list.AddWaiter(thread4.waiter(), MOJO_WAIT_FLAG_READABLE, 9);
+ test::SimpleWaiterThread thread4(&result4, &context4);
+ waiter_list.AddWaiter(thread4.waiter(), MOJO_WAIT_FLAG_READABLE, 10);
thread4.Start();
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
@@ -249,10 +271,14 @@ TEST(WaiterListTest, MultipleWaiters) {
// Cancel #4.
waiter_list.CancelAllWaiters();
} // Join threads.
- EXPECT_EQ(6, result1);
+ EXPECT_EQ(MOJO_RESULT_OK, result1);
+ EXPECT_EQ(7u, context1);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2);
+ EXPECT_EQ(8u, context2);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3);
+ EXPECT_EQ(9u, context3);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result4);
+ EXPECT_EQ(10u, context4);
}
} // namespace
diff --git a/mojo/system/waiter_test_utils.cc b/mojo/system/waiter_test_utils.cc
index 94cd930..23c8e3e 100644
--- a/mojo/system/waiter_test_utils.cc
+++ b/mojo/system/waiter_test_utils.cc
@@ -8,11 +8,13 @@ namespace mojo {
namespace system {
namespace test {
-SimpleWaiterThread::SimpleWaiterThread(MojoResult* result)
+SimpleWaiterThread::SimpleWaiterThread(MojoResult* result, uint32_t* context)
: base::SimpleThread("waiter_thread"),
- result_(result) {
+ result_(result),
+ context_(context) {
waiter_.Init();
*result_ = -5420734; // Totally invalid result.
+ *context_ = 23489023; // "Random".
}
SimpleWaiterThread::~SimpleWaiterThread() {
@@ -20,7 +22,7 @@ SimpleWaiterThread::~SimpleWaiterThread() {
}
void SimpleWaiterThread::Run() {
- *result_ = waiter_.Wait(MOJO_DEADLINE_INDEFINITE);
+ *result_ = waiter_.Wait(MOJO_DEADLINE_INDEFINITE, context_);
}
WaiterThread::WaiterThread(scoped_refptr<Dispatcher> dispatcher,
@@ -28,16 +30,19 @@ WaiterThread::WaiterThread(scoped_refptr<Dispatcher> dispatcher,
MojoDeadline deadline,
uint32_t context,
bool* did_wait_out,
- MojoResult* result_out)
+ MojoResult* result_out,
+ uint32_t* context_out)
: base::SimpleThread("waiter_thread"),
dispatcher_(dispatcher),
wait_flags_(wait_flags),
deadline_(deadline),
context_(context),
did_wait_out_(did_wait_out),
- result_out_(result_out) {
+ result_out_(result_out),
+ context_out_(context_out) {
*did_wait_out_ = false;
*result_out_ = -8542346; // Totally invalid result.
+ *context_out_ = 89023444; // "Random".
}
WaiterThread::~WaiterThread() {
@@ -52,7 +57,7 @@ void WaiterThread::Run() {
return;
*did_wait_out_ = true;
- *result_out_ = waiter_.Wait(deadline_);
+ *result_out_ = waiter_.Wait(deadline_, context_out_);
dispatcher_->RemoveWaiter(&waiter_);
}
diff --git a/mojo/system/waiter_test_utils.h b/mojo/system/waiter_test_utils.h
index d4f1fa1..26dd747 100644
--- a/mojo/system/waiter_test_utils.h
+++ b/mojo/system/waiter_test_utils.h
@@ -47,7 +47,7 @@ class SimpleWaiterThread : public base::SimpleThread {
public:
// For the duration of the lifetime of this object, |*result| belongs to it
// (in the sense that it will write to it whenever it wants).
- explicit SimpleWaiterThread(MojoResult* result);
+ SimpleWaiterThread(MojoResult* result, uint32_t* context);
virtual ~SimpleWaiterThread(); // Joins the thread.
Waiter* waiter() { return &waiter_; }
@@ -56,6 +56,7 @@ class SimpleWaiterThread : public base::SimpleThread {
virtual void Run() OVERRIDE;
MojoResult* const result_;
+ uint32_t* const context_;
Waiter waiter_;
DISALLOW_COPY_AND_ASSIGN(SimpleWaiterThread);
@@ -66,13 +67,15 @@ class SimpleWaiterThread : public base::SimpleThread {
// |SimpleWaiterThread|, it requires the machinery of |Dispatcher|.
class WaiterThread : public base::SimpleThread {
public:
- // Note: |*did_wait_out| and |*result| belong to this object while it's alive.
+ // Note: |*did_wait_out|, |*result_out|, and |*context_out| "belong" to this
+ // object (i.e., may be modified by, on some other thread) while it's alive.
WaiterThread(scoped_refptr<Dispatcher> dispatcher,
MojoWaitFlags wait_flags,
MojoDeadline deadline,
uint32_t context,
bool* did_wait_out,
- MojoResult* result_out);
+ MojoResult* result_out,
+ uint32_t* context_out);
virtual ~WaiterThread();
private:
@@ -84,6 +87,7 @@ class WaiterThread : public base::SimpleThread {
const uint32_t context_;
bool* const did_wait_out_;
MojoResult* const result_out_;
+ uint32_t* const context_out_;
Waiter waiter_;
diff --git a/mojo/system/waiter_unittest.cc b/mojo/system/waiter_unittest.cc
index 22237de..3afef28 100644
--- a/mojo/system/waiter_unittest.cc
+++ b/mojo/system/waiter_unittest.cc
@@ -31,7 +31,8 @@ class WaitingThread : public base::SimpleThread {
: base::SimpleThread("waiting_thread"),
deadline_(deadline),
done_(false),
- result_(MOJO_RESULT_UNKNOWN) {
+ result_(MOJO_RESULT_UNKNOWN),
+ context_(static_cast<uint32_t>(-1)) {
waiter_.Init();
}
@@ -39,12 +40,15 @@ class WaitingThread : public base::SimpleThread {
Join();
}
- void WaitUntilDone(MojoResult* result, base::TimeDelta* elapsed) {
+ void WaitUntilDone(MojoResult* result,
+ uint32_t* context,
+ base::TimeDelta* elapsed) {
for (;;) {
{
base::AutoLock locker(lock_);
if (done_) {
*result = result_;
+ *context = context_;
*elapsed = elapsed_;
break;
}
@@ -61,16 +65,18 @@ class WaitingThread : public base::SimpleThread {
virtual void Run() OVERRIDE {
test::Stopwatch stopwatch;
MojoResult result;
+ uint32_t context = static_cast<uint32_t>(-1);
base::TimeDelta elapsed;
stopwatch.Start();
- result = waiter_.Wait(deadline_);
+ result = waiter_.Wait(deadline_, &context);
elapsed = stopwatch.Elapsed();
{
base::AutoLock locker(lock_);
done_ = true;
result_ = result;
+ context_ = context;
elapsed_ = elapsed;
}
}
@@ -81,6 +87,7 @@ class WaitingThread : public base::SimpleThread {
base::Lock lock_; // Protects the following members.
bool done_;
MojoResult result_;
+ uint32_t context_;
base::TimeDelta elapsed_;
DISALLOW_COPY_AND_ASSIGN(WaitingThread);
@@ -88,6 +95,7 @@ class WaitingThread : public base::SimpleThread {
TEST(WaiterTest, Basic) {
MojoResult result;
+ uint32_t context;
base::TimeDelta elapsed;
// Finite deadline.
@@ -96,19 +104,21 @@ TEST(WaiterTest, Basic) {
{
WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
thread.Start();
- thread.waiter()->Awake(0, MOJO_RESULT_OK);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(MOJO_RESULT_OK, 1);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(1u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
// Awake before after thread start.
{
WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
- thread.waiter()->Awake(0, MOJO_RESULT_CANCELLED);
+ thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 2);
thread.Start();
- thread.WaitUntilDone(&result, &elapsed);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(2u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
@@ -117,9 +127,10 @@ TEST(WaiterTest, Basic) {
WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, 1);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(1, 3);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(1, result);
+ EXPECT_EQ(3u, context);
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
}
@@ -129,9 +140,10 @@ TEST(WaiterTest, Basic) {
WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
thread.Start();
base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, 1);
- thread.WaitUntilDone(&result, &elapsed);
- EXPECT_EQ(1, result);
+ thread.waiter()->Awake(2, 4);
+ thread.WaitUntilDone(&result, &context, &elapsed);
+ EXPECT_EQ(2, result);
+ EXPECT_EQ(4u, context);
EXPECT_GT(elapsed, (5-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (5+1) * test::EpsilonTimeout());
}
@@ -140,8 +152,9 @@ TEST(WaiterTest, Basic) {
{
WaitingThread thread(2 * test::EpsilonTimeout().InMicroseconds());
thread.Start();
- thread.WaitUntilDone(&result, &elapsed);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
+ EXPECT_EQ(static_cast<uint32_t>(-1), context);
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
}
@@ -152,19 +165,21 @@ TEST(WaiterTest, Basic) {
{
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
thread.Start();
- thread.waiter()->Awake(0, MOJO_RESULT_OK);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(MOJO_RESULT_OK, 5);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(5u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
// Awake before after thread start.
{
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.waiter()->Awake(0, MOJO_RESULT_CANCELLED);
+ thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 6);
thread.Start();
- thread.WaitUntilDone(&result, &elapsed);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(6u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
@@ -173,9 +188,10 @@ TEST(WaiterTest, Basic) {
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
thread.Start();
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, 1);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(1, 7);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(1, result);
+ EXPECT_EQ(7u, context);
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
}
@@ -185,9 +201,10 @@ TEST(WaiterTest, Basic) {
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
thread.Start();
base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, 1);
- thread.WaitUntilDone(&result, &elapsed);
- EXPECT_EQ(1, result);
+ thread.waiter()->Awake(2, 8);
+ thread.WaitUntilDone(&result, &context, &elapsed);
+ EXPECT_EQ(2, result);
+ EXPECT_EQ(8u, context);
EXPECT_GT(elapsed, (5-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (5+1) * test::EpsilonTimeout());
}
@@ -198,63 +215,71 @@ TEST(WaiterTest, TimeOut) {
base::TimeDelta elapsed;
Waiter waiter;
+ uint32_t context = 123;
waiter.Init();
stopwatch.Start();
- EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, &context));
elapsed = stopwatch.Elapsed();
EXPECT_LT(elapsed, test::EpsilonTimeout());
+ EXPECT_EQ(123u, context);
waiter.Init();
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- waiter.Wait(2 * test::EpsilonTimeout().InMicroseconds()));
+ waiter.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2+1) * test::EpsilonTimeout());
+ EXPECT_EQ(123u, context);
waiter.Init();
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
- waiter.Wait(5 * test::EpsilonTimeout().InMicroseconds()));
+ waiter.Wait(5 * test::EpsilonTimeout().InMicroseconds(), &context));
elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (5-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (5+1) * test::EpsilonTimeout());
+ EXPECT_EQ(123u, context);
}
// The first |Awake()| should always win.
TEST(WaiterTest, MultipleAwakes) {
MojoResult result;
+ uint32_t context;
base::TimeDelta elapsed;
{
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
thread.Start();
- thread.waiter()->Awake(0, MOJO_RESULT_OK);
- thread.waiter()->Awake(0, 1);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(MOJO_RESULT_OK, 1);
+ thread.waiter()->Awake(1, 2);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_OK, result);
+ EXPECT_EQ(1u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
{
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
- thread.waiter()->Awake(0, 1);
+ thread.waiter()->Awake(1, 3);
thread.Start();
- thread.waiter()->Awake(0, MOJO_RESULT_OK);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(MOJO_RESULT_OK, 4);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(1, result);
+ EXPECT_EQ(3u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
{
WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
thread.Start();
- thread.waiter()->Awake(0, 10);
+ thread.waiter()->Awake(10, 5);
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, 20);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(20, 6);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(10, result);
+ EXPECT_EQ(5u, context);
EXPECT_LT(elapsed, test::EpsilonTimeout());
}
@@ -262,11 +287,12 @@ TEST(WaiterTest, MultipleAwakes) {
WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
thread.Start();
base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, MOJO_RESULT_FAILED_PRECONDITION);
+ thread.waiter()->Awake(MOJO_RESULT_FAILED_PRECONDITION, 7);
base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
- thread.waiter()->Awake(0, MOJO_RESULT_OK);
- thread.WaitUntilDone(&result, &elapsed);
+ thread.waiter()->Awake(MOJO_RESULT_OK, 8);
+ thread.WaitUntilDone(&result, &context, &elapsed);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
+ EXPECT_EQ(7u, context);
EXPECT_GT(elapsed, (1-1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (1+1) * test::EpsilonTimeout());
}