Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3250)

Unified Diff: mojo/public/cpp/system/tests/wait_set_unittest.cc

Issue 2754143005: Use WaitableEvents to wake up sync IPC waiting (Closed)
Patch Set: . Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/cpp/bindings/sync_handle_registry.h ('k') | mojo/public/cpp/system/wait_set.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/cpp/system/tests/wait_set_unittest.cc
diff --git a/mojo/public/cpp/system/tests/wait_set_unittest.cc b/mojo/public/cpp/system/tests/wait_set_unittest.cc
index 2a6d9b88256b32e9857971e6d2037454d3c6077f..d60cb45924df33c88dff54a70bd8708e01024dbd 100644
--- a/mojo/public/cpp/system/tests/wait_set_unittest.cc
+++ b/mojo/public/cpp/system/tests/wait_set_unittest.cc
@@ -4,11 +4,17 @@
#include "mojo/public/cpp/system/wait_set.h"
+#include <set>
+#include <vector>
+
#include "base/bind.h"
#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/public/cpp/system/wait.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
@@ -68,7 +74,7 @@ TEST_F(WaitSetTest, Satisfied) {
Handle ready_handles[2];
MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
HandleSignalsState hss[2];
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(p.handle1.get(), ready_handles[0]);
@@ -85,7 +91,7 @@ TEST_F(WaitSetTest, Satisfied) {
num_ready_handles = 2;
ready_results[0] = MOJO_RESULT_UNKNOWN;
ready_results[1] = MOJO_RESULT_UNKNOWN;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(p.handle0.get(), ready_handles[0]);
@@ -98,7 +104,7 @@ TEST_F(WaitSetTest, Satisfied) {
num_ready_handles = 2;
ready_results[0] = MOJO_RESULT_UNKNOWN;
ready_results[1] = MOJO_RESULT_UNKNOWN;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
EXPECT_EQ(2u, num_ready_handles);
EXPECT_TRUE((ready_handles[0] == p.handle0.get() &&
ready_handles[1] == p.handle1.get()) ||
@@ -112,7 +118,7 @@ TEST_F(WaitSetTest, Satisfied) {
// Wait on both again, but with only enough output space for one result.
num_ready_handles = 1;
ready_results[0] = MOJO_RESULT_UNKNOWN;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
ready_handles[0] == p.handle1.get());
@@ -123,7 +129,7 @@ TEST_F(WaitSetTest, Satisfied) {
num_ready_handles = 1;
ready_results[0] = MOJO_RESULT_UNKNOWN;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results, hss);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results, hss);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_TRUE(ready_handles[0] == p.handle0.get() ||
ready_handles[0] == p.handle1.get());
@@ -133,7 +139,7 @@ TEST_F(WaitSetTest, Satisfied) {
// The wait set should be empty now. Nothing to wait on.
num_ready_handles = 2;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
EXPECT_EQ(0u, num_ready_handles);
}
@@ -150,7 +156,7 @@ TEST_F(WaitSetTest, Unsatisfiable) {
MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
p.handle1.reset();
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(p.handle0.get(), ready_handles[0]);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, ready_results[0]);
@@ -175,7 +181,7 @@ TEST_F(WaitSetTest, CloseWhileWaiting) {
size_t num_ready_handles = 2;
Handle ready_handles[2];
MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(handle0_value, ready_handles[0]);
EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_results[0]);
@@ -203,20 +209,20 @@ TEST_F(WaitSetTest, CloseBeforeWaiting) {
size_t num_ready_handles = 1;
Handle ready_handle;
MojoResult ready_result = MOJO_RESULT_UNKNOWN;
- wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
+ wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
- wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
+ wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_TRUE(ready_handle == handle0_value || ready_handle == handle1_value);
EXPECT_EQ(MOJO_RESULT_CANCELLED, ready_result);
EXPECT_EQ(MOJO_RESULT_NOT_FOUND, wait_set.RemoveHandle(handle0_value));
// Nothing more to wait on.
- wait_set.Wait(&num_ready_handles, &ready_handle, &ready_result);
+ wait_set.Wait(nullptr, &num_ready_handles, &ready_handle, &ready_result);
EXPECT_EQ(0u, num_ready_handles);
}
@@ -233,7 +239,7 @@ TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
size_t num_ready_handles = 2;
Handle ready_handles[2];
MojoResult ready_results[2] = {MOJO_RESULT_UNKNOWN, MOJO_RESULT_UNKNOWN};
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(p.handle1.get(), ready_handles[0]);
EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
@@ -250,11 +256,121 @@ TEST_F(WaitSetTest, SatisfiedThenUnsatisfied) {
write_after_delay.Start();
num_ready_handles = 2;
- wait_set.Wait(&num_ready_handles, ready_handles, ready_results);
+ wait_set.Wait(nullptr, &num_ready_handles, ready_handles, ready_results);
EXPECT_EQ(1u, num_ready_handles);
EXPECT_EQ(p.handle0.get(), ready_handles[0]);
EXPECT_EQ(MOJO_RESULT_OK, ready_results[0]);
}
+TEST_F(WaitSetTest, EventOnly) {
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::SIGNALED);
+ WaitSet wait_set;
+ wait_set.AddEvent(&event);
+
+ base::WaitableEvent* ready_event = nullptr;
+ size_t num_ready_handles = 1;
+ Handle ready_handle;
+ MojoResult ready_result = MOJO_RESULT_UNKNOWN;
+ wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
+ EXPECT_EQ(0u, num_ready_handles);
+ EXPECT_EQ(&event, ready_event);
+}
+
+TEST_F(WaitSetTest, EventAndHandle) {
+ const char kTestMessage[] = "hello hello";
+
+ MessagePipe p;
+ WriteMessage(p.handle0, kTestMessage);
+
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+
+ WaitSet wait_set;
+ wait_set.AddHandle(p.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddEvent(&event);
+
+ base::WaitableEvent* ready_event = nullptr;
+ size_t num_ready_handles = 1;
+ Handle ready_handle;
+ MojoResult ready_result = MOJO_RESULT_UNKNOWN;
+ wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(nullptr, ready_event);
+ EXPECT_EQ(p.handle1.get(), ready_handle);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_result);
+
+ EXPECT_EQ(kTestMessage, ReadMessage(p.handle1));
+
+ ThreadedRunner signal_after_delay(base::Bind(
+ [](base::WaitableEvent* event) {
+ // Wait a little while, then close the handle.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+ event->Signal();
+ },
+ &event));
+ signal_after_delay.Start();
+
+ wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle, &ready_result);
+ EXPECT_EQ(0u, num_ready_handles);
+ EXPECT_EQ(&event, ready_event);
+}
+
+TEST_F(WaitSetTest, NoStarvation) {
+ const char kTestMessage[] = "wait for it";
+ const size_t kNumTestPipes = 50;
+ const size_t kNumTestEvents = 10;
+
+ // Create a bunch of handles and events which are always ready and add them
+ // to a shared WaitSet.
+
+ WaitSet wait_set;
+
+ MessagePipe pipes[kNumTestPipes];
+ for (size_t i = 0; i < kNumTestPipes; ++i) {
+ WriteMessage(pipes[i].handle0, kTestMessage);
+ Wait(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ WriteMessage(pipes[i].handle1, kTestMessage);
+ Wait(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+
+ wait_set.AddHandle(pipes[i].handle0.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ wait_set.AddHandle(pipes[i].handle1.get(), MOJO_HANDLE_SIGNAL_READABLE);
+ }
+
+ std::vector<std::unique_ptr<base::WaitableEvent>> events(kNumTestEvents);
+ for (auto& event_ptr : events) {
+ event_ptr = base::MakeUnique<base::WaitableEvent>(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ event_ptr->Signal();
+ wait_set.AddEvent(event_ptr.get());
+ }
+
+ // Now verify that all handle and event signals are deteceted within a finite
+ // number of consecutive Wait() calls. Do it a few times for good measure.
+ for (size_t i = 0; i < 3; ++i) {
+ std::set<base::WaitableEvent*> ready_events;
+ std::set<Handle> ready_handles;
+ while (ready_events.size() < kNumTestEvents ||
+ ready_handles.size() < kNumTestPipes * 2) {
+ base::WaitableEvent* ready_event = nullptr;
+ size_t num_ready_handles = 1;
+ Handle ready_handle;
+ MojoResult ready_result = MOJO_RESULT_UNKNOWN;
+ wait_set.Wait(&ready_event, &num_ready_handles, &ready_handle,
+ &ready_result);
+ if (ready_event)
+ ready_events.insert(ready_event);
+
+ if (num_ready_handles) {
+ EXPECT_EQ(1u, num_ready_handles);
+ EXPECT_EQ(MOJO_RESULT_OK, ready_result);
+ ready_handles.insert(ready_handle);
+ }
+ }
+ }
+}
+
} // namespace
} // namespace mojo
« no previous file with comments | « mojo/public/cpp/bindings/sync_handle_registry.h ('k') | mojo/public/cpp/system/wait_set.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698