diff options
author | rockot <rockot@chromium.org> | 2014-12-08 22:41:37 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-09 06:42:04 +0000 |
commit | fa648a32329c36eda94aeadac4aac14f3b8013be (patch) | |
tree | 29386b2d867a4bb482368a57b90ba809b4079c22 | |
parent | bf9d1f3cc8c6921e60de38d8c1a51dee74edcd76 (diff) | |
download | chromium_src-fa648a32329c36eda94aeadac4aac14f3b8013be.zip chromium_src-fa648a32329c36eda94aeadac4aac14f3b8013be.tar.gz chromium_src-fa648a32329c36eda94aeadac4aac14f3b8013be.tar.bz2 |
Update mojo sdk to rev f6c8ec07c01deebc13178d516225fd12695c3dc2
BUG=None
TBR=digit@chromium.org for ashmem dep
TBR=darin@chromium.org for toplevel
Review URL: https://codereview.chromium.org/782693004
Cr-Commit-Position: refs/heads/master@{#307427}
150 files changed, 3204 insertions, 2438 deletions
diff --git a/build/all.gyp b/build/all.gyp index 9c325fb..a1f751a 100644 --- a/build/all.gyp +++ b/build/all.gyp @@ -463,8 +463,10 @@ }], ['disable_nacl==0 and disable_nacl_untrusted==0', { 'dependencies': [ - '../mojo/mojo_nacl.gyp:*', - '../testing/gtest_nacl.gyp:*', + '../mojo/mojo_nacl.gyp:mojo_nacl', + '../mojo/mojo_nacl.gyp:monacl_codegen', + '../mojo/mojo_nacl.gyp:monacl_sel', + '../mojo/mojo_nacl.gyp:monacl_shell', ], }], ], diff --git a/mojo/cc/BUILD.gn b/mojo/cc/BUILD.gn index 1a78c01..113148d 100644 --- a/mojo/cc/BUILD.gn +++ b/mojo/cc/BUILD.gn @@ -8,11 +8,15 @@ source_set("cc") { "//base", "//cc", "//cc/surfaces", - "//skia", + "//cc/surfaces:surface_id", "//gpu/command_buffer/client:gles2_implementation", + "//gpu/command_buffer/client:gles2_interface", "//mojo/converters/surfaces", - "//mojo/public/gles2:for_shared_library", + "//mojo/public/c/gles2", + "//mojo/public/cpp/environment", + "//mojo/public/cpp/system", "//mojo/services/public/interfaces/surfaces", + "//skia", ] sources = [ diff --git a/mojo/edk/DEPS b/mojo/edk/DEPS index 5fe1410..9a51b60 100644 --- a/mojo/edk/DEPS +++ b/mojo/edk/DEPS @@ -2,4 +2,6 @@ include_rules = [ "-mojo", "+mojo/edk", "+mojo/public", + + "+third_party/ashmem", ] diff --git a/mojo/edk/embedder/BUILD.gn b/mojo/edk/embedder/BUILD.gn index 5271e66..3d808d8 100644 --- a/mojo/edk/embedder/BUILD.gn +++ b/mojo/edk/embedder/BUILD.gn @@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("embedder") { +import("../mojo_edk.gni") + +mojo_edk_source_set("embedder") { # This isn't really a standalone target; it must be linked into the # mojo_system_impl component. - visibility = [ "//mojo/edk/system" ] + mojo_edk_visibility = [ "mojo/edk/system" ] sources = [ "channel_info_forward.h", @@ -30,11 +32,14 @@ source_set("embedder") { "MOJO_SYSTEM_IMPLEMENTATION", ] - configs += [ "//mojo/edk/system:system_config" ] + mojo_edk_configs = [ "mojo/edk/system:system_config" ] public_deps = [ ":platform", - "//mojo/public/cpp/system", + ] + + mojo_sdk_public_deps = [ + "mojo/public/cpp/system", ] deps = [ @@ -42,12 +47,15 @@ source_set("embedder") { ] } -source_set("platform") { +mojo_edk_source_set("platform") { # This isn't really a standalone target; it must be linked into the # mojo_system_impl component. visibility = [ ":embedder", - "//mojo/edk/system", + ] + + mojo_edk_visibility = [ + "mojo/edk/system", ] sources = [ @@ -68,6 +76,7 @@ source_set("platform") { "scoped_platform_handle.h", "simple_platform_shared_buffer.cc", "simple_platform_shared_buffer.h", + "simple_platform_shared_buffer_android.cc", "simple_platform_shared_buffer_posix.cc", "simple_platform_shared_buffer_win.cc", "simple_platform_support.cc", @@ -76,16 +85,16 @@ source_set("platform") { defines = [ "MOJO_SYSTEM_IMPL_IMPLEMENTATION" ] - configs += [ "//mojo/edk/system:system_config" ] + mojo_edk_configs = [ "mojo/edk/system:system_config" ] deps = [ "//base", ] } -source_set("embedder_unittests") { +mojo_edk_source_set("embedder_unittests") { testonly = true - visibility = [ "//mojo/edk/system:mojo_system_unittests" ] + mojo_edk_visibility = [ "mojo/edk/system:mojo_system_unittests" ] sources = [ "embedder_unittest.cc", @@ -96,8 +105,12 @@ source_set("embedder_unittests") { deps = [ "//base", "//base/test:test_support", - "//mojo/edk/test:test_support", - "//mojo/edk/system", "//testing/gtest", ] + + mojo_edk_deps = [ + "mojo/edk/test:test_support", + "mojo/edk/system", + "mojo/edk/system:test_utils", + ] } diff --git a/mojo/edk/embedder/channel_init.cc b/mojo/edk/embedder/channel_init.cc index 0e7a7b6..9a0bfce 100644 --- a/mojo/edk/embedder/channel_init.cc +++ b/mojo/edk/embedder/channel_init.cc @@ -22,7 +22,7 @@ ChannelInit::~ChannelInit() { ScopedMessagePipeHandle ChannelInit::Init( base::PlatformFile file, scoped_refptr<base::TaskRunner> io_thread_task_runner) { - DCHECK(!io_thread_task_runner_.get()); // Should only init once. + DCHECK(!io_thread_task_runner_); // Should only init once. io_thread_task_runner_ = io_thread_task_runner; ScopedMessagePipeHandle message_pipe = CreateChannel( diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 9c73eb0..d538810 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -62,7 +62,7 @@ void CreateChannelHelper( MakeChannel(platform_handle.Pass(), channel_endpoint); // Hand the channel back to the embedder. - if (callback_thread_task_runner.get()) { + if (callback_thread_task_runner) { callback_thread_task_runner->PostTask( FROM_HERE, base::Bind(callback, channel_info.release())); } else { @@ -118,7 +118,7 @@ ScopedMessagePipeHandle CreateChannel( DidCreateChannelCallback callback, scoped_refptr<base::TaskRunner> callback_thread_task_runner) { DCHECK(platform_handle.is_valid()); - DCHECK(io_thread_task_runner.get()); + DCHECK(io_thread_task_runner); DCHECK(!callback.is_null()); scoped_refptr<system::ChannelEndpoint> channel_endpoint; @@ -195,7 +195,7 @@ MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, DCHECK(internal::g_core); scoped_refptr<system::Dispatcher> dispatcher( internal::g_core->GetDispatcher(platform_handle_wrapper_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; if (dispatcher->GetType() != system::Dispatcher::kTypePlatformHandle) diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index b138a2d..0393748 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc @@ -24,6 +24,13 @@ namespace mojo { namespace embedder { namespace { +const MojoHandleSignals kSignalReadadableWritable = + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; + +const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | + MOJO_HANDLE_SIGNAL_WRITABLE | + MOJO_HANDLE_SIGNAL_PEER_CLOSED; + class ScopedTestChannel { public: // Creates a channel that lives on a given I/O thread (determined by the given @@ -123,8 +130,12 @@ TEST_F(EmbedderTest, ChannelsBasic) { 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); // Now wait for the other side to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + MojoHandleSignalsState state; + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); char buffer[1000] = {}; uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); @@ -188,8 +199,12 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); // Wait for |client_mp| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + MojoHandleSignalsState state; + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Read a message from |client_mp|. char buffer[1000] = {}; @@ -206,8 +221,10 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { h1 = handles[0]; // Wait for |h1| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(h1, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Read a message from |h1|. memset(buffer, 0, sizeof(buffer)); @@ -222,8 +239,10 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { EXPECT_EQ(0u, num_handles); // Wait for |h1| to become readable (again). - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(h1, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Read the second message from |h1|. memset(buffer, 0, sizeof(buffer)); @@ -242,8 +261,10 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); // Wait for |h0| to become readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(h0, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Read a message from |h0|. memset(buffer, 0, sizeof(buffer)); @@ -282,6 +303,7 @@ TEST_F(EmbedderTest, ChannelsHandlePassing) { // 10. (close) // 11. (wait/cl.) // 12. (wait/cl.) + #if defined(OS_ANDROID) // Android multi-process tests are not executing the new process. This is flaky. #define MAYBE_MultiprocessChannels DISABLED_MultiprocessChannels @@ -313,8 +335,13 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { // |server_mp|), we die with a fatal error in |Channel::HandleLocalError()|. // 2. Read a message from |server_mp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + MojoHandleSignalsState state; + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); + char buffer[1000] = {}; uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, @@ -346,8 +373,11 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); // 9. Read a message from |mp0|, which should have |mp2| attached. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp0, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(mp0, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); + memset(buffer, 0, sizeof(buffer)); num_bytes = static_cast<uint32_t>(sizeof(buffer)); MojoHandle mp2 = MOJO_HANDLE_INVALID; @@ -362,8 +392,13 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { EXPECT_NE(mp2, MOJO_HANDLE_INVALID); // 7. Read a message from |mp2|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfiable_signals); + memset(buffer, 0, sizeof(buffer)); num_bytes = static_cast<uint32_t>(sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, @@ -380,8 +415,11 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessChannels) { // TODO(vtl): crbug.com/351768 #if 0 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + MojoNewWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, + &state)); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfiable_signals); #endif EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); } @@ -407,8 +445,13 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { CHECK(client_channel.channel_info() != nullptr); // 1. Read the first message from |client_mp|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + MojoHandleSignalsState state; + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); + char buffer[1000] = {}; uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, @@ -426,8 +469,15 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); // 4. Read a message from |client_mp|, which should have |mp1| attached. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + // The other end of the handle may or may not be closed at this point, so we + // can't test MOJO_HANDLE_SIGNAL_WRITABLE or MOJO_HANDLE_SIGNAL_PEER_CLOSED. + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, + state.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, + state.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE); // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd // die (again due to |Channel::HandleLocalError()|). memset(buffer, 0, sizeof(buffer)); @@ -470,8 +520,11 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { mp2 = MOJO_HANDLE_INVALID; // 3. Read a message from |mp1|. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoNewWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(kSignalReadadableWritable, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); + memset(buffer, 0, sizeof(buffer)); num_bytes = static_cast<uint32_t>(sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_OK, @@ -482,9 +535,11 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { EXPECT_STREQ(kFoo, buffer); // 11. Wait on |mp1| (which should eventually fail) and then close it. - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, + MojoNewWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); } diff --git a/mojo/edk/embedder/entrypoints.cc b/mojo/edk/embedder/entrypoints.cc index 7b2e53f..6ecdd14 100644 --- a/mojo/edk/embedder/entrypoints.cc +++ b/mojo/edk/embedder/entrypoints.cc @@ -41,6 +41,25 @@ MojoResult MojoWaitMany(const MojoHandle* handles, : result; } +MojoResult MojoNewWait(MojoHandle handle, + MojoHandleSignals signals, + MojoDeadline deadline, + MojoHandleSignalsState* signals_state) { + return g_core->Wait(handle, signals, deadline, + MakeUserPointer(signals_state)); +} + +MojoResult MojoNewWaitMany(const MojoHandle* handles, + const MojoHandleSignals* signals, + uint32_t num_handles, + MojoDeadline deadline, + uint32_t* result_index, + MojoHandleSignalsState* signals_states) { + return g_core->WaitMany(MakeUserPointer(handles), MakeUserPointer(signals), + num_handles, deadline, MakeUserPointer(result_index), + MakeUserPointer(signals_states)); +} + MojoResult MojoCreateMessagePipe(const MojoCreateMessagePipeOptions* options, MojoHandle* message_pipe_handle0, MojoHandle* message_pipe_handle1) { diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_android.cc b/mojo/edk/embedder/simple_platform_shared_buffer_android.cc new file mode 100644 index 0000000..3517db3 --- /dev/null +++ b/mojo/edk/embedder/simple_platform_shared_buffer_android.cc @@ -0,0 +1,74 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/embedder/simple_platform_shared_buffer.h" + +#include <stdint.h> +#include <sys/mman.h> // For |mmap()|/|munmap()|. +#include <sys/types.h> // For |off_t|. +#include <unistd.h> + +#include <limits> + +#include "base/files/scoped_file.h" +#include "base/logging.h" +#include "base/macros.h" +#include "mojo/edk/embedder/platform_handle.h" +#include "third_party/ashmem/ashmem.h" + +namespace mojo { +namespace embedder { + +// SimplePlatformSharedBuffer -------------------------------------------------- + +bool SimplePlatformSharedBuffer::Init() { + DCHECK(!handle_.is_valid()); + + if (static_cast<uint64_t>(num_bytes_) > + static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { + return false; + } + + base::ScopedFD fd(ashmem_create_region(nullptr, num_bytes_)); + if (!fd.is_valid()) { + DPLOG(ERROR) << "ashmem_create_region()"; + return false; + } + + if (ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE) < 0) { + DPLOG(ERROR) << "ashmem_set_prot_region()"; + return false; + } + + handle_.reset(PlatformHandle(fd.release())); + return true; +} + +bool SimplePlatformSharedBuffer::InitFromPlatformHandle( + ScopedPlatformHandle platform_handle) { + DCHECK(!handle_.is_valid()); + + if (static_cast<uint64_t>(num_bytes_) > + static_cast<uint64_t>(std::numeric_limits<off_t>::max())) { + return false; + } + + int size = ashmem_get_size_region(platform_handle.get().fd); + + if (size < 0) { + DPLOG(ERROR) << "ashmem_get_size_region()"; + return false; + } + + if (static_cast<size_t>(size) != num_bytes_) { + LOG(ERROR) << "Shared memory region has the wrong size"; + return false; + } + + handle_ = platform_handle.Pass(); + return true; +} + +} // namespace embedder +} // namespace mojo diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc b/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc index 8dfcf44..a3d10ef 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_posix.cc @@ -33,6 +33,10 @@ namespace embedder { // SimplePlatformSharedBuffer -------------------------------------------------- +// The implementation for android uses ashmem to generate the file descriptor +// for the shared memory. See simple_platform_shared_buffer_android.cc +#if !defined(OS_ANDROID) + bool SimplePlatformSharedBuffer::Init() { DCHECK(!handle_.is_valid()); @@ -115,6 +119,8 @@ bool SimplePlatformSharedBuffer::InitFromPlatformHandle( return true; } +#endif // !defined(OS_ANDROID) + scoped_ptr<PlatformSharedBufferMapping> SimplePlatformSharedBuffer::MapImpl( size_t offset, size_t length) { diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc index 45d27b9..4644b7b 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc @@ -24,7 +24,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) { // Make some memory. scoped_refptr<SimplePlatformSharedBuffer> buffer( SimplePlatformSharedBuffer::Create(kNumBytes)); - ASSERT_TRUE(buffer.get()); + ASSERT_TRUE(buffer); // Map it all, scribble some stuff, and then unmap it. { @@ -100,7 +100,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) { TEST(SimplePlatformSharedBufferTest, InvalidMappings) { scoped_refptr<SimplePlatformSharedBuffer> buffer( SimplePlatformSharedBuffer::Create(100)); - ASSERT_TRUE(buffer.get()); + ASSERT_TRUE(buffer); // Zero length not allowed. EXPECT_FALSE(buffer->Map(0, 0)); @@ -133,7 +133,7 @@ TEST(SimplePlatformSharedBufferTest, TooBig) { SimplePlatformSharedBuffer::Create(kMaxSizeT)); // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should // always fail. - if (buffer.get()) + if (buffer) EXPECT_FALSE(buffer->Map(0, kMaxSizeT)); } diff --git a/mojo/edk/js/BUILD.gn b/mojo/edk/js/BUILD.gn index 5a7e3d5..9a066d3 100644 --- a/mojo/edk/js/BUILD.gn +++ b/mojo/edk/js/BUILD.gn @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("js") { +import("../mojo_edk.gni") + +mojo_edk_source_set("js") { sources = [ "core.cc", "core.h", @@ -27,22 +29,28 @@ source_set("js") { "//v8", ] - deps = [ - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", + mojo_sdk_deps = [ + "mojo/public/cpp/environment", + "mojo/public/cpp/system", ] } -source_set("js_unittests") { +mojo_edk_source_set("js_unittests") { testonly = true sources = [ "handle_unittest.cc", ] deps = [ - "//mojo/edk/js", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/system", "//testing/gtest", ] + + mojo_edk_deps = [ + "mojo/edk/js", + "mojo/edk/test:test_support", + ] + + mojo_sdk_deps = [ + "mojo/public/cpp/system", + ] } diff --git a/mojo/edk/js/test/BUILD.gn b/mojo/edk/js/test/BUILD.gn index be3a641..6e9792c 100644 --- a/mojo/edk/js/test/BUILD.gn +++ b/mojo/edk/js/test/BUILD.gn @@ -4,17 +4,17 @@ test("js_unittests") { deps = [ + "../../js", + "../../js:js_unittests", + "../../test:run_all_unittests", + "../../test:test_support", + "../../../environment:chromium", + "../../../public/cpp/environment", + "../../../public/cpp/system", + "../../../public/cpp/utility", + "../../../public/interfaces/bindings/tests:test_interfaces", "//base", "//gin:gin_test", - "//mojo/edk/js", - "//mojo/edk/js:js_unittests", - "//mojo/edk/test:run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", - "//mojo/public/cpp/utility", - "//mojo/environment:chromium", - "//mojo/public/interfaces/bindings/tests:test_interfaces", ] sources = [ @@ -24,15 +24,15 @@ test("js_unittests") { test("js_integration_tests") { deps = [ + "../../js", + "../../js/tests:js_to_cpp_tests", + "../../test:run_all_unittests", + "../../test:test_support", + "../../../environment:chromium", + "../../../public/cpp/bindings", + "../../../public/interfaces/bindings/tests:test_interfaces", "//base", "//gin:gin_test", - "//mojo/edk/js", - "//mojo/edk/js/tests:js_to_cpp_tests", - "//mojo/edk/test:run_all_unittests", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings", - "//mojo/environment:chromium", - "//mojo/public/interfaces/bindings/tests:test_interfaces", ] sources = [ diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn index c7f568b..c9711c7 100644 --- a/mojo/edk/js/tests/BUILD.gn +++ b/mojo/edk/js/tests/BUILD.gn @@ -2,19 +2,26 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/tools/bindings/mojom.gni") +import("../../mojo_edk.gni") +import("../../../public/tools/bindings/mojom.gni") -source_set("js_to_cpp_tests") { +mojo_edk_source_set("js_to_cpp_tests") { testonly = true deps = [ ":js_to_cpp_bindings", "//gin:gin_test", - "//mojo/edk/js", - "//mojo/edk/test:test_support", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/bindings/tests:test_interfaces", + ] + + mojo_edk_deps = [ + "mojo/edk/js", + "mojo/edk/test:test_support", + ] + + mojo_sdk_deps = [ + "mojo/public/cpp/bindings", + "mojo/public/cpp/system", + "mojo/public/interfaces/bindings/tests:test_interfaces", ] sources = [ diff --git a/mojo/edk/js/tests/connection_tests.js b/mojo/edk/js/tests/connection_tests.js index 6649dfe..17009d9 100644 --- a/mojo/edk/js/tests/connection_tests.js +++ b/mojo/edk/js/tests/connection_tests.js @@ -81,14 +81,20 @@ define([ threading.quit(); }.bind(this)); + function createPeerConnection(handle, stubClass, proxyClass) { + var c = new connection.Connection(handle, stubClass, proxyClass); + c.local.peer = c.remote; + c.remote.peer = c.local; + return c; + } + function testClientServer() { var receivedFrobinate = false; var receivedDidFrobinate = false; // ServiceImpl ------------------------------------------------------------ - function ServiceImpl(peer) { - this.peer = peer; + function ServiceImpl() { } ServiceImpl.prototype = Object.create( @@ -106,8 +112,7 @@ define([ // ServiceClientImpl ------------------------------------------------------ - function ServiceClientImpl(peer) { - this.peer = peer; + function ServiceClientImpl() { } ServiceClientImpl.prototype = @@ -123,10 +128,10 @@ define([ var anotherPipe = core.createMessagePipe(); var sourcePipe = core.createMessagePipe(); - var connection0 = new connection.Connection( + var connection0 = createPeerConnection( pipe.handle0, ServiceImpl, sample_service.ServiceClient.proxyClass); - var connection1 = new connection.Connection( + var connection1 = createPeerConnection( pipe.handle1, ServiceClientImpl, sample_service.Service.proxyClass); var foo = new sample_service.Foo(); @@ -163,7 +168,7 @@ define([ function testWriteToClosedPipe() { var pipe = core.createMessagePipe(); - var connection1 = new connection.Connection( + var connection1 = createPeerConnection( pipe.handle1, function() {}, sample_service.Service.proxyClass); // Close the other end of the pipe. @@ -192,8 +197,7 @@ define([ // ProviderImpl ------------------------------------------------------------ - function ProviderImpl(peer) { - this.peer = peer; + function ProviderImpl() { } ProviderImpl.prototype = @@ -211,8 +215,7 @@ define([ // ProviderClientImpl ------------------------------------------------------ - function ProviderClientImpl(peer) { - this.peer = peer; + function ProviderClientImpl() { } ProviderClientImpl.prototype = @@ -220,12 +223,12 @@ define([ var pipe = core.createMessagePipe(); - var connection0 = new connection.Connection( + var connection0 = createPeerConnection( pipe.handle0, ProviderImpl, sample_interfaces.ProviderClient.proxyClass); - var connection1 = new connection.Connection( + var connection1 = createPeerConnection( pipe.handle1, ProviderClientImpl, sample_interfaces.Provider.proxyClass); diff --git a/mojo/edk/js/tests/js_to_cpp_tests.js b/mojo/edk/js/tests/js_to_cpp_tests.js index c32f0af..140ad4c 100644 --- a/mojo/edk/js/tests/js_to_cpp_tests.js +++ b/mojo/edk/js/tests/js_to_cpp_tests.js @@ -19,9 +19,7 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [ capacityNumBytes: 64 }; - function JsSideConnection(cppSide) { - this.cppSide_ = cppSide; - cppSide.startTest(); + function JsSideConnection() { } JsSideConnection.prototype = @@ -205,6 +203,12 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [ }, null); } + function createCppSideConnection(handle, stubClass, proxyClass) { + var c = new connection.Connection(handle, stubClass, proxyClass); + c.local.cppSide_ = c.remote; + return c; + } + return function(handle) { var i; sampleData = new Uint8Array(DATA_PIPE_PARAMS.capacityNumBytes); @@ -215,7 +219,8 @@ define('mojo/edk/js/tests/js_to_cpp_tests', [ for (i = 0; i < sampleMessage.length; ++i) { sampleMessage[i] = 255 - i; } - retainedConnection = new connection.Connection(handle, JsSideConnection, - jsToCpp.CppSide.proxyClass); + retainedConnection = createCppSideConnection( + handle, JsSideConnection,jsToCpp.CppSide.proxyClass); + retainedConnection.remote.startTest(); }; }); diff --git a/mojo/edk/mojo_edk.gni b/mojo/edk/mojo_edk.gni new file mode 100644 index 0000000..34b82d4 --- /dev/null +++ b/mojo/edk/mojo_edk.gni @@ -0,0 +1,96 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../public/mojo_sdk.gni") + +# A mojo_edk_source_set is a mojo_sdk_source_set that does not restrict +# external dependencies and understands the following additional variables, all +# of which admit a list of the relevant elements specified relative to the +# location of the Mojo EDK: +# mojo_edk_configs +# allow_circular_mojo_edk_includes_from +# mojo_edk_public_deps +# mojo_edk_deps + +# Note that it is assumed that the Mojo EDK is a sibling of the Mojo SDK in a +# client repo; the distinctions made above are for the sake of clarity in +# writing targets. +template("mojo_edk_source_set") { + mojo_sdk_source_set(target_name) { + restrict_external_deps = false + + if (defined(invoker.visibility)) { + visibility = invoker.visibility + } + if (defined(invoker.mojo_edk_visibility)) { + mojo_sdk_visibility = invoker.mojo_edk_visibility + } + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + if (defined(invoker.sources)) { + sources = invoker.sources + } + if (defined(invoker.defines)) { + defines = invoker.defines + } + if (defined(invoker.public_configs)) { + public_configs = invoker.public_configs + } + + configs = [] + if (defined(invoker.configs)) { + configs = invoker.configs + } + if (defined(invoker.mojo_edk_configs)) { + foreach(edk_config, invoker.mojo_edk_configs) { + # Check that the EDK config was not mistakenly given as an absolute + # path. + assert(get_path_info(edk_config, "abspath") != edk_config) + configs += [ rebase_path(edk_config, ".", mojo_root) ] + } + } + + allow_circular_includes_from = [] + if (defined(invoker.allow_circular_includes_from)) { + allow_circular_includes_from += invoker.allow_circular_includes_from + } + if (defined(invoker.allow_circular_mojo_edk_includes_from)) { + foreach(edk_target, invoker.allow_circular_mojo_edk_includes_from) { + # Check that the EDK target was not mistakenly given as an absolute + # path. + assert(get_path_info(edk_target, "abspath") != edk_target) + allow_circular_includes_from += [ + rebase_path(edk_target, ".", mojo_root) + ] + } + } + + if (defined(invoker.public_deps)) { + public_deps = invoker.public_deps + } + mojo_sdk_public_deps = [] + if (defined(invoker.mojo_edk_public_deps)) { + # The EDK is required to be a sibling of the SDK, so the relative + # dependencies are rewritten in the same way. + mojo_sdk_public_deps = invoker.mojo_edk_public_deps + } + if (defined(invoker.mojo_sdk_public_deps)) { + mojo_sdk_public_deps += invoker.mojo_sdk_public_deps + } + + if (defined(invoker.deps)) { + deps = invoker.deps + } + mojo_sdk_deps = [] + if (defined(invoker.mojo_edk_deps)) { + # The EDK is required to be a sibling of the SDK, so the relative + # dependencies are rewritten in the same way. + mojo_sdk_deps = invoker.mojo_edk_deps + } + if (defined(invoker.mojo_sdk_deps)) { + mojo_sdk_deps += invoker.mojo_sdk_deps + } + } +} diff --git a/mojo/edk/mojo_edk_system_impl.gypi b/mojo/edk/mojo_edk_system_impl.gypi index a0af387..bab747b 100644 --- a/mojo/edk/mojo_edk_system_impl.gypi +++ b/mojo/edk/mojo_edk_system_impl.gypi @@ -37,10 +37,14 @@ 'embedder/scoped_platform_handle.h', 'embedder/simple_platform_shared_buffer.cc', 'embedder/simple_platform_shared_buffer.h', + 'embedder/simple_platform_shared_buffer_android.cc', 'embedder/simple_platform_shared_buffer_posix.cc', 'embedder/simple_platform_shared_buffer_win.cc', 'embedder/simple_platform_support.cc', 'embedder/simple_platform_support.h', + 'system/awakable.h', + 'system/awakable_list.cc', + 'system/awakable_list.h', 'system/channel.cc', 'system/channel.h', 'system/channel_endpoint.cc', @@ -64,6 +68,8 @@ 'system/data_pipe_producer_dispatcher.h', 'system/dispatcher.cc', 'system/dispatcher.h', + 'system/endpoint_relayer.cc', + 'system/endpoint_relayer.h', 'system/handle_signals_state.h', 'system/handle_table.cc', 'system/handle_table.h', @@ -102,8 +108,6 @@ 'system/transport_data.h', 'system/waiter.cc', 'system/waiter.h', - 'system/waiter_list.cc', - 'system/waiter_list.h', # Test-only code: # TODO(vtl): It's a little unfortunate that these end up in the same # component as non-test-only code. In the static build, this code @@ -115,4 +119,11 @@ # Ensures that dependent projects import the core functions on Windows. 'defines': ['MOJO_USE_SYSTEM_IMPL'], }, + 'conditions': [ + ['OS=="android"', { + "dependencies": [ + "<(DEPTH)/third_party/ashmem/ashmem.gyp:ashmem", + ], + }], + ], } diff --git a/mojo/edk/mojo_edk_tests.gyp b/mojo/edk/mojo_edk_tests.gyp index b877967..a571069 100644 --- a/mojo/edk/mojo_edk_tests.gyp +++ b/mojo/edk/mojo_edk_tests.gyp @@ -168,6 +168,7 @@ 'embedder/embedder_unittest.cc', 'embedder/platform_channel_pair_posix_unittest.cc', 'embedder/simple_platform_shared_buffer_unittest.cc', + 'system/awakable_list_unittest.cc', 'system/channel_endpoint_id_unittest.cc', 'system/channel_manager_unittest.cc', 'system/channel_unittest.cc', @@ -192,7 +193,6 @@ 'system/simple_dispatcher_unittest.cc', 'system/test_utils.cc', 'system/test_utils.h', - 'system/waiter_list_unittest.cc', 'system/waiter_test_utils.cc', 'system/waiter_test_utils.h', 'system/waiter_unittest.cc', diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn index 8cc8905..8d24a08 100644 --- a/mojo/edk/system/BUILD.gn +++ b/mojo/edk/system/BUILD.gn @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../mojo_edk.gni") + if (is_android) { import("//build/config/android/config.gni") import("//build/config/android/rules.gni") @@ -18,6 +20,9 @@ component("system") { output_name = "mojo_system_impl" sources = [ + "awakable.h", + "awakable_list.cc", + "awakable_list.h", "channel.cc", "channel.h", "channel_endpoint.cc", @@ -41,6 +46,8 @@ component("system") { "data_pipe_producer_dispatcher.h", "dispatcher.cc", "dispatcher.h", + "endpoint_relayer.cc", + "endpoint_relayer.h", "handle_signals_state.h", "handle_table.cc", "handle_table.h", @@ -79,8 +86,6 @@ component("system") { "transport_data.h", "waiter.cc", "waiter.h", - "waiter_list.cc", - "waiter_list.h", ] defines = [ @@ -91,9 +96,9 @@ component("system") { all_dependent_configs = [ ":system_config" ] public_deps = [ - "//mojo/edk/embedder", - "//mojo/edk/embedder:platform", - "//mojo/public/c/system", + "../embedder", + "../embedder:platform", + "../../public/c/system", ] deps = [ @@ -101,13 +106,28 @@ component("system") { "//base/third_party/dynamic_annotations", ] - allow_circular_includes_from = [ "//mojo/edk/embedder" ] + allow_circular_includes_from = [ "../embedder" ] +} + +mojo_edk_source_set("test_utils") { + testonly = true + + sources = [ + "test_utils.cc", + "test_utils.h", + ] + + deps = [ + "//base", + "//base/test:test_support", + ] } # GYP version: mojo/edk/mojo_edk.gyp:mojo_system_unittests test("mojo_system_unittests") { sources = [ "../test/multiprocess_test_helper_unittest.cc", + "awakable_list_unittest.cc", "channel_endpoint_id_unittest.cc", "channel_manager_unittest.cc", "channel_unittest.cc", @@ -130,11 +150,6 @@ test("mojo_system_unittests") { "run_all_unittests.cc", "shared_buffer_dispatcher_unittest.cc", "simple_dispatcher_unittest.cc", - - # TODO(vtl): Factor test_utils.* into their own source set. - "test_utils.cc", - "test_utils.h", - "waiter_list_unittest.cc", "waiter_test_utils.cc", "waiter_test_utils.h", "waiter_unittest.cc", @@ -142,10 +157,11 @@ test("mojo_system_unittests") { deps = [ ":system", + ":test_utils", + "../embedder:embedder_unittests", + "../test:test_support", "//base", "//base/test:test_support", - "//mojo/edk/embedder:embedder_unittests", - "//mojo/edk/test:test_support", "//testing/gtest", ] @@ -153,7 +169,7 @@ test("mojo_system_unittests") { deps += [ "//testing/android:native_test_native_code" ] } - allow_circular_includes_from = [ "//mojo/edk/embedder:embedder_unittests" ] + allow_circular_includes_from = [ "../embedder:embedder_unittests" ] } # GYP version: mojo/edk/mojo_edk.gyp:mojo_message_pipe_perftests @@ -162,16 +178,15 @@ test("mojo_message_pipe_perftests") { "message_pipe_perftest.cc", "message_pipe_test_utils.h", "message_pipe_test_utils.cc", - "test_utils.cc", - "test_utils.h", ] deps = [ ":system", + ":test_utils", + "../test:test_support", "//base", "//base/test:test_support", "//base/test:test_support_perf", - "//mojo/edk/test:test_support", "//testing/gtest", ] } diff --git a/mojo/edk/system/awakable.h b/mojo/edk/system/awakable.h new file mode 100644 index 0000000..5479912 --- /dev/null +++ b/mojo/edk/system/awakable.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_AWAKABLE_H_ +#define MOJO_EDK_SYSTEM_AWAKABLE_H_ + +#include <stdint.h> + +#include "mojo/edk/system/system_impl_export.h" +#include "mojo/public/c/system/types.h" + +namespace mojo { +namespace system { + +// An interface that may be waited on |AwakableList|. +class MOJO_SYSTEM_IMPL_EXPORT Awakable { + public: + // |Awake()| must satisfy the following contract: + // * As this is called from any thread, this must be thread-safe. + // * As this is called inside a lock, this must not call anything that takes + // "non-terminal" locks, i.e., those which are always safe to take. + virtual void Awake(MojoResult result, uintptr_t context) = 0; + + protected: + Awakable() {} +}; + +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_AWAKABLE_H_ diff --git a/mojo/edk/system/awakable_list.cc b/mojo/edk/system/awakable_list.cc new file mode 100644 index 0000000..6af305b --- /dev/null +++ b/mojo/edk/system/awakable_list.cc @@ -0,0 +1,58 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/awakable_list.h" + +#include "base/logging.h" +#include "mojo/edk/system/awakable.h" +#include "mojo/edk/system/handle_signals_state.h" + +namespace mojo { +namespace system { + +AwakableList::AwakableList() { +} + +AwakableList::~AwakableList() { + DCHECK(awakables_.empty()); +} + +void AwakableList::AwakeForStateChange(const HandleSignalsState& state) { + for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end(); + ++it) { + if (state.satisfies(it->signals)) + it->awakable->Awake(MOJO_RESULT_OK, it->context); + else if (!state.can_satisfy(it->signals)) + it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context); + } +} + +void AwakableList::CancelAll() { + for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end(); + ++it) { + it->awakable->Awake(MOJO_RESULT_CANCELLED, it->context); + } + awakables_.clear(); +} + +void AwakableList::Add(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context) { + awakables_.push_back(AwakeInfo(awakable, signals, context)); +} + +void AwakableList::Remove(Awakable* awakable) { + // We allow a thread to wait on the same handle multiple times simultaneously, + // so we need to scan the entire list and remove all occurrences of |waiter|. + for (AwakeInfoList::iterator it = awakables_.begin(); + it != awakables_.end();) { + AwakeInfoList::iterator maybe_delete = it; + ++it; + if (maybe_delete->awakable == awakable) + awakables_.erase(maybe_delete); + } +} + +} // namespace system +} // namespace mojo diff --git a/mojo/edk/system/awakable_list.h b/mojo/edk/system/awakable_list.h new file mode 100644 index 0000000..19c03c8 --- /dev/null +++ b/mojo/edk/system/awakable_list.h @@ -0,0 +1,58 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ +#define MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ + +#include <stdint.h> + +#include <list> + +#include "base/macros.h" +#include "mojo/edk/system/system_impl_export.h" +#include "mojo/public/c/system/types.h" + +namespace mojo { +namespace system { + +class Awakable; +struct HandleSignalsState; + +// |AwakableList| tracks all the |Waiter|s that are waiting on a given +// handle/|Dispatcher|. There should be a |AwakableList| for each handle that +// can be waited on (in any way). In the simple case, the |AwakableList| is +// owned by the |Dispatcher|, whereas in more complex cases it is owned by the +// secondary object (see simple_dispatcher.* and the explanatory comment in +// core.cc). This class is thread-unsafe (all concurrent access must be +// protected by some lock). +class MOJO_SYSTEM_IMPL_EXPORT AwakableList { + public: + AwakableList(); + ~AwakableList(); + + void AwakeForStateChange(const HandleSignalsState& state); + void CancelAll(); + void Add(Awakable* awakable, MojoHandleSignals signals, uint32_t context); + void Remove(Awakable* awakable); + + private: + struct AwakeInfo { + AwakeInfo(Awakable* awakable, MojoHandleSignals signals, uint32_t context) + : awakable(awakable), signals(signals), context(context) {} + + Awakable* awakable; + MojoHandleSignals signals; + uint32_t context; + }; + typedef std::list<AwakeInfo> AwakeInfoList; + + AwakeInfoList awakables_; + + DISALLOW_COPY_AND_ASSIGN(AwakableList); +}; + +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_AWAKABLE_LIST_H_ diff --git a/mojo/edk/system/waiter_list_unittest.cc b/mojo/edk/system/awakable_list_unittest.cc index 129df71..201b751 100644 --- a/mojo/edk/system/waiter_list_unittest.cc +++ b/mojo/edk/system/awakable_list_unittest.cc @@ -7,7 +7,7 @@ // increase tolerance and reduce observed flakiness (though doing so reduces the // meaningfulness of the test). -#include "mojo/edk/system/waiter_list.h" +#include "mojo/edk/system/awakable_list.h" #include "base/threading/platform_thread.h" // For |Sleep()|. #include "base/time/time.h" @@ -21,29 +21,29 @@ namespace mojo { namespace system { namespace { -TEST(WaiterListTest, BasicCancel) { +TEST(AwakableListTest, BasicCancel) { MojoResult result; uint32_t context; // Cancel immediately after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); thread.Start(); - waiter_list.CancelAllWaiters(); + awakable_list.CancelAll(); // Double-remove okay: - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_CANCELLED, result); EXPECT_EQ(1u, context); // Cancel before after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - waiter_list.CancelAllWaiters(); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); + awakable_list.CancelAll(); thread.Start(); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_CANCELLED, result); @@ -51,46 +51,46 @@ TEST(WaiterListTest, BasicCancel) { // Cancel some time after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); thread.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.CancelAllWaiters(); + awakable_list.CancelAll(); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_CANCELLED, result); EXPECT_EQ(3u, context); } -TEST(WaiterListTest, BasicAwakeSatisfied) { +TEST(AwakableListTest, BasicAwakeSatisfied) { MojoResult result; uint32_t context; // Awake immediately after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); thread.Start(); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_OK, result); EXPECT_EQ(1u, context); // Awake before after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); // Double-remove okay: - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); thread.Start(); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_OK, result); @@ -98,45 +98,45 @@ TEST(WaiterListTest, BasicAwakeSatisfied) { // Awake some time after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); thread.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_OK, result); EXPECT_EQ(3u, context); } -TEST(WaiterListTest, BasicAwakeUnsatisfiable) { +TEST(AwakableListTest, BasicAwakeUnsatisfiable) { MojoResult result; uint32_t context; // Awake (for unsatisfiability) immediately after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); thread.Start(); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(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; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); thread.Start(); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); @@ -144,22 +144,22 @@ TEST(WaiterListTest, BasicAwakeUnsatisfiable) { // Awake (for unsatisfiability) some time after thread start. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread(&result, &context); - waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); + awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); thread.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); // Double-remove okay: - waiter_list.RemoveWaiter(thread.waiter()); + awakable_list.Remove(thread.waiter()); } // Join |thread|. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); EXPECT_EQ(3u, context); } -TEST(WaiterListTest, MultipleWaiters) { +TEST(AwakableListTest, MultipleAwakables) { MojoResult result1; MojoResult result2; MojoResult result3; @@ -169,110 +169,110 @@ TEST(WaiterListTest, MultipleWaiters) { uint32_t context3; uint32_t context4; - // Cancel two waiters. + // Cancel two awakables. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread1(&result1, &context1); - waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); + awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); thread1.Start(); test::SimpleWaiterThread thread2(&result2, &context2); - waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); + awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); thread2.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.CancelAllWaiters(); + awakable_list.CancelAll(); } // 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. + // Awake one awakable, cancel other. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread1(&result1, &context1); - waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); + awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); thread1.Start(); test::SimpleWaiterThread thread2(&result2, &context2); - waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); + awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); thread2.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread1.waiter()); - waiter_list.CancelAllWaiters(); + awakable_list.Remove(thread1.waiter()); + awakable_list.CancelAll(); } // Join threads. 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. + // Cancel one awakable, awake other for unsatisfiability. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread1(&result1, &context1); - waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); + awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); thread1.Start(); test::SimpleWaiterThread thread2(&result2, &context2); - waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); + awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); thread2.Start(); base::PlatformThread::Sleep(2 * test::EpsilonTimeout()); - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); - waiter_list.RemoveWaiter(thread2.waiter()); - waiter_list.CancelAllWaiters(); + awakable_list.Remove(thread2.waiter()); + awakable_list.CancelAll(); } // 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. + // Cancel one awakable, awake other for unsatisfiability. { - WaiterList waiter_list; + AwakableList awakable_list; test::SimpleWaiterThread thread1(&result1, &context1); - waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); + awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); thread1.Start(); base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); // Should do nothing. - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); test::SimpleWaiterThread thread2(&result2, &context2); - waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); + awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); thread2.Start(); base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); // Awake #1. - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); - waiter_list.RemoveWaiter(thread1.waiter()); + awakable_list.Remove(thread1.waiter()); base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); test::SimpleWaiterThread thread3(&result3, &context3); - waiter_list.AddWaiter(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); + awakable_list.Add(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); thread3.Start(); test::SimpleWaiterThread thread4(&result4, &context4); - waiter_list.AddWaiter(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); + awakable_list.Add(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); thread4.Start(); base::PlatformThread::Sleep(1 * test::EpsilonTimeout()); // Awake #2 and #3 for unsatisfiability. - waiter_list.AwakeWaitersForStateChange(HandleSignalsState( + awakable_list.AwakeForStateChange(HandleSignalsState( MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); - waiter_list.RemoveWaiter(thread2.waiter()); - waiter_list.RemoveWaiter(thread3.waiter()); + awakable_list.Remove(thread2.waiter()); + awakable_list.Remove(thread3.waiter()); // Cancel #4. - waiter_list.CancelAllWaiters(); + awakable_list.CancelAll(); } // Join threads. EXPECT_EQ(MOJO_RESULT_OK, result1); EXPECT_EQ(7u, context1); diff --git a/mojo/edk/system/channel.cc b/mojo/edk/system/channel.cc index 3d6c54f..1e26145 100644 --- a/mojo/edk/system/channel.cc +++ b/mojo/edk/system/channel.cc @@ -72,7 +72,7 @@ void Channel::Shutdown() { size_t num_zombies = 0; for (IdToEndpointMap::iterator it = to_destroy.begin(); it != to_destroy.end(); ++it) { - if (it->second.get()) { + if (it->second) { num_live++; it->second->DetachFromChannel(); } else { @@ -97,7 +97,7 @@ void Channel::WillShutdownSoon() { ChannelEndpointId Channel::AttachAndRunEndpoint( scoped_refptr<ChannelEndpoint> endpoint, bool is_bootstrap) { - DCHECK(endpoint.get()); + DCHECK(endpoint); ChannelEndpointId local_id; ChannelEndpointId remote_id; @@ -185,7 +185,7 @@ void Channel::DetachEndpoint(ChannelEndpoint* endpoint, if (it == local_id_to_endpoint_map_.end() || it->second.get() != endpoint) return; - DCHECK(it->second.get()); + DCHECK(it->second); it->second = nullptr; // Send a remove message outside the lock. @@ -306,7 +306,7 @@ void Channel::OnReadMessageForEndpoint( local_id_to_endpoint_map_.find(local_id); if (it != local_id_to_endpoint_map_.end()) { // Ignore messages for zombie endpoints (not an error). - if (!it->second.get()) { + if (!it->second) { DVLOG(2) << "Ignoring downstream message for zombie endpoint (local ID " "= " << local_id << ", remote ID = " << message_view.source_id() << ")"; @@ -316,7 +316,7 @@ void Channel::OnReadMessageForEndpoint( endpoint = it->second; } } - if (!endpoint.get()) { + if (!endpoint) { HandleRemoteError(base::StringPrintf( "Received a message for nonexistent local destination ID %u", static_cast<unsigned>(local_id.value()))); @@ -453,7 +453,7 @@ bool Channel::OnRemoveMessagePipeEndpoint(ChannelEndpointId local_id, return false; } - if (!it->second.get()) { + if (!it->second) { // Remove messages "crossed"; we have to wait for the ack. return true; } @@ -489,7 +489,7 @@ bool Channel::OnRemoveMessagePipeEndpointAck(ChannelEndpointId local_id) { return false; } - if (it->second.get()) { + if (it->second) { DVLOG(2) << "Remove message pipe endpoint ack error: wrong state"; return false; } diff --git a/mojo/edk/system/channel_endpoint.cc b/mojo/edk/system/channel_endpoint.cc index a8bbbb2..8ef1f40 100644 --- a/mojo/edk/system/channel_endpoint.cc +++ b/mojo/edk/system/channel_endpoint.cc @@ -5,6 +5,7 @@ #include "mojo/edk/system/channel_endpoint.h" #include "base/logging.h" +#include "base/threading/platform_thread.h" #include "mojo/edk/system/channel.h" #include "mojo/edk/system/channel_endpoint_client.h" @@ -14,8 +15,11 @@ namespace system { ChannelEndpoint::ChannelEndpoint(ChannelEndpointClient* client, unsigned client_port, MessageInTransitQueue* message_queue) - : client_(client), client_port_(client_port), channel_(nullptr) { - DCHECK(client_.get() || message_queue); + : client_(client), + client_port_(client_port), + channel_(nullptr), + is_detached_from_channel_(false) { + DCHECK(client_ || message_queue); if (message_queue) channel_message_queue_.Swap(message_queue); @@ -39,21 +43,27 @@ bool ChannelEndpoint::EnqueueMessage(scoped_ptr<MessageInTransit> message) { return WriteMessageNoLock(message.Pass()); } +bool ChannelEndpoint::ReplaceClient(ChannelEndpointClient* client, + unsigned client_port) { + DCHECK(client); + + base::AutoLock locker(lock_); + DCHECK(client_); + DCHECK(client != client_.get() || client_port != client_port_); + client_ = client; + client_port_ = client_port; + return !is_detached_from_channel_; +} + void ChannelEndpoint::DetachFromClient() { - { - base::AutoLock locker(lock_); - DCHECK(client_.get()); - client_ = nullptr; + base::AutoLock locker(lock_); + DCHECK(client_); + client_ = nullptr; - if (!channel_) - return; - DCHECK(local_id_.is_valid()); - DCHECK(remote_id_.is_valid()); - channel_->DetachEndpoint(this, local_id_, remote_id_); - channel_ = nullptr; - local_id_ = ChannelEndpointId(); - remote_id_ = ChannelEndpointId(); - } + if (!channel_) + return; + channel_->DetachEndpoint(this, local_id_, remote_id_); + ResetChannelNoLock(); } void ChannelEndpoint::AttachAndRun(Channel* channel, @@ -76,32 +86,52 @@ void ChannelEndpoint::AttachAndRun(Channel* channel, << "Failed to write enqueue message to channel"; } - if (!client_.get()) { + if (!client_) { channel_->DetachEndpoint(this, local_id_, remote_id_); - channel_ = nullptr; - local_id_ = ChannelEndpointId(); - remote_id_ = ChannelEndpointId(); + ResetChannelNoLock(); } } void ChannelEndpoint::OnReadMessage(scoped_ptr<MessageInTransit> message) { scoped_refptr<ChannelEndpointClient> client; - unsigned client_port; - { - base::AutoLock locker(lock_); - DCHECK(channel_); - if (!client_.get()) { - // This isn't a failure per se. (It just means that, e.g., the other end - // of the message point closed first.) - return; + unsigned client_port = 0; + + // This loop is to make |ReplaceClient()| work. We can't call the client's + // |OnReadMessage()| under our lock, so by the time we do that, |client| may + // no longer be our client. + // + // In that case, |client| must return false. We'll then yield, and retry with + // the new client. (Theoretically, the client could be replaced again.) + // + // This solution isn't terribly elegant, but it's the least costly way of + // handling/avoiding this (very unlikely) race. (Other solutions -- e.g., + // adding a client message queue, which the client only fetches messages from + // -- impose significant cost in the common case.) + for (;;) { + { + base::AutoLock locker(lock_); + if (!channel_ || !client_) { + // This isn't a failure per se. (It just means that, e.g., the other end + // of the message point closed first.) + return; + } + + // If we get here in a second (third, etc.) iteration of the loop, it's + // because |ReplaceClient()| was called. + DCHECK(client_ != client || client_port_ != client_port); + + // Take a ref, and call |OnReadMessage()| outside the lock. + client = client_; + client_port = client_port_; } - // Take a ref, and call |OnReadMessage()| outside the lock. - client = client_; - client_port = client_port_; - } + if (client->OnReadMessage(client_port, message.get())) { + ignore_result(message.release()); + break; + } - client->OnReadMessage(client_port, message.Pass()); + base::PlatformThread::YieldCurrentThread(); + } } void ChannelEndpoint::DetachFromChannel() { @@ -110,7 +140,7 @@ void ChannelEndpoint::DetachFromChannel() { { base::AutoLock locker(lock_); - if (client_.get()) { + if (client_) { // Take a ref, and call |OnDetachFromChannel()| outside the lock. client = client_; client_port = client_port_; @@ -119,21 +149,23 @@ void ChannelEndpoint::DetachFromChannel() { // |channel_| may already be null if we already detached from the channel in // |DetachFromClient()| by calling |Channel::DetachEndpoint()| (and there // are racing detaches). - if (channel_) { - DCHECK(local_id_.is_valid()); - DCHECK(remote_id_.is_valid()); - channel_ = nullptr; - local_id_ = ChannelEndpointId(); - remote_id_ = ChannelEndpointId(); - } + if (channel_) + ResetChannelNoLock(); + else + DCHECK(is_detached_from_channel_); } - if (client.get()) + // If |ReplaceClient()| is called (from another thread) after the above locked + // section but before we call |OnDetachFromChannel()|, |ReplaceClient()| + // return false to notify the caller that the channel was already detached. + // (The old client has to accept the arguably-spurious call to + // |OnDetachFromChannel()|.) + if (client) client->OnDetachFromChannel(client_port); } ChannelEndpoint::~ChannelEndpoint() { - DCHECK(!client_.get()); + DCHECK(!client_); DCHECK(!channel_); DCHECK(!local_id_.is_valid()); DCHECK(!remote_id_.is_valid()); @@ -154,5 +186,17 @@ bool ChannelEndpoint::WriteMessageNoLock(scoped_ptr<MessageInTransit> message) { return channel_->WriteMessage(message.Pass()); } +void ChannelEndpoint::ResetChannelNoLock() { + DCHECK(channel_); + DCHECK(local_id_.is_valid()); + DCHECK(remote_id_.is_valid()); + DCHECK(!is_detached_from_channel_); + + channel_ = nullptr; + local_id_ = ChannelEndpointId(); + remote_id_ = ChannelEndpointId(); + is_detached_from_channel_ = true; +} + } // namespace system } // namespace mojo diff --git a/mojo/edk/system/channel_endpoint.h b/mojo/edk/system/channel_endpoint.h index 71b6f9b..90ee86b 100644 --- a/mojo/edk/system/channel_endpoint.h +++ b/mojo/edk/system/channel_endpoint.h @@ -130,6 +130,15 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint // called.) bool EnqueueMessage(scoped_ptr<MessageInTransit> message); + // Called to *replace* current client with a new client (which must differ + // from the existing client). This must not be called after + // |DetachFromClient()| has been called. + // + // This returns true in the typical case, and false if this endpoint has been + // detached from the channel, in which case the caller should probably call + // its (new) client's |OnDetachFromChannel()|. + bool ReplaceClient(ChannelEndpointClient* client, unsigned client_port); + // Called before the |ChannelEndpointClient| gives up its reference to this // object. void DetachFromClient(); @@ -156,6 +165,10 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint // Must be called with |lock_| held. bool WriteMessageNoLock(scoped_ptr<MessageInTransit> message); + // Resets |channel_| to null (and sets |is_detached_from_channel_|). This may + // only be called if |channel_| is non-null. Must be called with |lock_| held. + void ResetChannelNoLock(); + // Protects the members below. base::Lock lock_; @@ -168,6 +181,9 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint // WARNING: |ChannelEndpointClient| methods must not be called under |lock_|. // Thus to make such a call, a reference must first be taken under |lock_| and // the lock released. + // WARNING: Beware of interactions with |ReplaceClient()|. By the time the + // call is made, the client may have changed. This must be detected and dealt + // with. scoped_refptr<ChannelEndpointClient> client_; unsigned client_port_; @@ -177,6 +193,9 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpoint Channel* channel_; ChannelEndpointId local_id_; ChannelEndpointId remote_id_; + // This distinguishes the two cases of |channel| being null: not yet attached + // versus detached. + bool is_detached_from_channel_; // This queue is used before we're running on a channel and ready to send // messages to the channel. diff --git a/mojo/edk/system/channel_endpoint_client.h b/mojo/edk/system/channel_endpoint_client.h index 7a7d5b8..c758e9c 100644 --- a/mojo/edk/system/channel_endpoint_client.h +++ b/mojo/edk/system/channel_endpoint_client.h @@ -38,8 +38,9 @@ class MOJO_SYSTEM_IMPL_EXPORT ChannelEndpointClient // called by |Channel| when it receives a message for the |ChannelEndpoint|. // (|port| is the value passed to |ChannelEndpoint|'s constructor as // |client_port|.) - virtual void OnReadMessage(unsigned port, - scoped_ptr<MessageInTransit> message) = 0; + // + // This should return true if it accepted (and took ownership of) |message|. + virtual bool OnReadMessage(unsigned port, MessageInTransit* message) = 0; // Called by |ChannelEndpoint| when the |Channel| is relinquishing its pointer // to the |ChannelEndpoint| (and vice versa). After this is called, diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc index e84ab5b..ce4eefe 100644 --- a/mojo/edk/system/channel_unittest.cc +++ b/mojo/edk/system/channel_unittest.cc @@ -50,7 +50,7 @@ class ChannelTest : public testing::Test { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); CHECK(raw_channel_); - CHECK(channel_.get()); + CHECK(channel_); CHECK_EQ(init_result_, TRISTATE_UNKNOWN); init_result_ = BoolToTristate(channel_->Init(raw_channel_.Pass())); @@ -59,7 +59,7 @@ class ChannelTest : public testing::Test { void ShutdownChannelOnIOThread() { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - CHECK(channel_.get()); + CHECK(channel_); channel_->Shutdown(); } @@ -231,7 +231,7 @@ TEST_F(ChannelTest, ShutdownAfterAttach) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Don't wait for the shutdown to run ... io_thread()->PostTask(FROM_HERE, @@ -242,7 +242,7 @@ TEST_F(ChannelTest, ShutdownAfterAttach) { EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); HandleSignalsState hss; - mp->RemoveWaiter(0, &waiter, &hss); + mp->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -277,8 +277,9 @@ TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) { Waiter waiter; waiter.Init(); HandleSignalsState hss; - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss)); + EXPECT_EQ( + MOJO_RESULT_FAILED_PRECONDITION, + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index 27d33b2..3843d97 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc @@ -47,10 +47,11 @@ namespace system { // |Dispatcher|s for the handles that it wants to wait on with a |Waiter| // object; this |Waiter| object may be created on the stack of that thread or be // kept in thread local storage for that thread (TODO(vtl): future improvement). -// The |Dispatcher| then adds the |Waiter| to a |WaiterList| that's either owned -// by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object (e.g., -// |MessagePipe|). To signal/wake a |Waiter|, the object in question -- either a -// |SimpleDispatcher| or a secondary object -- talks to its |WaiterList|. +// The |Dispatcher| then adds the |Waiter| to an |AwakableList| that's either +// owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object +// (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question -- +// either a |SimpleDispatcher| or a secondary object -- talks to its +// |AwakableList|. // Thread-safety notes // @@ -221,7 +222,7 @@ MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, uint32_t num_handles, MojoWriteMessageFlags flags) { scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; // Easy case: not sending any handles. @@ -288,7 +289,7 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, UserPointer<uint32_t> num_handles, MojoReadMessageFlags flags) { scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get(); @@ -322,7 +323,7 @@ MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, << " handles, but handle table full"; // Close dispatchers (outside the lock). for (size_t i = 0; i < dispatchers.size(); i++) { - if (dispatchers[i].get()) + if (dispatchers[i]) dispatchers[i]->Close(); } if (rv == MOJO_RESULT_OK) @@ -381,7 +382,7 @@ MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, MojoWriteDataFlags flags) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->WriteData(elements, num_bytes, flags); @@ -393,7 +394,7 @@ MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, MojoWriteDataFlags flags) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); @@ -403,7 +404,7 @@ MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, uint32_t num_bytes_written) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_producer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->EndWriteData(num_bytes_written); @@ -415,7 +416,7 @@ MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, MojoReadDataFlags flags) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->ReadData(elements, num_bytes, flags); @@ -427,7 +428,7 @@ MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, MojoReadDataFlags flags) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); @@ -437,7 +438,7 @@ MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, uint32_t num_bytes_read) { scoped_refptr<Dispatcher> dispatcher( GetDispatcher(data_pipe_consumer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; return dispatcher->EndReadData(num_bytes_read); @@ -457,7 +458,7 @@ MojoResult Core::CreateSharedBuffer( result = SharedBufferDispatcher::Create(platform_support(), validated_options, num_bytes, &dispatcher); if (result != MOJO_RESULT_OK) { - DCHECK(!dispatcher.get()); + DCHECK(!dispatcher); return result; } @@ -477,7 +478,7 @@ MojoResult Core::DuplicateBufferHandle( UserPointer<const MojoDuplicateBufferHandleOptions> options, UserPointer<MojoHandle> new_buffer_handle) { scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; // Don't verify |options| here; that's the dispatcher's job. @@ -504,7 +505,7 @@ MojoResult Core::MapBuffer(MojoHandle buffer_handle, UserPointer<void*> buffer, MojoMapBufferFlags flags) { scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); - if (!dispatcher.get()) + if (!dispatcher) return MOJO_RESULT_INVALID_ARGUMENT; scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; @@ -532,7 +533,7 @@ MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { // Note: We allow |handles| to repeat the same handle multiple times, since // different flags may be specified. -// TODO(vtl): This incurs a performance cost in |RemoveWaiter()|. Analyze this +// TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this // more carefully and address it if necessary. MojoResult Core::WaitManyInternal(const MojoHandle* handles, const MojoHandleSignals* signals, @@ -547,7 +548,7 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, dispatchers.reserve(num_handles); for (uint32_t i = 0; i < num_handles; i++) { scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); - if (!dispatcher.get()) { + if (!dispatcher) { *result_index = i; return MOJO_RESULT_INVALID_ARGUMENT; } @@ -561,7 +562,7 @@ 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( + rv = dispatchers[i]->AddAwakable( &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); if (rv != MOJO_RESULT_OK) { *result_index = i; @@ -579,8 +580,8 @@ MojoResult Core::WaitManyInternal(const MojoHandle* handles, // |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, - signals_states ? &signals_states[i] : nullptr); + dispatchers[i]->RemoveAwakable( + &waiter, signals_states ? &signals_states[i] : nullptr); } if (signals_states) { for (; i < num_handles; i++) diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc index ea06c29..76e70e2 100644 --- a/mojo/edk/system/core_test_base.cc +++ b/mojo/edk/system/core_test_base.cc @@ -123,27 +123,27 @@ class MockDispatcher : public Dispatcher { return MOJO_RESULT_UNIMPLEMENTED; } - MojoResult AddWaiterImplNoLock(Waiter* /*waiter*/, - MojoHandleSignals /*signals*/, - uint32_t /*context*/, - HandleSignalsState* signals_state) override { - info_->IncrementAddWaiterCallCount(); + MojoResult AddAwakableImplNoLock(Awakable* /*awakable*/, + MojoHandleSignals /*signals*/, + uint32_t /*context*/, + HandleSignalsState* signals_state) override { + info_->IncrementAddAwakableCallCount(); lock().AssertAcquired(); if (signals_state) *signals_state = HandleSignalsState(); return MOJO_RESULT_FAILED_PRECONDITION; } - void RemoveWaiterImplNoLock(Waiter* /*waiter*/, - HandleSignalsState* signals_state) override { - info_->IncrementRemoveWaiterCallCount(); + void RemoveAwakableImplNoLock(Awakable* /*awakable*/, + HandleSignalsState* signals_state) override { + info_->IncrementRemoveAwakableCallCount(); lock().AssertAcquired(); if (signals_state) *signals_state = HandleSignalsState(); } - void CancelAllWaitersNoLock() override { - info_->IncrementCancelAllWaitersCallCount(); + void CancelAllAwakablesNoLock() override { + info_->IncrementCancelAllAwakablesCallCount(); lock().AssertAcquired(); } @@ -196,9 +196,9 @@ CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo() read_data_call_count_(0), begin_read_data_call_count_(0), end_read_data_call_count_(0), - add_waiter_call_count_(0), - remove_waiter_call_count_(0), - cancel_all_waiters_call_count_(0) { + add_awakable_call_count_(0), + remove_awakable_call_count_(0), + cancel_all_awakables_call_count_(0) { } CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() { @@ -259,19 +259,19 @@ unsigned CoreTestBase_MockHandleInfo::GetEndReadDataCallCount() const { return end_read_data_call_count_; } -unsigned CoreTestBase_MockHandleInfo::GetAddWaiterCallCount() const { +unsigned CoreTestBase_MockHandleInfo::GetAddAwakableCallCount() const { base::AutoLock locker(lock_); - return add_waiter_call_count_; + return add_awakable_call_count_; } -unsigned CoreTestBase_MockHandleInfo::GetRemoveWaiterCallCount() const { +unsigned CoreTestBase_MockHandleInfo::GetRemoveAwakableCallCount() const { base::AutoLock locker(lock_); - return remove_waiter_call_count_; + return remove_awakable_call_count_; } -unsigned CoreTestBase_MockHandleInfo::GetCancelAllWaitersCallCount() const { +unsigned CoreTestBase_MockHandleInfo::GetCancelAllAwakablesCallCount() const { base::AutoLock locker(lock_); - return cancel_all_waiters_call_count_; + return cancel_all_awakables_call_count_; } void CoreTestBase_MockHandleInfo::IncrementCtorCallCount() { @@ -329,19 +329,19 @@ void CoreTestBase_MockHandleInfo::IncrementEndReadDataCallCount() { end_read_data_call_count_++; } -void CoreTestBase_MockHandleInfo::IncrementAddWaiterCallCount() { +void CoreTestBase_MockHandleInfo::IncrementAddAwakableCallCount() { base::AutoLock locker(lock_); - add_waiter_call_count_++; + add_awakable_call_count_++; } -void CoreTestBase_MockHandleInfo::IncrementRemoveWaiterCallCount() { +void CoreTestBase_MockHandleInfo::IncrementRemoveAwakableCallCount() { base::AutoLock locker(lock_); - remove_waiter_call_count_++; + remove_awakable_call_count_++; } -void CoreTestBase_MockHandleInfo::IncrementCancelAllWaitersCallCount() { +void CoreTestBase_MockHandleInfo::IncrementCancelAllAwakablesCallCount() { base::AutoLock locker(lock_); - cancel_all_waiters_call_count_++; + cancel_all_awakables_call_count_++; } } // namespace test diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h index 2881176..80a926b 100644 --- a/mojo/edk/system/core_test_base.h +++ b/mojo/edk/system/core_test_base.h @@ -58,9 +58,9 @@ class CoreTestBase_MockHandleInfo { unsigned GetReadDataCallCount() const; unsigned GetBeginReadDataCallCount() const; unsigned GetEndReadDataCallCount() const; - unsigned GetAddWaiterCallCount() const; - unsigned GetRemoveWaiterCallCount() const; - unsigned GetCancelAllWaitersCallCount() const; + unsigned GetAddAwakableCallCount() const; + unsigned GetRemoveAwakableCallCount() const; + unsigned GetCancelAllAwakablesCallCount() const; // For use by |MockDispatcher|: void IncrementCtorCallCount(); @@ -74,9 +74,9 @@ class CoreTestBase_MockHandleInfo { void IncrementReadDataCallCount(); void IncrementBeginReadDataCallCount(); void IncrementEndReadDataCallCount(); - void IncrementAddWaiterCallCount(); - void IncrementRemoveWaiterCallCount(); - void IncrementCancelAllWaitersCallCount(); + void IncrementAddAwakableCallCount(); + void IncrementRemoveAwakableCallCount(); + void IncrementCancelAllAwakablesCallCount(); private: mutable base::Lock lock_; // Protects the following members. @@ -91,9 +91,9 @@ class CoreTestBase_MockHandleInfo { unsigned read_data_call_count_; unsigned begin_read_data_call_count_; unsigned end_read_data_call_count_; - unsigned add_waiter_call_count_; - unsigned remove_waiter_call_count_; - unsigned cancel_all_waiters_call_count_; + unsigned add_awakable_call_count_; + unsigned remove_awakable_call_count_; + unsigned cancel_all_awakables_call_count_; DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo); }; diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc index 51a4022..d7976a3 100644 --- a/mojo/edk/system/core_unittest.cc +++ b/mojo/edk/system/core_unittest.cc @@ -95,30 +95,30 @@ TEST_F(CoreTest, Basic) { EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0)); EXPECT_EQ(1u, info.GetEndReadDataCallCount()); - EXPECT_EQ(0u, info.GetAddWaiterCallCount()); + EXPECT_EQ(0u, info.GetAddAwakableCallCount()); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, NullUserPointer())); - EXPECT_EQ(1u, info.GetAddWaiterCallCount()); + EXPECT_EQ(1u, info.GetAddAwakableCallCount()); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer())); - EXPECT_EQ(2u, info.GetAddWaiterCallCount()); + EXPECT_EQ(2u, info.GetAddAwakableCallCount()); MojoHandleSignalsState hss = kFullMojoHandleSignalsState; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&hss))); - EXPECT_EQ(3u, info.GetAddWaiterCallCount()); + EXPECT_EQ(3u, info.GetAddAwakableCallCount()); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); EXPECT_EQ( MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer())); - EXPECT_EQ(4u, info.GetAddWaiterCallCount()); + EXPECT_EQ(4u, info.GetAddAwakableCallCount()); hss = kFullMojoHandleSignalsState; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, MakeUserPointer(&hss))); - EXPECT_EQ(5u, info.GetAddWaiterCallCount()); + EXPECT_EQ(5u, info.GetAddAwakableCallCount()); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); @@ -128,14 +128,14 @@ TEST_F(CoreTest, Basic) { core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, MOJO_DEADLINE_INDEFINITE, NullUserPointer(), NullUserPointer())); - EXPECT_EQ(6u, info.GetAddWaiterCallCount()); + EXPECT_EQ(6u, info.GetAddAwakableCallCount()); uint32_t result_index = static_cast<uint32_t>(-1); EXPECT_EQ( MOJO_RESULT_FAILED_PRECONDITION, core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), NullUserPointer())); - EXPECT_EQ(7u, info.GetAddWaiterCallCount()); + EXPECT_EQ(7u, info.GetAddAwakableCallCount()); EXPECT_EQ(0u, result_index); hss = kFullMojoHandleSignalsState; EXPECT_EQ( @@ -143,7 +143,7 @@ TEST_F(CoreTest, Basic) { core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, MOJO_DEADLINE_INDEFINITE, NullUserPointer(), MakeUserPointer(&hss))); - EXPECT_EQ(8u, info.GetAddWaiterCallCount()); + EXPECT_EQ(8u, info.GetAddAwakableCallCount()); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); result_index = static_cast<uint32_t>(-1); @@ -153,21 +153,21 @@ TEST_F(CoreTest, Basic) { core()->WaitMany(MakeUserPointer(&h), MakeUserPointer(&handle_signals), 1, MOJO_DEADLINE_INDEFINITE, MakeUserPointer(&result_index), MakeUserPointer(&hss))); - EXPECT_EQ(9u, info.GetAddWaiterCallCount()); + EXPECT_EQ(9u, info.GetAddAwakableCallCount()); EXPECT_EQ(0u, result_index); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); EXPECT_EQ(0u, info.GetDtorCallCount()); EXPECT_EQ(0u, info.GetCloseCallCount()); - EXPECT_EQ(0u, info.GetCancelAllWaitersCallCount()); + EXPECT_EQ(0u, info.GetCancelAllAwakablesCallCount()); EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h)); - EXPECT_EQ(1u, info.GetCancelAllWaitersCallCount()); + EXPECT_EQ(1u, info.GetCancelAllAwakablesCallCount()); EXPECT_EQ(1u, info.GetCloseCallCount()); EXPECT_EQ(1u, info.GetDtorCallCount()); - // No waiters should ever have ever been added. - EXPECT_EQ(0u, info.GetRemoveWaiterCallCount()); + // No awakables should ever have ever been added. + EXPECT_EQ(0u, info.GetRemoveAwakableCallCount()); } TEST_F(CoreTest, InvalidArguments) { diff --git a/mojo/edk/system/data_pipe.cc b/mojo/edk/system/data_pipe.cc index cbacb89..2f433bd 100644 --- a/mojo/edk/system/data_pipe.cc +++ b/mojo/edk/system/data_pipe.cc @@ -10,10 +10,10 @@ #include <limits> #include "base/logging.h" +#include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/configuration.h" #include "mojo/edk/system/memory.h" #include "mojo/edk/system/options_validation.h" -#include "mojo/edk/system/waiter_list.h" namespace mojo { namespace system { @@ -83,10 +83,10 @@ MojoResult DataPipe::ValidateCreateOptions( return MOJO_RESULT_OK; } -void DataPipe::ProducerCancelAllWaiters() { +void DataPipe::ProducerCancelAllAwakables() { base::AutoLock locker(lock_); DCHECK(has_local_producer_no_lock()); - producer_waiter_list_->CancelAllWaiters(); + producer_awakable_list_->CancelAll(); } void DataPipe::ProducerClose() { @@ -94,13 +94,13 @@ void DataPipe::ProducerClose() { DCHECK(producer_open_); producer_open_ = false; DCHECK(has_local_producer_no_lock()); - producer_waiter_list_.reset(); + producer_awakable_list_.reset(); // Not a bug, except possibly in "user" code. DVLOG_IF(2, producer_in_two_phase_write_no_lock()) << "Producer closed with active two-phase write"; producer_two_phase_max_num_bytes_written_ = 0; ProducerCloseImplNoLock(); - AwakeConsumerWaitersForStateChangeNoLock( + AwakeConsumerAwakablesForStateChangeNoLock( ConsumerGetHandleSignalsStateImplNoLock()); } @@ -132,7 +132,7 @@ MojoResult DataPipe::ProducerWriteData(UserPointer<const void> elements, HandleSignalsState new_consumer_state = ConsumerGetHandleSignalsStateImplNoLock(); if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); + AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); return rv; } @@ -159,10 +159,10 @@ MojoResult DataPipe::ProducerBeginWriteData( min_num_bytes_to_write); if (rv != MOJO_RESULT_OK) return rv; - // Note: No need to awake producer waiters, even though we're going from + // Note: No need to awake producer awakables, even though we're going from // writable to non-writable (since you can't wait on non-writability). // Similarly, though this may have discarded data (in "may discard" mode), - // making it non-readable, there's still no need to awake consumer waiters. + // making it non-readable, there's still no need to awake consumer awakables. DCHECK(producer_in_two_phase_write_no_lock()); return MOJO_RESULT_OK; } @@ -189,15 +189,15 @@ MojoResult DataPipe::ProducerEndWriteData(uint32_t num_bytes_written) { // Two-phase write ended even on failure. DCHECK(!producer_in_two_phase_write_no_lock()); // If we're now writable, we *became* writable (since we weren't writable - // during the two-phase write), so awake producer waiters. + // during the two-phase write), so awake producer awakables. HandleSignalsState new_producer_state = ProducerGetHandleSignalsStateImplNoLock(); if (new_producer_state.satisfies(MOJO_HANDLE_SIGNAL_WRITABLE)) - AwakeProducerWaitersForStateChangeNoLock(new_producer_state); + AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); HandleSignalsState new_consumer_state = ConsumerGetHandleSignalsStateImplNoLock(); if (!new_consumer_state.equals(old_consumer_state)) - AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); + AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); return rv; } @@ -207,10 +207,10 @@ HandleSignalsState DataPipe::ProducerGetHandleSignalsState() { return ProducerGetHandleSignalsStateImplNoLock(); } -MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) { +MojoResult DataPipe::ProducerAddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) { base::AutoLock locker(lock_); DCHECK(has_local_producer_no_lock()); @@ -226,15 +226,15 @@ MojoResult DataPipe::ProducerAddWaiter(Waiter* waiter, return MOJO_RESULT_FAILED_PRECONDITION; } - producer_waiter_list_->AddWaiter(waiter, signals, context); + producer_awakable_list_->Add(awakable, signals, context); return MOJO_RESULT_OK; } -void DataPipe::ProducerRemoveWaiter(Waiter* waiter, - HandleSignalsState* signals_state) { +void DataPipe::ProducerRemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state) { base::AutoLock locker(lock_); DCHECK(has_local_producer_no_lock()); - producer_waiter_list_->RemoveWaiter(waiter); + producer_awakable_list_->Remove(awakable); if (signals_state) *signals_state = ProducerGetHandleSignalsStateImplNoLock(); } @@ -244,10 +244,10 @@ bool DataPipe::ProducerIsBusy() const { return producer_in_two_phase_write_no_lock(); } -void DataPipe::ConsumerCancelAllWaiters() { +void DataPipe::ConsumerCancelAllAwakables() { base::AutoLock locker(lock_); DCHECK(has_local_consumer_no_lock()); - consumer_waiter_list_->CancelAllWaiters(); + consumer_awakable_list_->CancelAll(); } void DataPipe::ConsumerClose() { @@ -255,13 +255,13 @@ void DataPipe::ConsumerClose() { DCHECK(consumer_open_); consumer_open_ = false; DCHECK(has_local_consumer_no_lock()); - consumer_waiter_list_.reset(); + consumer_awakable_list_.reset(); // Not a bug, except possibly in "user" code. DVLOG_IF(2, consumer_in_two_phase_read_no_lock()) << "Consumer closed with active two-phase read"; consumer_two_phase_max_num_bytes_read_ = 0; ConsumerCloseImplNoLock(); - AwakeProducerWaitersForStateChangeNoLock( + AwakeProducerAwakablesForStateChangeNoLock( ProducerGetHandleSignalsStateImplNoLock()); } @@ -291,7 +291,7 @@ MojoResult DataPipe::ConsumerReadData(UserPointer<void> elements, HandleSignalsState new_producer_state = ProducerGetHandleSignalsStateImplNoLock(); if (!new_producer_state.equals(old_producer_state)) - AwakeProducerWaitersForStateChangeNoLock(new_producer_state); + AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); return rv; } @@ -320,7 +320,7 @@ MojoResult DataPipe::ConsumerDiscardData(UserPointer<uint32_t> num_bytes, HandleSignalsState new_producer_state = ProducerGetHandleSignalsStateImplNoLock(); if (!new_producer_state.equals(old_producer_state)) - AwakeProducerWaitersForStateChangeNoLock(new_producer_state); + AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); return rv; } @@ -380,15 +380,15 @@ MojoResult DataPipe::ConsumerEndReadData(uint32_t num_bytes_read) { // Two-phase read ended even on failure. DCHECK(!consumer_in_two_phase_read_no_lock()); // If we're now readable, we *became* readable (since we weren't readable - // during the two-phase read), so awake consumer waiters. + // during the two-phase read), so awake consumer awakables. HandleSignalsState new_consumer_state = ConsumerGetHandleSignalsStateImplNoLock(); if (new_consumer_state.satisfies(MOJO_HANDLE_SIGNAL_READABLE)) - AwakeConsumerWaitersForStateChangeNoLock(new_consumer_state); + AwakeConsumerAwakablesForStateChangeNoLock(new_consumer_state); HandleSignalsState new_producer_state = ProducerGetHandleSignalsStateImplNoLock(); if (!new_producer_state.equals(old_producer_state)) - AwakeProducerWaitersForStateChangeNoLock(new_producer_state); + AwakeProducerAwakablesForStateChangeNoLock(new_producer_state); return rv; } @@ -398,10 +398,10 @@ HandleSignalsState DataPipe::ConsumerGetHandleSignalsState() { return ConsumerGetHandleSignalsStateImplNoLock(); } -MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) { +MojoResult DataPipe::ConsumerAddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) { base::AutoLock locker(lock_); DCHECK(has_local_consumer_no_lock()); @@ -417,15 +417,15 @@ MojoResult DataPipe::ConsumerAddWaiter(Waiter* waiter, return MOJO_RESULT_FAILED_PRECONDITION; } - consumer_waiter_list_->AddWaiter(waiter, signals, context); + consumer_awakable_list_->Add(awakable, signals, context); return MOJO_RESULT_OK; } -void DataPipe::ConsumerRemoveWaiter(Waiter* waiter, - HandleSignalsState* signals_state) { +void DataPipe::ConsumerRemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state) { base::AutoLock locker(lock_); DCHECK(has_local_consumer_no_lock()); - consumer_waiter_list_->RemoveWaiter(waiter); + consumer_awakable_list_->Remove(awakable); if (signals_state) *signals_state = ConsumerGetHandleSignalsStateImplNoLock(); } @@ -444,8 +444,10 @@ DataPipe::DataPipe(bool has_local_producer, capacity_num_bytes_(validated_options.capacity_num_bytes), producer_open_(true), consumer_open_(true), - producer_waiter_list_(has_local_producer ? new WaiterList() : nullptr), - consumer_waiter_list_(has_local_consumer ? new WaiterList() : nullptr), + producer_awakable_list_(has_local_producer ? new AwakableList() + : nullptr), + consumer_awakable_list_(has_local_consumer ? new AwakableList() + : nullptr), producer_two_phase_max_num_bytes_written_(0), consumer_two_phase_max_num_bytes_read_(0) { // Check that the passed in options actually are validated. @@ -457,24 +459,24 @@ DataPipe::DataPipe(bool has_local_producer, DataPipe::~DataPipe() { DCHECK(!producer_open_); DCHECK(!consumer_open_); - DCHECK(!producer_waiter_list_); - DCHECK(!consumer_waiter_list_); + DCHECK(!producer_awakable_list_); + DCHECK(!consumer_awakable_list_); } -void DataPipe::AwakeProducerWaitersForStateChangeNoLock( +void DataPipe::AwakeProducerAwakablesForStateChangeNoLock( const HandleSignalsState& new_producer_state) { lock_.AssertAcquired(); if (!has_local_producer_no_lock()) return; - producer_waiter_list_->AwakeWaitersForStateChange(new_producer_state); + producer_awakable_list_->AwakeForStateChange(new_producer_state); } -void DataPipe::AwakeConsumerWaitersForStateChangeNoLock( +void DataPipe::AwakeConsumerAwakablesForStateChangeNoLock( const HandleSignalsState& new_consumer_state) { lock_.AssertAcquired(); if (!has_local_consumer_no_lock()) return; - consumer_waiter_list_->AwakeWaitersForStateChange(new_consumer_state); + consumer_awakable_list_->AwakeForStateChange(new_consumer_state); } } // namespace system diff --git a/mojo/edk/system/data_pipe.h b/mojo/edk/system/data_pipe.h index 767d405..d893465 100644 --- a/mojo/edk/system/data_pipe.h +++ b/mojo/edk/system/data_pipe.h @@ -20,8 +20,8 @@ namespace mojo { namespace system { -class Waiter; -class WaiterList; +class Awakable; +class AwakableList; // |DataPipe| is a base class for secondary objects implementing data pipes, // similar to |MessagePipe| (see the explanatory comment in core.cc). It is @@ -48,7 +48,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe // These are called by the producer dispatcher to implement its methods of // corresponding names. - void ProducerCancelAllWaiters(); + void ProducerCancelAllAwakables(); void ProducerClose(); MojoResult ProducerWriteData(UserPointer<const void> elements, UserPointer<uint32_t> num_bytes, @@ -58,16 +58,17 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe bool all_or_none); MojoResult ProducerEndWriteData(uint32_t num_bytes_written); HandleSignalsState ProducerGetHandleSignalsState(); - MojoResult ProducerAddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - void ProducerRemoveWaiter(Waiter* waiter, HandleSignalsState* signals_state); + MojoResult ProducerAddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + void ProducerRemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state); bool ProducerIsBusy() const; // These are called by the consumer dispatcher to implement its methods of // corresponding names. - void ConsumerCancelAllWaiters(); + void ConsumerCancelAllAwakables(); void ConsumerClose(); // This does not validate its arguments, except to check that |*num_bytes| is // a multiple of |element_num_bytes_|. @@ -83,11 +84,12 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe bool all_or_none); MojoResult ConsumerEndReadData(uint32_t num_bytes_read); HandleSignalsState ConsumerGetHandleSignalsState(); - MojoResult ConsumerAddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - void ConsumerRemoveWaiter(Waiter* waiter, HandleSignalsState* signals_state); + MojoResult ConsumerAddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + void ConsumerRemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state); bool ConsumerIsBusy() const; protected: @@ -179,18 +181,18 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe } private: - void AwakeProducerWaitersForStateChangeNoLock( + void AwakeProducerAwakablesForStateChangeNoLock( const HandleSignalsState& new_producer_state); - void AwakeConsumerWaitersForStateChangeNoLock( + void AwakeConsumerAwakablesForStateChangeNoLock( const HandleSignalsState& new_consumer_state); bool has_local_producer_no_lock() const { lock_.AssertAcquired(); - return !!producer_waiter_list_; + return !!producer_awakable_list_; } bool has_local_consumer_no_lock() const { lock_.AssertAcquired(); - return !!consumer_waiter_list_; + return !!consumer_awakable_list_; } const bool may_discard_; @@ -202,8 +204,8 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipe bool producer_open_; bool consumer_open_; // Non-null only if the producer or consumer, respectively, is local. - scoped_ptr<WaiterList> producer_waiter_list_; - scoped_ptr<WaiterList> consumer_waiter_list_; + scoped_ptr<AwakableList> producer_awakable_list_; + scoped_ptr<AwakableList> consumer_awakable_list_; // These are nonzero if and only if a two-phase write/read is in progress. uint32_t producer_two_phase_max_num_bytes_written_; uint32_t consumer_two_phase_max_num_bytes_read_; diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc index 3c14f35..21127c6 100644 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc +++ b/mojo/edk/system/data_pipe_consumer_dispatcher.cc @@ -15,7 +15,7 @@ DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() { } void DataPipeConsumerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { - DCHECK(data_pipe.get()); + DCHECK(data_pipe); data_pipe_ = data_pipe; } @@ -25,12 +25,12 @@ Dispatcher::Type DataPipeConsumerDispatcher::GetType() const { DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() { // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!data_pipe_.get()); + DCHECK(!data_pipe_); } -void DataPipeConsumerDispatcher::CancelAllWaitersNoLock() { +void DataPipeConsumerDispatcher::CancelAllAwakablesNoLock() { lock().AssertAcquired(); - data_pipe_->ConsumerCancelAllWaiters(); + data_pipe_->ConsumerCancelAllAwakables(); } void DataPipeConsumerDispatcher::CloseImplNoLock() { @@ -109,20 +109,21 @@ HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsStateImplNoLock() return data_pipe_->ConsumerGetHandleSignalsState(); } -MojoResult DataPipeConsumerDispatcher::AddWaiterImplNoLock( - Waiter* waiter, +MojoResult DataPipeConsumerDispatcher::AddAwakableImplNoLock( + Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { lock().AssertAcquired(); - return data_pipe_->ConsumerAddWaiter(waiter, signals, context, signals_state); + return data_pipe_->ConsumerAddAwakable(awakable, signals, context, + signals_state); } -void DataPipeConsumerDispatcher::RemoveWaiterImplNoLock( - Waiter* waiter, +void DataPipeConsumerDispatcher::RemoveAwakableImplNoLock( + Awakable* awakable, HandleSignalsState* signals_state) { lock().AssertAcquired(); - data_pipe_->ConsumerRemoveWaiter(waiter, signals_state); + data_pipe_->ConsumerRemoveAwakable(awakable, signals_state); } bool DataPipeConsumerDispatcher::IsBusyNoLock() const { diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h index 6555fb5..10a3d94 100644 --- a/mojo/edk/system/data_pipe_consumer_dispatcher.h +++ b/mojo/edk/system/data_pipe_consumer_dispatcher.h @@ -32,7 +32,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher : public Dispatcher { ~DataPipeConsumerDispatcher() override; // |Dispatcher| protected methods: - void CancelAllWaitersNoLock() override; + void CancelAllAwakablesNoLock() override; void CloseImplNoLock() override; scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override; @@ -44,12 +44,12 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeConsumerDispatcher : public Dispatcher { MojoReadDataFlags flags) override; MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read) override; HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddWaiterImplNoLock(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) override; - void RemoveWaiterImplNoLock(Waiter* waiter, - HandleSignalsState* signals_state) override; + MojoResult AddAwakableImplNoLock(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) override; + void RemoveAwakableImplNoLock(Awakable* awakable, + HandleSignalsState* signals_state) override; bool IsBusyNoLock() const override; // Protected by |lock()|: diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.cc b/mojo/edk/system/data_pipe_producer_dispatcher.cc index 0a82c9a..0531126 100644 --- a/mojo/edk/system/data_pipe_producer_dispatcher.cc +++ b/mojo/edk/system/data_pipe_producer_dispatcher.cc @@ -15,7 +15,7 @@ DataPipeProducerDispatcher::DataPipeProducerDispatcher() { } void DataPipeProducerDispatcher::Init(scoped_refptr<DataPipe> data_pipe) { - DCHECK(data_pipe.get()); + DCHECK(data_pipe); data_pipe_ = data_pipe; } @@ -25,12 +25,12 @@ Dispatcher::Type DataPipeProducerDispatcher::GetType() const { DataPipeProducerDispatcher::~DataPipeProducerDispatcher() { // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!data_pipe_.get()); + DCHECK(!data_pipe_); } -void DataPipeProducerDispatcher::CancelAllWaitersNoLock() { +void DataPipeProducerDispatcher::CancelAllAwakablesNoLock() { lock().AssertAcquired(); - data_pipe_->ProducerCancelAllWaiters(); + data_pipe_->ProducerCancelAllAwakables(); } void DataPipeProducerDispatcher::CloseImplNoLock() { @@ -82,20 +82,21 @@ HandleSignalsState DataPipeProducerDispatcher::GetHandleSignalsStateImplNoLock() return data_pipe_->ProducerGetHandleSignalsState(); } -MojoResult DataPipeProducerDispatcher::AddWaiterImplNoLock( - Waiter* waiter, +MojoResult DataPipeProducerDispatcher::AddAwakableImplNoLock( + Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { lock().AssertAcquired(); - return data_pipe_->ProducerAddWaiter(waiter, signals, context, signals_state); + return data_pipe_->ProducerAddAwakable(awakable, signals, context, + signals_state); } -void DataPipeProducerDispatcher::RemoveWaiterImplNoLock( - Waiter* waiter, +void DataPipeProducerDispatcher::RemoveAwakableImplNoLock( + Awakable* awakable, HandleSignalsState* signals_state) { lock().AssertAcquired(); - data_pipe_->ProducerRemoveWaiter(waiter, signals_state); + data_pipe_->ProducerRemoveAwakable(awakable, signals_state); } bool DataPipeProducerDispatcher::IsBusyNoLock() const { diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h index bf13148..39c070c 100644 --- a/mojo/edk/system/data_pipe_producer_dispatcher.h +++ b/mojo/edk/system/data_pipe_producer_dispatcher.h @@ -32,7 +32,7 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher : public Dispatcher { ~DataPipeProducerDispatcher() override; // |Dispatcher| protected methods: - void CancelAllWaitersNoLock() override; + void CancelAllAwakablesNoLock() override; void CloseImplNoLock() override; scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override; @@ -44,12 +44,12 @@ class MOJO_SYSTEM_IMPL_EXPORT DataPipeProducerDispatcher : public Dispatcher { MojoWriteDataFlags flags) override; MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written) override; HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddWaiterImplNoLock(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) override; - void RemoveWaiterImplNoLock(Waiter* waiter, - HandleSignalsState* signals_state) override; + MojoResult AddAwakableImplNoLock(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) override; + void RemoveAwakableImplNoLock(Awakable* awakable, + HandleSignalsState* signals_state) override; bool IsBusyNoLock() const override; // Protected by |lock()|: diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc index bed5f9e..e2f2b87 100644 --- a/mojo/edk/system/dispatcher.cc +++ b/mojo/edk/system/dispatcher.cc @@ -220,10 +220,10 @@ HandleSignalsState Dispatcher::GetHandleSignalsState() const { return GetHandleSignalsStateImplNoLock(); } -MojoResult Dispatcher::AddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) { +MojoResult Dispatcher::AddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) { base::AutoLock locker(lock_); if (is_closed_) { if (signals_state) @@ -231,18 +231,19 @@ MojoResult Dispatcher::AddWaiter(Waiter* waiter, return MOJO_RESULT_INVALID_ARGUMENT; } - return AddWaiterImplNoLock(waiter, signals, context, signals_state); + return AddAwakableImplNoLock(awakable, signals, context, signals_state); } -void Dispatcher::RemoveWaiter(Waiter* waiter, - HandleSignalsState* handle_signals_state) { +void Dispatcher::RemoveAwakable(Awakable* awakable, + HandleSignalsState* handle_signals_state) { base::AutoLock locker(lock_); if (is_closed_) { if (handle_signals_state) *handle_signals_state = HandleSignalsState(); return; } - RemoveWaiterImplNoLock(waiter, handle_signals_state); + + RemoveAwakableImplNoLock(awakable, handle_signals_state); } Dispatcher::Dispatcher() : is_closed_(false) { @@ -253,7 +254,7 @@ Dispatcher::~Dispatcher() { DCHECK(is_closed_); } -void Dispatcher::CancelAllWaitersNoLock() { +void Dispatcher::CancelAllAwakablesNoLock() { lock_.AssertAcquired(); DCHECK(is_closed_); // By default, waiting isn't supported. Only dispatchers that can be waited on @@ -370,10 +371,11 @@ HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const { return HandleSignalsState(); } -MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/, - MojoHandleSignals /*signals*/, - uint32_t /*context*/, - HandleSignalsState* signals_state) { +MojoResult Dispatcher::AddAwakableImplNoLock( + Awakable* /*awakable*/, + MojoHandleSignals /*signals*/, + uint32_t /*context*/, + HandleSignalsState* signals_state) { lock_.AssertAcquired(); DCHECK(!is_closed_); // By default, waiting isn't supported. Only dispatchers that can be waited on @@ -383,8 +385,8 @@ MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/, return MOJO_RESULT_FAILED_PRECONDITION; } -void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/, - HandleSignalsState* signals_state) { +void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, + HandleSignalsState* signals_state) { lock_.AssertAcquired(); DCHECK(!is_closed_); // By default, waiting isn't supported. Only dispatchers that can be waited on @@ -427,7 +429,7 @@ void Dispatcher::CloseNoLock() { DCHECK(!is_closed_); is_closed_ = true; - CancelAllWaitersNoLock(); + CancelAllAwakablesNoLock(); CloseImplNoLock(); } @@ -437,7 +439,7 @@ Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { DCHECK(!is_closed_); is_closed_ = true; - CancelAllWaitersNoLock(); + CancelAllAwakablesNoLock(); return CreateEquivalentDispatcherAndCloseImplNoLock(); } diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h index b17bfae..c069269 100644 --- a/mojo/edk/system/dispatcher.h +++ b/mojo/edk/system/dispatcher.h @@ -39,7 +39,7 @@ class HandleTable; class LocalMessagePipeEndpoint; class ProxyMessagePipeEndpoint; class TransportData; -class Waiter; +class Awakable; typedef std::vector<scoped_refptr<Dispatcher>> DispatcherVector; @@ -128,7 +128,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher // threads. HandleSignalsState GetHandleSignalsState() const; - // Adds a waiter to this dispatcher. The waiter will be woken up when this + // Adds an awakable to this dispatcher, which will be woken up when this // object changes state to satisfy |signals| with context |context|. It will // also be woken up when it becomes impossible for the object to ever satisfy // |signals| with a suitable error status. @@ -137,20 +137,20 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher // to the current handle signals state (on success, it is left untouched). // // Returns: - // - |MOJO_RESULT_OK| if the waiter was added; + // - |MOJO_RESULT_OK| if the awakable was added; // - |MOJO_RESULT_ALREADY_EXISTS| if |signals| is already satisfied; // - |MOJO_RESULT_INVALID_ARGUMENT| if the dispatcher has been closed; and // - |MOJO_RESULT_FAILED_PRECONDITION| if it is not (or no longer) possible // that |signals| will ever be satisfied. - MojoResult AddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - // Removes a waiter from this dispatcher. (It is valid to call this multiple - // times for the same |waiter| on the same object, so long as |AddWaiter()| - // was called at most once.) If |signals_state| is non-null, |*signals_state| - // will be set to the current handle signals state. - void RemoveWaiter(Waiter* waiter, HandleSignalsState* signals_state); + MojoResult AddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + // Removes an awakable from this dispatcher. (It is valid to call this + // multiple times for the same |awakable| on the same object, so long as + // |AddAwakable()| was called at most once.) If |signals_state| is non-null, + // |*signals_state| will be set to the current handle signals state. + void RemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state); // A dispatcher must be put into a special state in order to be sent across a // message pipe. Outside of tests, only |HandleTableAccess| is allowed to do @@ -220,9 +220,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher virtual ~Dispatcher(); // These are to be overridden by subclasses (if necessary). They are called - // exactly once -- first |CancelAllWaitersNoLock()|, then |CloseImplNoLock()|, + // exactly once -- first |CancelAllAwakablesNoLock()|, then + // |CloseImplNoLock()|, // when the dispatcher is being closed. They are called under |lock_|. - virtual void CancelAllWaitersNoLock(); + virtual void CancelAllAwakablesNoLock(); virtual void CloseImplNoLock(); virtual scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() = 0; @@ -266,12 +267,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Dispatcher MojoMapBufferFlags flags, scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping); virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const; - virtual MojoResult AddWaiterImplNoLock(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - virtual void RemoveWaiterImplNoLock(Waiter* waiter, - HandleSignalsState* signals_state); + virtual MojoResult AddAwakableImplNoLock(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + virtual void RemoveAwakableImplNoLock(Awakable* awakable, + HandleSignalsState* signals_state); // These implement the API used to serialize dispatchers to a |Channel| // (described below). They will only be called on a dispatcher that's attached diff --git a/mojo/edk/system/dispatcher_unittest.cc b/mojo/edk/system/dispatcher_unittest.cc index 0b15436..97e2eed 100644 --- a/mojo/edk/system/dispatcher_unittest.cc +++ b/mojo/edk/system/dispatcher_unittest.cc @@ -67,16 +67,16 @@ TEST(DispatcherTest, Basic) { w.Init(); HandleSignalsState hss; EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d->AddWaiter(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); + d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); // Okay to remove even if it wasn't added (or was already removed). hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); @@ -104,11 +104,11 @@ TEST(DispatcherTest, Basic) { EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, d->EndReadData(0)); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->AddWaiter(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); + d->AddAwakable(&w, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); } @@ -212,8 +212,8 @@ class ThreadSafetyStressThread : public base::SimpleThread { } case ADD_WAITER: { HandleSignalsState hss; - MojoResult r = - dispatcher_->AddWaiter(&waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss); + MojoResult r = dispatcher_->AddAwakable( + &waiter_, ~MOJO_HANDLE_SIGNAL_NONE, 0, &hss); EXPECT_TRUE(r == MOJO_RESULT_FAILED_PRECONDITION || r == MOJO_RESULT_INVALID_ARGUMENT); EXPECT_EQ(0u, hss.satisfied_signals); @@ -222,7 +222,7 @@ class ThreadSafetyStressThread : public base::SimpleThread { } case REMOVE_WAITER: { HandleSignalsState hss; - dispatcher_->RemoveWaiter(&waiter_, &hss); + dispatcher_->RemoveAwakable(&waiter_, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); break; @@ -234,7 +234,7 @@ class ThreadSafetyStressThread : public base::SimpleThread { // Always try to remove the waiter, in case we added it. HandleSignalsState hss; - dispatcher_->RemoveWaiter(&waiter_, &hss); + dispatcher_->RemoveAwakable(&waiter_, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); } diff --git a/mojo/edk/system/endpoint_relayer.cc b/mojo/edk/system/endpoint_relayer.cc new file mode 100644 index 0000000..52faefa --- /dev/null +++ b/mojo/edk/system/endpoint_relayer.cc @@ -0,0 +1,70 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "mojo/edk/system/endpoint_relayer.h" + +#include "base/logging.h" +#include "mojo/edk/system/channel_endpoint.h" +#include "mojo/edk/system/message_in_transit.h" + +namespace mojo { +namespace system { + +EndpointRelayer::EndpointRelayer() { +} + +// static +unsigned EndpointRelayer::GetPeerPort(unsigned port) { + DCHECK(port == 0 || port == 1); + return port ^ 1; +} + +void EndpointRelayer::Init(ChannelEndpoint* endpoint0, + ChannelEndpoint* endpoint1) { + DCHECK(endpoint0); + DCHECK(endpoint1); + DCHECK(!endpoints_[0]); + DCHECK(!endpoints_[1]); + endpoints_[0] = endpoint0; + endpoints_[1] = endpoint1; +} + +bool EndpointRelayer::OnReadMessage(unsigned port, MessageInTransit* message) { + DCHECK(message); + + base::AutoLock locker(lock_); + + // If we're no longer the client, then reject the message. + if (!endpoints_[port]) + return false; + + // Otherwise, consume it even if the peer port is closed. + unsigned peer_port = GetPeerPort(port); + if (endpoints_[peer_port]) + endpoints_[peer_port]->EnqueueMessage(make_scoped_ptr(message)); + return true; +} + +void EndpointRelayer::OnDetachFromChannel(unsigned port) { + base::AutoLock locker(lock_); + + if (endpoints_[port]) { + endpoints_[port]->DetachFromClient(); + endpoints_[port] = nullptr; + } + + unsigned peer_port = GetPeerPort(port); + if (endpoints_[peer_port]) { + endpoints_[peer_port]->DetachFromClient(); + endpoints_[peer_port] = nullptr; + } +} + +EndpointRelayer::~EndpointRelayer() { + DCHECK(!endpoints_[0]); + DCHECK(!endpoints_[1]); +} + +} // namespace system +} // namespace mojo diff --git a/mojo/edk/system/endpoint_relayer.h b/mojo/edk/system/endpoint_relayer.h new file mode 100644 index 0000000..4084452 --- /dev/null +++ b/mojo/edk/system/endpoint_relayer.h @@ -0,0 +1,49 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ +#define MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "mojo/edk/system/channel_endpoint_client.h" +#include "mojo/edk/system/system_impl_export.h" + +namespace mojo { +namespace system { + +class ChannelEndpoint; + +// This is a simple |ChannelEndpointClient| that just relays messages between +// two |ChannelEndpoint|s (without the overhead of |MessagePipe|). +class MOJO_SYSTEM_IMPL_EXPORT EndpointRelayer : public ChannelEndpointClient { + public: + EndpointRelayer(); + + // Gets the other port number (i.e., 0 -> 1, 1 -> 0). + static unsigned GetPeerPort(unsigned port); + + // Initialize this object. This must be called before any other method. + void Init(ChannelEndpoint* endpoint0, ChannelEndpoint* endpoint1); + + // |ChannelEndpointClient| methods: + bool OnReadMessage(unsigned port, MessageInTransit* message) override; + void OnDetachFromChannel(unsigned port) override; + + private: + virtual ~EndpointRelayer(); + + // TODO(vtl): We could probably get away without the lock if we had a + // thread-safe |scoped_refptr|. + base::Lock lock_; // Protects the following members. + scoped_refptr<ChannelEndpoint> endpoints_[2]; + + DISALLOW_COPY_AND_ASSIGN(EndpointRelayer); +}; + +} // namespace system +} // namespace mojo + +#endif // MOJO_EDK_SYSTEM_ENDPOINT_RELAYER_H_ diff --git a/mojo/edk/system/handle_table.cc b/mojo/edk/system/handle_table.cc index 05d5260..e054919 100644 --- a/mojo/edk/system/handle_table.cc +++ b/mojo/edk/system/handle_table.cc @@ -91,7 +91,7 @@ bool HandleTable::AddDispatcherVector(const DispatcherVector& dispatchers, return false; for (size_t i = 0; i < dispatchers.size(); i++) { - if (dispatchers[i].get()) { + if (dispatchers[i]) { handles[i] = AddDispatcherNoSizeCheck(dispatchers[i]); } else { LOG(WARNING) << "Invalid dispatcher at index " << i; @@ -188,7 +188,7 @@ MojoResult HandleTable::MarkBusyAndStartTransport( MojoHandle HandleTable::AddDispatcherNoSizeCheck( const scoped_refptr<Dispatcher>& dispatcher) { - DCHECK(dispatcher.get()); + DCHECK(dispatcher); DCHECK_LT(handle_to_entry_map_.size(), GetConfiguration().max_handle_table_size); DCHECK_NE(next_handle_, MOJO_HANDLE_INVALID); diff --git a/mojo/edk/system/local_data_pipe_unittest.cc b/mojo/edk/system/local_data_pipe_unittest.cc index cea50a0..1223a2ba 100644 --- a/mojo/edk/system/local_data_pipe_unittest.cc +++ b/mojo/edk/system/local_data_pipe_unittest.cc @@ -237,7 +237,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_FAILED_PRECONDITION, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -247,7 +247,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 34, &hss)); // Write two elements. int32_t elements[2] = {123, 456}; @@ -259,13 +259,13 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { // Adding a waiter should now succeed. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, + nullptr)); // And it shouldn't be writable yet. EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -283,22 +283,22 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { // Add a waiter. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 56, + nullptr)); // And it still shouldn't be writable yet. EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); // Do it again. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 78, + nullptr)); // Read one element. elements[0] = -1; @@ -315,7 +315,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); EXPECT_EQ(78u, context); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -335,9 +335,9 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { // Add a waiter. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 90, + nullptr)); // Read one element, using a two-phase read. const void* read_buffer = nullptr; @@ -359,7 +359,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); EXPECT_EQ(90u, context); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -374,9 +374,9 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { // Add a waiter. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, + nullptr)); // Close the consumer. dp->ConsumerClose(); @@ -385,7 +385,7 @@ TEST(LocalDataPipeTest, BasicProducerWaiting) { EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context)); EXPECT_EQ(12u, context); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -412,8 +412,8 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) { // Add a waiter. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, - nullptr)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, + 12, nullptr)); // Close the consumer. dp->ConsumerClose(); @@ -423,7 +423,7 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); EXPECT_EQ(12u, context); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -436,8 +436,8 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) { // Add a waiter. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, - nullptr)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, + 12, nullptr)); // Close the producer. dp->ProducerClose(); @@ -447,7 +447,7 @@ TEST(LocalDataPipeTest, PeerClosedWaiting) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); EXPECT_EQ(12u, context); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -475,9 +475,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Never writable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, &hss)); + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, + &hss)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -485,11 +485,11 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Not yet readable. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, - nullptr)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -504,9 +504,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should already be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -520,9 +520,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should still be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -541,9 +541,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should still be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -562,8 +562,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Adding a waiter should now succeed. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90, - nullptr)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 90, + nullptr)); // Write one element. elements[0] = 789; @@ -577,7 +577,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context)); EXPECT_EQ(90u, context); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -588,9 +588,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should still be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -610,9 +610,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should be never-readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_FAILED_PRECONDITION, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss)); + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -646,9 +646,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should already be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -670,9 +670,9 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Should still be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ( - MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss)); + EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, + &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -694,8 +694,8 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { // Adding a waiter should now succeed. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, - nullptr)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, + nullptr)); // Close the producer. dp->ProducerClose(); @@ -704,7 +704,7 @@ TEST(LocalDataPipeTest, BasicConsumerWaiting) { EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(1000, &context)); EXPECT_EQ(56u, context); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -733,7 +733,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -748,24 +748,24 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { // At this point, it shouldn't be writable. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 1, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ProducerRemoveWaiter(&waiter, &hss); + dp->ProducerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); // It shouldn't be readable yet either. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -779,7 +779,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -789,7 +789,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -809,7 +809,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -831,19 +831,19 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); // But not readable. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -856,7 +856,7 @@ TEST(LocalDataPipeTest, BasicTwoPhaseWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -886,19 +886,19 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); // Not readable. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -915,7 +915,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -925,7 +925,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -943,7 +943,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -953,7 +953,7 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -972,19 +972,19 @@ TEST(LocalDataPipeTest, BasicMayDiscardWaiting) { hss = HandleSignalsState(); EXPECT_EQ( MOJO_RESULT_ALREADY_EXISTS, - dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); + dp->ProducerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); // No longer readable. waiter.Init(); - ASSERT_EQ( - MOJO_RESULT_OK, - dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, nullptr)); + ASSERT_EQ(MOJO_RESULT_OK, + dp->ConsumerAddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, + nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - dp->ConsumerRemoveWaiter(&waiter, &hss); + dp->ConsumerRemoveAwakable(&waiter, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc index 86d241c..576ad50 100644 --- a/mojo/edk/system/local_message_pipe_endpoint.cc +++ b/mojo/edk/system/local_message_pipe_endpoint.cc @@ -35,7 +35,7 @@ bool LocalMessagePipeEndpoint::OnPeerClose() { HandleSignalsState new_state = GetHandleSignalsState(); if (!new_state.equals(old_state)) - waiter_list_.AwakeWaitersForStateChange(new_state); + awakable_list_.AwakeForStateChange(new_state); return true; } @@ -48,7 +48,7 @@ void LocalMessagePipeEndpoint::EnqueueMessage( bool was_empty = message_queue_.IsEmpty(); message_queue_.AddMessage(message.Pass()); if (was_empty) - waiter_list_.AwakeWaitersForStateChange(GetHandleSignalsState()); + awakable_list_.AwakeForStateChange(GetHandleSignalsState()); } void LocalMessagePipeEndpoint::Close() { @@ -57,9 +57,9 @@ void LocalMessagePipeEndpoint::Close() { message_queue_.Clear(); } -void LocalMessagePipeEndpoint::CancelAllWaiters() { +void LocalMessagePipeEndpoint::CancelAllAwakables() { DCHECK(is_open_); - waiter_list_.CancelAllWaiters(); + awakable_list_.CancelAll(); } MojoResult LocalMessagePipeEndpoint::ReadMessage( @@ -117,7 +117,7 @@ MojoResult LocalMessagePipeEndpoint::ReadMessage( if (message_queue_.IsEmpty()) { // It's currently not possible to wait for non-readability, but we should // do the state change anyway. - waiter_list_.AwakeWaitersForStateChange(GetHandleSignalsState()); + awakable_list_.AwakeForStateChange(GetHandleSignalsState()); } } @@ -144,8 +144,8 @@ HandleSignalsState LocalMessagePipeEndpoint::GetHandleSignalsState() const { return rv; } -MojoResult LocalMessagePipeEndpoint::AddWaiter( - Waiter* waiter, +MojoResult LocalMessagePipeEndpoint::AddAwakable( + Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { @@ -163,14 +163,15 @@ MojoResult LocalMessagePipeEndpoint::AddWaiter( return MOJO_RESULT_FAILED_PRECONDITION; } - waiter_list_.AddWaiter(waiter, signals, context); + awakable_list_.Add(awakable, signals, context); return MOJO_RESULT_OK; } -void LocalMessagePipeEndpoint::RemoveWaiter(Waiter* waiter, - HandleSignalsState* signals_state) { +void LocalMessagePipeEndpoint::RemoveAwakable( + Awakable* awakable, + HandleSignalsState* signals_state) { DCHECK(is_open_); - waiter_list_.RemoveWaiter(waiter); + awakable_list_.Remove(awakable); if (signals_state) *signals_state = GetHandleSignalsState(); } diff --git a/mojo/edk/system/local_message_pipe_endpoint.h b/mojo/edk/system/local_message_pipe_endpoint.h index 7eb3949..eb1c6ee 100644 --- a/mojo/edk/system/local_message_pipe_endpoint.h +++ b/mojo/edk/system/local_message_pipe_endpoint.h @@ -7,11 +7,11 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/handle_signals_state.h" #include "mojo/edk/system/message_in_transit_queue.h" #include "mojo/edk/system/message_pipe_endpoint.h" #include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/waiter_list.h" namespace mojo { namespace system { @@ -30,18 +30,19 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint // There's a dispatcher for |LocalMessagePipeEndpoint|s, so we have to // implement/override these: void Close() override; - void CancelAllWaiters() override; + void CancelAllAwakables() override; MojoResult ReadMessage(UserPointer<void> bytes, UserPointer<uint32_t> num_bytes, DispatcherVector* dispatchers, uint32_t* num_dispatchers, MojoReadMessageFlags flags) override; HandleSignalsState GetHandleSignalsState() const override; - MojoResult AddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) override; - void RemoveWaiter(Waiter* waiter, HandleSignalsState* signals_state) override; + MojoResult AddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) override; + void RemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state) override; // This is only to be used by |MessagePipe|: MessageInTransitQueue* message_queue() { return &message_queue_; } @@ -52,7 +53,7 @@ class MOJO_SYSTEM_IMPL_EXPORT LocalMessagePipeEndpoint // Queue of incoming messages. MessageInTransitQueue message_queue_; - WaiterList waiter_list_; + AwakableList awakable_list_; DISALLOW_COPY_AND_ASSIGN(LocalMessagePipeEndpoint); }; diff --git a/mojo/edk/system/message_in_transit.cc b/mojo/edk/system/message_in_transit.cc index 624a546..1387dd82 100644 --- a/mojo/edk/system/message_in_transit.cc +++ b/mojo/edk/system/message_in_transit.cc @@ -127,7 +127,7 @@ MessageInTransit::MessageInTransit(const View& message_view) MessageInTransit::~MessageInTransit() { if (dispatchers_) { for (size_t i = 0; i < dispatchers_->size(); i++) { - if (!(*dispatchers_)[i].get()) + if (!(*dispatchers_)[i]) continue; DCHECK((*dispatchers_)[i]->HasOneRef()); @@ -166,7 +166,7 @@ void MessageInTransit::SetDispatchers( dispatchers_ = dispatchers.Pass(); #ifndef NDEBUG for (size_t i = 0; i < dispatchers_->size(); i++) - DCHECK(!(*dispatchers_)[i].get() || (*dispatchers_)[i]->HasOneRef()); + DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef()); #endif } diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc index ee5036f..3e243b6 100644 --- a/mojo/edk/system/message_pipe.cc +++ b/mojo/edk/system/message_pipe.cc @@ -8,6 +8,7 @@ #include "mojo/edk/system/channel.h" #include "mojo/edk/system/channel_endpoint.h" #include "mojo/edk/system/channel_endpoint_id.h" +#include "mojo/edk/system/endpoint_relayer.h" #include "mojo/edk/system/local_message_pipe_endpoint.h" #include "mojo/edk/system/message_in_transit.h" #include "mojo/edk/system/message_pipe_dispatcher.h" @@ -41,7 +42,7 @@ MessagePipe* MessagePipe::CreateLocalLocal() { // static MessagePipe* MessagePipe::CreateLocalProxy( scoped_refptr<ChannelEndpoint>* channel_endpoint) { - DCHECK(!channel_endpoint->get()); // Not technically wrong, but unlikely. + DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. MessagePipe* message_pipe = new MessagePipe(); message_pipe->endpoints_[0].reset(new LocalMessagePipeEndpoint()); *channel_endpoint = new ChannelEndpoint(message_pipe, 1); @@ -53,7 +54,7 @@ MessagePipe* MessagePipe::CreateLocalProxy( // static MessagePipe* MessagePipe::CreateProxyLocal( scoped_refptr<ChannelEndpoint>* channel_endpoint) { - DCHECK(!channel_endpoint->get()); // Not technically wrong, but unlikely. + DCHECK(!*channel_endpoint); // Not technically wrong, but unlikely. MessagePipe* message_pipe = new MessagePipe(); *channel_endpoint = new ChannelEndpoint(message_pipe, 0); message_pipe->endpoints_[0].reset( @@ -74,7 +75,7 @@ bool MessagePipe::Deserialize(Channel* channel, size_t size, scoped_refptr<MessagePipe>* message_pipe, unsigned* port) { - DCHECK(!message_pipe->get()); // Not technically wrong, but unlikely. + DCHECK(!*message_pipe); // Not technically wrong, but unlikely. if (size != sizeof(SerializedMessagePipe)) { LOG(ERROR) << "Invalid serialized message pipe"; @@ -84,7 +85,7 @@ bool MessagePipe::Deserialize(Channel* channel, const SerializedMessagePipe* s = static_cast<const SerializedMessagePipe*>(source); *message_pipe = channel->PassIncomingMessagePipe(s->receiver_endpoint_id); - if (!message_pipe->get()) { + if (!*message_pipe) { LOG(ERROR) << "Failed to deserialize message pipe (ID = " << s->receiver_endpoint_id << ")"; return false; @@ -104,18 +105,18 @@ MessagePipeEndpoint::Type MessagePipe::GetType(unsigned port) { return endpoints_[port]->GetType(); } -void MessagePipe::CancelAllWaiters(unsigned port) { +void MessagePipe::CancelAllAwakables(unsigned port) { DCHECK(port == 0 || port == 1); base::AutoLock locker(lock_); DCHECK(endpoints_[port]); - endpoints_[port]->CancelAllWaiters(); + endpoints_[port]->CancelAllAwakables(); } void MessagePipe::Close(unsigned port) { DCHECK(port == 0 || port == 1); - unsigned destination_port = GetPeerPort(port); + unsigned peer_port = GetPeerPort(port); base::AutoLock locker(lock_); // The endpoint's |OnPeerClose()| may have been called first and returned @@ -124,9 +125,9 @@ void MessagePipe::Close(unsigned port) { return; endpoints_[port]->Close(); - if (endpoints_[destination_port]) { - if (!endpoints_[destination_port]->OnPeerClose()) - endpoints_[destination_port].reset(); + if (endpoints_[peer_port]) { + if (!endpoints_[peer_port]->OnPeerClose()) + endpoints_[peer_port].reset(); } endpoints_[port].reset(); } @@ -139,7 +140,9 @@ MojoResult MessagePipe::WriteMessage( std::vector<DispatcherTransport>* transports, MojoWriteMessageFlags flags) { DCHECK(port == 0 || port == 1); - return EnqueueMessage( + + base::AutoLock locker(lock_); + return EnqueueMessageNoLock( GetPeerPort(port), make_scoped_ptr(new MessageInTransit( MessageInTransit::kTypeEndpoint, @@ -171,28 +174,29 @@ HandleSignalsState MessagePipe::GetHandleSignalsState(unsigned port) const { return endpoints_[port]->GetHandleSignalsState(); } -MojoResult MessagePipe::AddWaiter(unsigned port, - Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) { +MojoResult MessagePipe::AddAwakable(unsigned port, + Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) { DCHECK(port == 0 || port == 1); base::AutoLock locker(lock_); DCHECK(endpoints_[port]); - return endpoints_[port]->AddWaiter(waiter, signals, context, signals_state); + return endpoints_[port]->AddAwakable(awakable, signals, context, + signals_state); } -void MessagePipe::RemoveWaiter(unsigned port, - Waiter* waiter, - HandleSignalsState* signals_state) { +void MessagePipe::RemoveAwakable(unsigned port, + Awakable* awakable, + HandleSignalsState* signals_state) { DCHECK(port == 0 || port == 1); base::AutoLock locker(lock_); DCHECK(endpoints_[port]); - endpoints_[port]->RemoveWaiter(waiter, signals_state); + endpoints_[port]->RemoveAwakable(awakable, signals_state); } void MessagePipe::StartSerialize(unsigned /*port*/, @@ -243,16 +247,17 @@ bool MessagePipe::EndSerialize( // We also pass its |ChannelEndpoint| to the channel, which then decides // what to do. We have no reason to continue to exist. // - // TODO(vtl): Factor some of this out to |ChannelEndpoint|. + // TODO(vtl): Factor some of this out to |ChannelEndpoint| (or |Channel|). - if (!endpoints_[GetPeerPort(port)]) { + unsigned peer_port = GetPeerPort(port); + if (!endpoints_[peer_port]) { // Case 1. channel_endpoint = new ChannelEndpoint( nullptr, 0, static_cast<LocalMessagePipeEndpoint*>( endpoints_[port].get())->message_queue()); endpoints_[port]->Close(); endpoints_[port].reset(); - } else if (endpoints_[GetPeerPort(port)]->GetType() == + } else if (endpoints_[peer_port]->GetType() == MessagePipeEndpoint::kTypeLocal) { // Case 2. channel_endpoint = new ChannelEndpoint( @@ -263,15 +268,44 @@ bool MessagePipe::EndSerialize( new ProxyMessagePipeEndpoint(channel_endpoint.get())); } else { // Case 3. - // TODO(vtl): Temporarily the same as case 2. DLOG(WARNING) << "Direct message pipe passing across multiple channels " "not yet implemented; will proxy"; + + // Create an |EndpointRelayer| to replace ourselves (rather than having a + // |MessagePipe| object that exists solely to relay messages between two + // |ChannelEndpoint|s, owned by the |Channel| through them. + // + // This reduces overhead somewhat, and more importantly restores some + // invariants, e.g., that |MessagePipe|s are owned by dispatchers. + // + // TODO(vtl): If we get the |Channel| to own/track the relayer directly, + // then possibly we could make |ChannelEndpoint|'s |client_| pointer a raw + // pointer (and not have the |Channel| owning the relayer via its + // |ChannelEndpoint|s. + // + // TODO(vtl): This is not obviously the right place for (all of) this + // logic, nor is it obviously factored correctly. + + DCHECK_EQ(endpoints_[peer_port]->GetType(), + MessagePipeEndpoint::kTypeProxy); + ProxyMessagePipeEndpoint* peer_endpoint = + static_cast<ProxyMessagePipeEndpoint*>(endpoints_[peer_port].get()); + scoped_refptr<ChannelEndpoint> peer_channel_endpoint = + peer_endpoint->ReleaseChannelEndpoint(); + + scoped_refptr<EndpointRelayer> relayer(new EndpointRelayer()); + // We'll assign our peer port's endpoint to the relayer's port 1, and this + // port's endpoint to the relayer's port 0. channel_endpoint = new ChannelEndpoint( - this, port, static_cast<LocalMessagePipeEndpoint*>( - endpoints_[port].get())->message_queue()); + relayer.get(), 0, static_cast<LocalMessagePipeEndpoint*>( + endpoints_[port].get())->message_queue()); + relayer->Init(channel_endpoint.get(), peer_channel_endpoint.get()); + peer_channel_endpoint->ReplaceClient(relayer.get(), 1); + endpoints_[port]->Close(); - endpoints_[port].reset( - new ProxyMessagePipeEndpoint(channel_endpoint.get())); + endpoints_[port].reset(); + // No need to call |Close()| after |ReleaseChannelEndpoint()|. + endpoints_[peer_port].reset(); } } @@ -287,16 +321,27 @@ bool MessagePipe::EndSerialize( return true; } -void MessagePipe::OnReadMessage(unsigned port, - scoped_ptr<MessageInTransit> message) { +bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) { + base::AutoLock locker(lock_); + + if (!endpoints_[port]) { + // This will happen only on the rare occasion that the call to + // |OnReadMessage()| is racing with us calling + // |ChannelEndpoint::ReplaceClient()|, in which case we reject the message, + // and the |ChannelEndpoint| can retry (calling the new client's + // |OnReadMessage()|). + return false; + } + // This is called when the |ChannelEndpoint| for the // |ProxyMessagePipeEndpoint| |port| receives a message (from the |Channel|). // We need to pass this message on to its peer port (typically a // |LocalMessagePipeEndpoint|). - MojoResult result = - EnqueueMessage(GetPeerPort(port), message.Pass(), nullptr); + MojoResult result = EnqueueMessageNoLock(GetPeerPort(port), + make_scoped_ptr(message), nullptr); DLOG_IF(WARNING, result != MOJO_RESULT_OK) - << "EnqueueMessage() failed (result = " << result << ")"; + << "EnqueueMessageNoLock() failed (result = " << result << ")"; + return true; } void MessagePipe::OnDetachFromChannel(unsigned port) { @@ -314,7 +359,7 @@ MessagePipe::~MessagePipe() { DCHECK(!endpoints_[1]); } -MojoResult MessagePipe::EnqueueMessage( +MojoResult MessagePipe::EnqueueMessageNoLock( unsigned port, scoped_ptr<MessageInTransit> message, std::vector<DispatcherTransport>* transports) { @@ -322,8 +367,6 @@ MojoResult MessagePipe::EnqueueMessage( DCHECK(message); DCHECK_EQ(message->type(), MessageInTransit::kTypeEndpoint); - - base::AutoLock locker(lock_); DCHECK(endpoints_[GetPeerPort(port)]); // The destination port need not be open, unlike the source port. diff --git a/mojo/edk/system/message_pipe.h b/mojo/edk/system/message_pipe.h index e8f97d0..431b5a6 100644 --- a/mojo/edk/system/message_pipe.h +++ b/mojo/edk/system/message_pipe.h @@ -28,9 +28,9 @@ namespace mojo { namespace system { +class Awakable; class Channel; class ChannelEndpoint; -class Waiter; // |MessagePipe| is the secondary object implementing a message pipe (see the // explanatory comment in core.cc). It is typically owned by the dispatcher(s) @@ -72,7 +72,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient { // These are called by the dispatcher to implement its methods of // corresponding names. In all cases, the port |port| must be open. - void CancelAllWaiters(unsigned port); + void CancelAllAwakables(unsigned port); void Close(unsigned port); // Unlike |MessagePipeDispatcher::WriteMessage()|, this does not validate its // arguments. @@ -88,14 +88,14 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient { uint32_t* num_dispatchers, MojoReadMessageFlags flags); HandleSignalsState GetHandleSignalsState(unsigned port) const; - MojoResult AddWaiter(unsigned port, - Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - void RemoveWaiter(unsigned port, - Waiter* waiter, - HandleSignalsState* signals_state); + MojoResult AddAwakable(unsigned port, + Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + void RemoveAwakable(unsigned port, + Awakable* awakable, + HandleSignalsState* signals_state); void StartSerialize(unsigned port, Channel* channel, size_t* max_size, @@ -107,8 +107,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient { embedder::PlatformHandleVector* platform_handles); // |ChannelEndpointClient| methods: - void OnReadMessage(unsigned port, - scoped_ptr<MessageInTransit> message) override; + bool OnReadMessage(unsigned port, MessageInTransit* message) override; void OnDetachFromChannel(unsigned port) override; private: @@ -117,12 +116,12 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipe : public ChannelEndpointClient { // This is used internally by |WriteMessage()| and by |OnReadMessage()|. // |transports| may be non-null only if it's nonempty and |message| has no - // dispatchers attached. - MojoResult EnqueueMessage(unsigned port, - scoped_ptr<MessageInTransit> message, - std::vector<DispatcherTransport>* transports); + // dispatchers attached. Must be called with |lock_| held. + MojoResult EnqueueMessageNoLock(unsigned port, + scoped_ptr<MessageInTransit> message, + std::vector<DispatcherTransport>* transports); - // Helper for |EnqueueMessage()|. Must be called with |lock_| held. + // Helper for |EnqueueMessageNoLock()|. Must be called with |lock_| held. MojoResult AttachTransportsNoLock( unsigned port, MessageInTransit* message, diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc index df861df..a6733dbe 100644 --- a/mojo/edk/system/message_pipe_dispatcher.cc +++ b/mojo/edk/system/message_pipe_dispatcher.cc @@ -60,7 +60,7 @@ MojoResult MessagePipeDispatcher::ValidateCreateOptions( void MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe, unsigned port) { - DCHECK(message_pipe.get()); + DCHECK(message_pipe); DCHECK(port == 0 || port == 1); message_pipe_ = message_pipe; @@ -92,7 +92,7 @@ scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( scoped_refptr<MessagePipe> message_pipe; if (!MessagePipe::Deserialize(channel, source, size, &message_pipe, &port)) return nullptr; - DCHECK(message_pipe.get()); + DCHECK(message_pipe); DCHECK(port == 0 || port == 1); scoped_refptr<MessagePipeDispatcher> dispatcher( @@ -103,7 +103,7 @@ scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( MessagePipeDispatcher::~MessagePipeDispatcher() { // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. - DCHECK(!message_pipe_.get()); + DCHECK(!message_pipe_); } MessagePipe* MessagePipeDispatcher::GetMessagePipeNoLock() const { @@ -116,9 +116,9 @@ unsigned MessagePipeDispatcher::GetPortNoLock() const { return port_; } -void MessagePipeDispatcher::CancelAllWaitersNoLock() { +void MessagePipeDispatcher::CancelAllAwakablesNoLock() { lock().AssertAcquired(); - message_pipe_->CancelAllWaiters(port_); + message_pipe_->CancelAllAwakables(port_); } void MessagePipeDispatcher::CloseImplNoLock() { @@ -178,21 +178,21 @@ HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateImplNoLock() return message_pipe_->GetHandleSignalsState(port_); } -MojoResult MessagePipeDispatcher::AddWaiterImplNoLock( - Waiter* waiter, +MojoResult MessagePipeDispatcher::AddAwakableImplNoLock( + Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { lock().AssertAcquired(); - return message_pipe_->AddWaiter(port_, waiter, signals, context, - signals_state); + return message_pipe_->AddAwakable(port_, awakable, signals, context, + signals_state); } -void MessagePipeDispatcher::RemoveWaiterImplNoLock( - Waiter* waiter, +void MessagePipeDispatcher::RemoveAwakableImplNoLock( + Awakable* awakable, HandleSignalsState* signals_state) { lock().AssertAcquired(); - message_pipe_->RemoveWaiter(port_, waiter, signals_state); + message_pipe_->RemoveAwakable(port_, awakable, signals_state); } void MessagePipeDispatcher::StartSerializeImplNoLock( diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h index 9afdb70..fb16dd3 100644 --- a/mojo/edk/system/message_pipe_dispatcher.h +++ b/mojo/edk/system/message_pipe_dispatcher.h @@ -73,7 +73,7 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher : public Dispatcher { unsigned GetPortNoLock() const; // |Dispatcher| protected methods: - void CancelAllWaitersNoLock() override; + void CancelAllAwakablesNoLock() override; void CloseImplNoLock() override; scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override; @@ -88,12 +88,12 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeDispatcher : public Dispatcher { uint32_t* num_dispatchers, MojoReadMessageFlags flags) override; HandleSignalsState GetHandleSignalsStateImplNoLock() const override; - MojoResult AddWaiterImplNoLock(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) override; - void RemoveWaiterImplNoLock(Waiter* waiter, - HandleSignalsState* signals_state) override; + MojoResult AddAwakableImplNoLock(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) override; + void RemoveAwakableImplNoLock(Awakable* awakable, + HandleSignalsState* signals_state) override; void StartSerializeImplNoLock(Channel* channel, size_t* max_size, size_t* max_platform_handles) override; diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc index 303ae6a..b5562b0 100644 --- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc +++ b/mojo/edk/system/message_pipe_dispatcher_unittest.cc @@ -59,7 +59,7 @@ TEST(MessagePipeDispatcherTest, Basic) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); // Shouldn't need to remove the waiter (it was not added). @@ -68,7 +68,7 @@ TEST(MessagePipeDispatcherTest, Basic) { // |d1|), then wait. w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); buffer[0] = 123456789; EXPECT_EQ(MOJO_RESULT_OK, d1->WriteMessage(UserPointer<const void>(buffer), kBufferSize, @@ -78,7 +78,7 @@ TEST(MessagePipeDispatcherTest, Basic) { EXPECT_EQ(1u, context); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); hss = HandleSignalsState(); - d0->RemoveWaiter(&w, &hss); + d0->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -87,7 +87,7 @@ TEST(MessagePipeDispatcherTest, Basic) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -106,19 +106,19 @@ TEST(MessagePipeDispatcherTest, Basic) { // Wait for zero time for readability on |d0| (will time out). w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); hss = HandleSignalsState(); - d0->RemoveWaiter(&w, &hss); + d0->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); // Wait for non-zero, finite time for readability on |d0| (will time out). w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr)); @@ -126,14 +126,14 @@ TEST(MessagePipeDispatcherTest, Basic) { EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); hss = HandleSignalsState(); - d0->RemoveWaiter(&w, &hss); + d0->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); // Check the peer closed signal. w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, nullptr)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, nullptr)); // Close the peer. EXPECT_EQ(MOJO_RESULT_OK, d1->Close()); @@ -142,7 +142,7 @@ TEST(MessagePipeDispatcherTest, Basic) { EXPECT_EQ(MOJO_RESULT_OK, w.Wait(1000, &context)); EXPECT_EQ(12u, context); hss = HandleSignalsState(); - d0->RemoveWaiter(&w, &hss); + d0->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -249,7 +249,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -269,7 +269,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -289,7 +289,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -309,7 +309,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -317,7 +317,7 @@ TEST(MessagePipeDispatcherTest, BasicClosed) { w.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); + d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -559,15 +559,15 @@ class ReaderThread : public base::SimpleThread { // Wait for it to be readable. w.Init(); hss = HandleSignalsState(); - result = - read_dispatcher_->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss); + result = read_dispatcher_->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, + &hss); EXPECT_TRUE(result == MOJO_RESULT_OK || result == MOJO_RESULT_ALREADY_EXISTS) << "result: " << result; if (result == MOJO_RESULT_OK) { // Actually need to wait. EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, nullptr)); - read_dispatcher_->RemoveWaiter(&w, &hss); + read_dispatcher_->RemoveAwakable(&w, &hss); } // We may not actually be readable, since we're racing with other threads. EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); diff --git a/mojo/edk/system/message_pipe_endpoint.cc b/mojo/edk/system/message_pipe_endpoint.cc index df623d4..4b8bc5e 100644 --- a/mojo/edk/system/message_pipe_endpoint.cc +++ b/mojo/edk/system/message_pipe_endpoint.cc @@ -9,7 +9,7 @@ namespace mojo { namespace system { -void MessagePipeEndpoint::CancelAllWaiters() { +void MessagePipeEndpoint::CancelAllAwakables() { NOTREACHED(); } @@ -27,18 +27,18 @@ HandleSignalsState MessagePipeEndpoint::GetHandleSignalsState() const { return HandleSignalsState(); } -MojoResult MessagePipeEndpoint::AddWaiter(Waiter* /*waiter*/, - MojoHandleSignals /*signals*/, - uint32_t /*context*/, - HandleSignalsState* signals_state) { +MojoResult MessagePipeEndpoint::AddAwakable(Awakable* /*awakable*/, + MojoHandleSignals /*signals*/, + uint32_t /*context*/, + HandleSignalsState* signals_state) { NOTREACHED(); if (signals_state) *signals_state = HandleSignalsState(); return MOJO_RESULT_INTERNAL; } -void MessagePipeEndpoint::RemoveWaiter(Waiter* /*waiter*/, - HandleSignalsState* signals_state) { +void MessagePipeEndpoint::RemoveAwakable(Awakable* /*awakable*/, + HandleSignalsState* signals_state) { NOTREACHED(); if (signals_state) *signals_state = HandleSignalsState(); diff --git a/mojo/edk/system/message_pipe_endpoint.h b/mojo/edk/system/message_pipe_endpoint.h index 7bc0a0d..0b5f12e 100644 --- a/mojo/edk/system/message_pipe_endpoint.h +++ b/mojo/edk/system/message_pipe_endpoint.h @@ -23,7 +23,7 @@ namespace mojo { namespace system { class ChannelEndpoint; -class Waiter; +class Awakable; // This is an interface to one of the ends of a message pipe, and is used by // |MessagePipe|. Its most important role is to provide a sink for messages @@ -58,18 +58,19 @@ class MOJO_SYSTEM_IMPL_EXPORT MessagePipeEndpoint { // These methods implement the methods of the same name in |MessagePipe|, // though |MessagePipe|'s implementation may have to do a little more if the // operation involves both endpoints. - virtual void CancelAllWaiters(); + virtual void CancelAllAwakables(); virtual MojoResult ReadMessage(UserPointer<void> bytes, UserPointer<uint32_t> num_bytes, DispatcherVector* dispatchers, uint32_t* num_dispatchers, MojoReadMessageFlags flags); virtual HandleSignalsState GetHandleSignalsState() const; - virtual MojoResult AddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state); - virtual void RemoveWaiter(Waiter* waiter, HandleSignalsState* signals_state); + virtual MojoResult AddAwakable(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state); + virtual void RemoveAwakable(Awakable* awakable, + HandleSignalsState* signals_state); // Implementations must override these if they represent a proxy endpoint. An // implementation for a local endpoint needs not override these methods, since diff --git a/mojo/edk/system/message_pipe_test_utils.cc b/mojo/edk/system/message_pipe_test_utils.cc index e5df26d..38fc899 100644 --- a/mojo/edk/system/message_pipe_test_utils.cc +++ b/mojo/edk/system/message_pipe_test_utils.cc @@ -21,14 +21,15 @@ MojoResult WaitIfNecessary(scoped_refptr<MessagePipe> mp, Waiter waiter; waiter.Init(); - MojoResult add_result = mp->AddWaiter(0, &waiter, signals, 0, signals_state); + MojoResult add_result = + mp->AddAwakable(0, &waiter, signals, 0, signals_state); if (add_result != MOJO_RESULT_OK) { return (add_result == MOJO_RESULT_ALREADY_EXISTS) ? MOJO_RESULT_OK : add_result; } MojoResult wait_result = waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr); - mp->RemoveWaiter(0, &waiter, signals_state); + mp->RemoveAwakable(0, &waiter, signals_state); return wait_result; } @@ -51,7 +52,7 @@ void ChannelThread::Start(embedder::ScopedPlatformHandle platform_handle, } void ChannelThread::Stop() { - if (channel_.get()) { + if (channel_) { // Hack to flush write buffers before quitting. // TODO(vtl): Remove this once |Channel| has a // |FlushWriteBufferAndShutdown()| (or whatever). @@ -85,7 +86,7 @@ void ChannelThread::InitChannelOnIOThread( } void ChannelThread::ShutdownChannelOnIOThread() { - CHECK(channel_.get()); + CHECK(channel_); channel_->Shutdown(); channel_ = nullptr; } diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc index c700891..a30b636 100644 --- a/mojo/edk/system/message_pipe_unittest.cc +++ b/mojo/edk/system/message_pipe_unittest.cc @@ -337,25 +337,26 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE, - 0, &hss)); + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE | + MOJO_HANDLE_SIGNAL_WRITABLE, + 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); // Not yet readable. waiter.Init(); - ASSERT_EQ(MOJO_RESULT_OK, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); + ASSERT_EQ( + MOJO_RESULT_OK, + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - mp->RemoveWaiter(0, &waiter, &hss); + mp->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -363,10 +364,10 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr)); + mp->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr)); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); hss = HandleSignalsState(); - mp->RemoveWaiter(0, &waiter, &hss); + mp->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -380,16 +381,16 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE | - MOJO_HANDLE_SIGNAL_WRITABLE, - 0, &hss)); + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE | + MOJO_HANDLE_SIGNAL_WRITABLE, + 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -397,7 +398,7 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -408,8 +409,9 @@ TEST(MessagePipeTest, BasicWaiting) { // Port 1 should be signaled with peer closed. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 5, &hss)); + EXPECT_EQ( + MOJO_RESULT_ALREADY_EXISTS, + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 5, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -419,7 +421,7 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -429,7 +431,7 @@ TEST(MessagePipeTest, BasicWaiting) { waiter.Init(); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, &hss)); + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -447,8 +449,9 @@ TEST(MessagePipeTest, BasicWaiting) { // Now port 1 should no longer be readable. waiter.Init(); hss = HandleSignalsState(); - EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr)); + EXPECT_EQ( + MOJO_RESULT_FAILED_PRECONDITION, + mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); @@ -469,8 +472,8 @@ TEST(MessagePipeTest, ThreadedWaiting) { thread.waiter()->Init(); ASSERT_EQ(MOJO_RESULT_OK, - mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1, - nullptr)); + mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, + 1, nullptr)); thread.Start(); buffer[0] = 123456789; @@ -480,7 +483,7 @@ TEST(MessagePipeTest, ThreadedWaiting) { nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE)); HandleSignalsState hss; - mp->RemoveWaiter(1, thread.waiter(), &hss); + mp->RemoveAwakable(1, thread.waiter(), &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -499,16 +502,16 @@ TEST(MessagePipeTest, ThreadedWaiting) { thread.waiter()->Init(); ASSERT_EQ(MOJO_RESULT_OK, - mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 2, - nullptr)); + mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, + 2, nullptr)); thread.Start(); // Close port 1 first -- this should result in the waiter being cancelled. - mp->CancelAllWaiters(1); + mp->CancelAllAwakables(1); mp->Close(1); - // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the - // |MessagePipe| to remove any waiter. + // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into + // the |MessagePipe| to remove any waiter. mp->Close(0); } // Joins |thread|. @@ -522,16 +525,16 @@ TEST(MessagePipeTest, ThreadedWaiting) { thread.waiter()->Init(); ASSERT_EQ(MOJO_RESULT_OK, - mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, - 3, nullptr)); + mp->AddAwakable(1, thread.waiter(), + MOJO_HANDLE_SIGNAL_PEER_CLOSED, 3, nullptr)); thread.Start(); // Close port 1 first -- this should result in the waiter being cancelled. - mp->CancelAllWaiters(1); + mp->CancelAllAwakables(1); mp->Close(1); - // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the - // |MessagePipe| to remove any waiter. + // Port 1 is closed, so |Dispatcher::RemoveAwakable()| wouldn't call into + // the |MessagePipe| to remove any waiter. mp->Close(0); } // Joins |thread|. @@ -545,21 +548,21 @@ TEST(MessagePipeTest, ThreadedWaiting) { thread.waiter()->Init(); ASSERT_EQ(MOJO_RESULT_OK, - mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 4, - nullptr)); + mp->AddAwakable(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, + 4, nullptr)); thread.Start(); // Close port 0 first -- this should wake the waiter up, since port 1 will // never be readable. - mp->CancelAllWaiters(0); + mp->CancelAllAwakables(0); mp->Close(0); HandleSignalsState hss; - mp->RemoveWaiter(1, thread.waiter(), &hss); + mp->RemoveAwakable(1, thread.waiter(), &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); - mp->CancelAllWaiters(1); + mp->CancelAllAwakables(1); mp->Close(1); } // Joins |thread|. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc index f486152..4d8380b 100644 --- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc +++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc @@ -316,7 +316,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); - ASSERT_TRUE(dispatcher.get()); + ASSERT_TRUE(dispatcher); // Make a mapping. scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc index 1d784a6..dae53b4 100644 --- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc +++ b/mojo/edk/system/platform_handle_dispatcher_unittest.cc @@ -84,7 +84,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) { scoped_refptr<Dispatcher> generic_dispatcher = transport.CreateEquivalentDispatcherAndClose(); - ASSERT_TRUE(generic_dispatcher.get()); + ASSERT_TRUE(generic_dispatcher); transport.End(); EXPECT_TRUE(dispatcher->HasOneRef()); diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.cc b/mojo/edk/system/proxy_message_pipe_endpoint.cc index 4a954d9..5f0f2e9 100644 --- a/mojo/edk/system/proxy_message_pipe_endpoint.cc +++ b/mojo/edk/system/proxy_message_pipe_endpoint.cc @@ -20,7 +20,15 @@ ProxyMessagePipeEndpoint::ProxyMessagePipeEndpoint( } ProxyMessagePipeEndpoint::~ProxyMessagePipeEndpoint() { - DCHECK(!channel_endpoint_.get()); + DCHECK(!channel_endpoint_); +} + +scoped_refptr<ChannelEndpoint> +ProxyMessagePipeEndpoint::ReleaseChannelEndpoint() { + DCHECK(channel_endpoint_); + scoped_refptr<ChannelEndpoint> rv; + rv.swap(channel_endpoint_); + return rv; } MessagePipeEndpoint::Type ProxyMessagePipeEndpoint::GetType() const { @@ -37,7 +45,7 @@ bool ProxyMessagePipeEndpoint::OnPeerClose() { // This case is handled in |Run()| (which will call us). void ProxyMessagePipeEndpoint::EnqueueMessage( scoped_ptr<MessageInTransit> message) { - DCHECK(channel_endpoint_.get()); + DCHECK(channel_endpoint_); LOG_IF(WARNING, !channel_endpoint_->EnqueueMessage(message.Pass())) << "Failed to write enqueue message to channel"; } @@ -47,7 +55,7 @@ void ProxyMessagePipeEndpoint::Close() { } void ProxyMessagePipeEndpoint::DetachIfNecessary() { - if (channel_endpoint_.get()) { + if (channel_endpoint_) { channel_endpoint_->DetachFromClient(); channel_endpoint_ = nullptr; } diff --git a/mojo/edk/system/proxy_message_pipe_endpoint.h b/mojo/edk/system/proxy_message_pipe_endpoint.h index 3426869..6e10699 100644 --- a/mojo/edk/system/proxy_message_pipe_endpoint.h +++ b/mojo/edk/system/proxy_message_pipe_endpoint.h @@ -33,6 +33,14 @@ class MOJO_SYSTEM_IMPL_EXPORT ProxyMessagePipeEndpoint explicit ProxyMessagePipeEndpoint(ChannelEndpoint* channel_endpoint); ~ProxyMessagePipeEndpoint() override; + // Returns |channel_endpoint_| and resets |channel_endpoint_| to null. This + // may be called at most once, after which |Close()| need not be called. + // + // Note: The returned |ChannelEndpoint| must have its client changed while + // still under |MessagePipe|'s lock (which this must have also been called + // under). + scoped_refptr<ChannelEndpoint> ReleaseChannelEndpoint(); + // |MessagePipeEndpoint| implementation: Type GetType() const override; bool OnPeerClose() override; diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc index 926ca0b..d34602c 100644 --- a/mojo/edk/system/remote_message_pipe_unittest.cc +++ b/mojo/edk/system/remote_message_pipe_unittest.cc @@ -110,11 +110,11 @@ class RemoteMessagePipeTest : public testing::Test { void TearDownOnIOThread() { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - if (channels_[0].get()) { + if (channels_[0]) { channels_[0]->Shutdown(); channels_[0] = nullptr; } - if (channels_[1].get()) { + if (channels_[1]) { channels_[1]->Shutdown(); channels_[1] = nullptr; } @@ -123,7 +123,7 @@ class RemoteMessagePipeTest : public testing::Test { void CreateAndInitChannel(unsigned channel_index) { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); CHECK(channel_index == 0 || channel_index == 1); - CHECK(!channels_[channel_index].get()); + CHECK(!channels_[channel_index]); channels_[channel_index] = new Channel(&platform_support_); CHECK(channels_[channel_index]->Init( @@ -134,9 +134,9 @@ class RemoteMessagePipeTest : public testing::Test { scoped_refptr<ChannelEndpoint> ep1) { CHECK_EQ(base::MessageLoop::current(), io_thread()->message_loop()); - if (!channels_[0].get()) + if (!channels_[0]) CreateAndInitChannel(0); - if (!channels_[1].get()) + if (!channels_[1]) CreateAndInitChannel(1); channels_[0]->AttachAndRunEndpoint(ep0, true); @@ -193,7 +193,7 @@ TEST_F(RemoteMessagePipeTest, Basic) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. EXPECT_EQ( @@ -205,7 +205,7 @@ TEST_F(RemoteMessagePipeTest, Basic) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -223,7 +223,7 @@ TEST_F(RemoteMessagePipeTest, Basic) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp0->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); + mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); EXPECT_EQ( MOJO_RESULT_OK, @@ -233,7 +233,7 @@ TEST_F(RemoteMessagePipeTest, Basic) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(456u, context); hss = HandleSignalsState(); - mp0->RemoveWaiter(0, &waiter, &hss); + mp0->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -255,13 +255,13 @@ TEST_F(RemoteMessagePipeTest, Basic) { waiter.Init(); hss = HandleSignalsState(); MojoResult result = - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, &hss); if (result == MOJO_RESULT_OK) { EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(789u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); } EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -292,12 +292,12 @@ TEST_F(RemoteMessagePipeTest, PeerClosed) { waiter.Init(); hss = HandleSignalsState(); MojoResult result = - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss); if (result == MOJO_RESULT_OK) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(101u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); } EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals); @@ -339,7 +339,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, mp0->WriteMessage(0, UserPointer<const void>(&remote_id), @@ -349,7 +349,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -366,14 +366,14 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { // Warning: The local side of mp3 is port 0, not port 1. scoped_refptr<MessagePipe> mp3 = channels(1)->PassIncomingMessagePipe(received_id); - ASSERT_TRUE(mp3.get()); + ASSERT_TRUE(mp3); // Write: MP 2, port 0 -> MP 3, port 1. waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp3->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, nullptr)); + mp3->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, nullptr)); EXPECT_EQ( MOJO_RESULT_OK, @@ -383,7 +383,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(789u, context); hss = HandleSignalsState(); - mp3->RemoveWaiter(0, &waiter, &hss); + mp3->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -419,7 +419,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); EXPECT_EQ( MOJO_RESULT_OK, @@ -429,7 +429,7 @@ TEST_F(RemoteMessagePipeTest, Multiplex) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -500,7 +500,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeAttachAndRun) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); BootstrapChannelEndpointNoWait(1, ep1); @@ -512,7 +512,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeAttachAndRun) { // not appear as writable (there's a race, and it may not have noticed that // the other side was closed yet -- e.g., inserting a sleep here would make it // much more likely to notice that it's no longer writable). - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); @@ -562,7 +562,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); BootstrapChannelEndpointNoWait(1, ep1); @@ -574,7 +574,7 @@ TEST_F(RemoteMessagePipeTest, CloseBeforeConnect) { // not appear as writable (there's a race, and it may not have noticed that // the other side was closed yet -- e.g., inserting a sleep here would make it // much more likely to notice that it's no longer writable). - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_TRUE((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE)); EXPECT_TRUE((hss.satisfiable_signals & MOJO_HANDLE_SIGNAL_READABLE)); @@ -613,7 +613,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. { @@ -639,7 +639,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -658,7 +658,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { EXPECT_STREQ(kHello, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); @@ -667,8 +667,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { // Add the waiter now, before it becomes readable to avoid a race. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dispatcher->AddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, - nullptr)); + dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, + nullptr)); // Write to "local_mp", port 1. EXPECT_EQ( @@ -683,7 +683,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(456u, context); hss = HandleSignalsState(); - dispatcher->RemoveWaiter(&waiter, &hss); + dispatcher->RemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -701,8 +701,8 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { // Prepare to wait on "local_mp", port 1. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - local_mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); + local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, + nullptr)); // Write to the dispatcher. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( @@ -713,7 +713,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassing) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(789u, context); hss = HandleSignalsState(); - local_mp->RemoveWaiter(1, &waiter, &hss); + local_mp->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -787,7 +787,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. { @@ -813,7 +813,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -832,7 +832,7 @@ TEST_F(RemoteMessagePipeTest, HandlePassingHalfClosed) { EXPECT_STREQ(kHello, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); @@ -903,7 +903,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); - ASSERT_TRUE(dispatcher.get()); + ASSERT_TRUE(dispatcher); // Make a mapping. scoped_ptr<embedder::PlatformSharedBufferMapping> mapping0; @@ -921,7 +921,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. { @@ -947,7 +947,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -966,7 +966,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_SharedBufferPassing) { EXPECT_STREQ(kHello, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypeSharedBuffer, read_dispatchers[0]->GetType()); @@ -1040,7 +1040,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. { @@ -1066,7 +1066,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -1085,7 +1085,7 @@ TEST_F(RemoteMessagePipeTest, MAYBE_PlatformHandlePassing) { EXPECT_STREQ(kWorld, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypePlatformHandle, read_dispatchers[0]->GetType()); @@ -1177,7 +1177,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); + mp1->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, nullptr)); // Write to MP 0, port 0. { @@ -1203,7 +1203,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(123u, context); hss = HandleSignalsState(); - mp1->RemoveWaiter(1, &waiter, &hss); + mp1->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -1222,7 +1222,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_STREQ(kHello, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); @@ -1236,7 +1236,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { waiter.Init(); ASSERT_EQ( MOJO_RESULT_OK, - mp0->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); + mp0->AddAwakable(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 456, nullptr)); // Write to MP 1, port 1. { @@ -1262,7 +1262,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(456u, context); hss = HandleSignalsState(); - mp0->RemoveWaiter(0, &waiter, &hss); + mp0->RemoveAwakable(0, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -1279,7 +1279,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_STREQ(kWorld, read_buffer); EXPECT_EQ(1u, read_dispatchers.size()); EXPECT_EQ(1u, read_num_dispatchers); - ASSERT_TRUE(read_dispatchers[0].get()); + ASSERT_TRUE(read_dispatchers[0]); EXPECT_TRUE(read_dispatchers[0]->HasOneRef()); EXPECT_EQ(Dispatcher::kTypeMessagePipe, read_dispatchers[0]->GetType()); @@ -1289,8 +1289,8 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { // Add the waiter now, before it becomes readable to avoid a race. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - dispatcher->AddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); + dispatcher->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, + nullptr)); // Write to "local_mp", port 1. EXPECT_EQ( @@ -1302,7 +1302,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(789u, context); hss = HandleSignalsState(); - dispatcher->RemoveWaiter(&waiter, &hss); + dispatcher->RemoveAwakable(&waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); @@ -1320,8 +1320,8 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { // Prepare to wait on "local_mp", port 1. waiter.Init(); ASSERT_EQ(MOJO_RESULT_OK, - local_mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, - nullptr)); + local_mp->AddAwakable(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 789, + nullptr)); // Write to the dispatcher. EXPECT_EQ(MOJO_RESULT_OK, dispatcher->WriteMessage( @@ -1332,7 +1332,7 @@ TEST_F(RemoteMessagePipeTest, PassMessagePipeHandleAcrossAndBack) { EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_EQ(789u, context); hss = HandleSignalsState(); - local_mp->RemoveWaiter(1, &waiter, &hss); + local_mp->RemoveAwakable(1, &waiter, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(kAllSignals, hss.satisfiable_signals); diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc index 698ef4e..db823d5 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/mojo/edk/system/shared_buffer_dispatcher.cc @@ -74,7 +74,7 @@ MojoResult SharedBufferDispatcher::Create( scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); - if (!shared_buffer.get()) + if (!shared_buffer) return MOJO_RESULT_RESOURCE_EXHAUSTED; *result = new SharedBufferDispatcher(shared_buffer); @@ -126,7 +126,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( channel->platform_support()->CreateSharedBufferFromHandle( num_bytes, embedder::ScopedPlatformHandle(platform_handle))); - if (!shared_buffer.get()) { + if (!shared_buffer) { LOG(ERROR) << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; return nullptr; @@ -139,7 +139,7 @@ scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( SharedBufferDispatcher::SharedBufferDispatcher( scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer) : shared_buffer_(shared_buffer) { - DCHECK(shared_buffer_.get()); + DCHECK(shared_buffer_); } SharedBufferDispatcher::~SharedBufferDispatcher() { @@ -179,14 +179,14 @@ MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( void SharedBufferDispatcher::CloseImplNoLock() { lock().AssertAcquired(); - DCHECK(shared_buffer_.get()); + DCHECK(shared_buffer_); shared_buffer_ = nullptr; } scoped_refptr<Dispatcher> SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { lock().AssertAcquired(); - DCHECK(shared_buffer_.get()); + DCHECK(shared_buffer_); scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer; shared_buffer.swap(shared_buffer_); return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer)); @@ -212,7 +212,7 @@ MojoResult SharedBufferDispatcher::MapBufferImplNoLock( MojoMapBufferFlags flags, scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { lock().AssertAcquired(); - DCHECK(shared_buffer_.get()); + DCHECK(shared_buffer_); if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) return MOJO_RESULT_INVALID_ARGUMENT; @@ -247,7 +247,7 @@ bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( size_t* actual_size, embedder::PlatformHandleVector* platform_handles) { DCHECK(HasOneRef()); // Only one ref => no need to take the lock. - DCHECK(shared_buffer_.get()); + DCHECK(shared_buffer_); SerializedSharedBufferDispatcher* serialization = static_cast<SerializedSharedBufferDispatcher*>(destination); diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index 5866089..29dcb57 100644 --- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -118,7 +118,7 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, 100, &dispatcher)); - ASSERT_TRUE(dispatcher.get()); + ASSERT_TRUE(dispatcher); EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType()); // Make a couple of mappings. @@ -165,7 +165,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { scoped_refptr<Dispatcher> dispatcher2; EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( NullUserPointer(), &dispatcher2)); - ASSERT_TRUE(dispatcher2.get()); + ASSERT_TRUE(dispatcher2); EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); @@ -193,7 +193,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsValid) { scoped_refptr<Dispatcher> dispatcher2; EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->DuplicateBufferHandle( MakeUserPointer(&options[i]), &dispatcher2)); - ASSERT_TRUE(dispatcher2.get()); + ASSERT_TRUE(dispatcher2); EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType()); EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close()); } @@ -216,7 +216,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) { EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), &dispatcher2)); - EXPECT_FALSE(dispatcher2.get()); + EXPECT_FALSE(dispatcher2); } // Unknown |flags|. @@ -227,7 +227,7 @@ TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandleOptionsInvalid) { EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, dispatcher1->DuplicateBufferHandle(MakeUserPointer(&options), &dispatcher2)); - EXPECT_FALSE(dispatcher2.get()); + EXPECT_FALSE(dispatcher2); } EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close()); @@ -241,14 +241,14 @@ TEST_F(SharedBufferDispatcherTest, CreateInvalidNumBytes) { SharedBufferDispatcher::Create( platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, std::numeric_limits<uint64_t>::max(), &dispatcher)); - EXPECT_FALSE(dispatcher.get()); + EXPECT_FALSE(dispatcher); // Zero size. EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, SharedBufferDispatcher::Create( platform_support(), SharedBufferDispatcher::kDefaultCreateOptions, 0, &dispatcher)); - EXPECT_FALSE(dispatcher.get()); + EXPECT_FALSE(dispatcher); } TEST_F(SharedBufferDispatcherTest, MapBufferInvalidArguments) { diff --git a/mojo/edk/system/simple_dispatcher.cc b/mojo/edk/system/simple_dispatcher.cc index 3eb7a4f..f7db875 100644 --- a/mojo/edk/system/simple_dispatcher.cc +++ b/mojo/edk/system/simple_dispatcher.cc @@ -17,16 +17,16 @@ SimpleDispatcher::~SimpleDispatcher() { void SimpleDispatcher::HandleSignalsStateChangedNoLock() { lock().AssertAcquired(); - waiter_list_.AwakeWaitersForStateChange(GetHandleSignalsStateImplNoLock()); + awakable_list_.AwakeForStateChange(GetHandleSignalsStateImplNoLock()); } -void SimpleDispatcher::CancelAllWaitersNoLock() { +void SimpleDispatcher::CancelAllAwakablesNoLock() { lock().AssertAcquired(); - waiter_list_.CancelAllWaiters(); + awakable_list_.CancelAll(); } -MojoResult SimpleDispatcher::AddWaiterImplNoLock( - Waiter* waiter, +MojoResult SimpleDispatcher::AddAwakableImplNoLock( + Awakable* awakable, MojoHandleSignals signals, uint32_t context, HandleSignalsState* signals_state) { @@ -44,15 +44,15 @@ MojoResult SimpleDispatcher::AddWaiterImplNoLock( return MOJO_RESULT_FAILED_PRECONDITION; } - waiter_list_.AddWaiter(waiter, signals, context); + awakable_list_.Add(awakable, signals, context); return MOJO_RESULT_OK; } -void SimpleDispatcher::RemoveWaiterImplNoLock( - Waiter* waiter, +void SimpleDispatcher::RemoveAwakableImplNoLock( + Awakable* awakable, HandleSignalsState* signals_state) { lock().AssertAcquired(); - waiter_list_.RemoveWaiter(waiter); + awakable_list_.Remove(awakable); if (signals_state) *signals_state = GetHandleSignalsStateImplNoLock(); } diff --git a/mojo/edk/system/simple_dispatcher.h b/mojo/edk/system/simple_dispatcher.h index b1260ef..eddf614 100644 --- a/mojo/edk/system/simple_dispatcher.h +++ b/mojo/edk/system/simple_dispatcher.h @@ -8,9 +8,9 @@ #include <list> #include "base/macros.h" +#include "mojo/edk/system/awakable_list.h" #include "mojo/edk/system/dispatcher.h" #include "mojo/edk/system/system_impl_export.h" -#include "mojo/edk/system/waiter_list.h" namespace mojo { namespace system { @@ -30,17 +30,17 @@ class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher { void HandleSignalsStateChangedNoLock(); // |Dispatcher| protected methods: - void CancelAllWaitersNoLock() override; - MojoResult AddWaiterImplNoLock(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context, - HandleSignalsState* signals_state) override; - void RemoveWaiterImplNoLock(Waiter* waiter, - HandleSignalsState* signals_state) override; + void CancelAllAwakablesNoLock() override; + MojoResult AddAwakableImplNoLock(Awakable* awakable, + MojoHandleSignals signals, + uint32_t context, + HandleSignalsState* signals_state) override; + void RemoveAwakableImplNoLock(Awakable* awakable, + HandleSignalsState* signals_state) override; private: // Protected by |lock()|: - WaiterList waiter_list_; + AwakableList awakable_list_; DISALLOW_COPY_AND_ASSIGN(SimpleDispatcher); }; diff --git a/mojo/edk/system/simple_dispatcher_unittest.cc b/mojo/edk/system/simple_dispatcher_unittest.cc index f23ff68..b8e57e9 100644 --- a/mojo/edk/system/simple_dispatcher_unittest.cc +++ b/mojo/edk/system/simple_dispatcher_unittest.cc @@ -104,7 +104,7 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss)); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -114,14 +114,14 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { w.Init(); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, nullptr)); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(1u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -130,14 +130,14 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { w.Init(); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_OK, w.Wait(0, &context)); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(2u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -146,7 +146,7 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { w.Init(); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_WRITABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_OK, @@ -154,7 +154,7 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(3u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -163,12 +163,12 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { w.Init(); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr)); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -178,7 +178,7 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { w.Init(); d->SetSatisfiedSignals(MOJO_HANDLE_SIGNAL_READABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 5, nullptr)); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(2 * test::EpsilonTimeout().InMicroseconds(), nullptr)); @@ -186,7 +186,7 @@ TEST(SimpleDispatcherTest, MAYBE_Basic) { EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout()); EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout()); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals); @@ -208,7 +208,7 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { d->SetSatisfiedSignals(0); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); // Shouldn't need to remove the waiter (it was not added). @@ -218,7 +218,7 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, @@ -226,7 +226,7 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(2u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); @@ -235,14 +235,14 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, w.Wait(0, &context)); EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(3u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); @@ -252,7 +252,7 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); d->SetSatisfiableSignals(MOJO_HANDLE_SIGNAL_READABLE); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, @@ -260,7 +260,7 @@ TEST(SimpleDispatcherTest, BasicUnsatisfiable) { EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout()); EXPECT_EQ(4u, context); hss = HandleSignalsState(); - d->RemoveWaiter(&w, &hss); + d->RemoveAwakable(&w, &hss); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); @@ -281,7 +281,7 @@ TEST(SimpleDispatcherTest, BasicClosed) { EXPECT_EQ(MOJO_RESULT_OK, d->Close()); hss = HandleSignalsState(); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 1, &hss)); EXPECT_EQ(0u, hss.satisfied_signals); EXPECT_EQ(0u, hss.satisfiable_signals); // Shouldn't need to remove the waiter (it was not added). @@ -290,7 +290,7 @@ TEST(SimpleDispatcherTest, BasicClosed) { d = new MockSimpleDispatcher(); w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 2, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, d->Close()); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(MOJO_DEADLINE_INDEFINITE, &context)); @@ -302,7 +302,7 @@ TEST(SimpleDispatcherTest, BasicClosed) { d = new MockSimpleDispatcher(); w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 3, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, d->Close()); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_CANCELLED, w.Wait(0, &context)); @@ -315,7 +315,7 @@ TEST(SimpleDispatcherTest, BasicClosed) { d = new MockSimpleDispatcher(); w.Init(); ASSERT_EQ(MOJO_RESULT_OK, - d->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); + d->AddAwakable(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, nullptr)); EXPECT_EQ(MOJO_RESULT_OK, d->Close()); stopwatch.Start(); EXPECT_EQ(MOJO_RESULT_CANCELLED, diff --git a/mojo/edk/system/test_utils.cc b/mojo/edk/system/test_utils.cc index 3217c00..420b084 100644 --- a/mojo/edk/system/test_utils.cc +++ b/mojo/edk/system/test_utils.cc @@ -42,7 +42,7 @@ base::TimeDelta EpsilonTimeout() { // Currently, |tiny_timeout()| is usually 100 ms (possibly scaled under ASAN, // etc.). Based on this, set it to (usually be) 30 ms on Windows and 20 ms // elsewhere. -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_ANDROID) return (TestTimeouts::tiny_timeout() * 3) / 10; #else return (TestTimeouts::tiny_timeout() * 2) / 10; diff --git a/mojo/edk/system/waiter.cc b/mojo/edk/system/waiter.cc index 6dcd713..f9047cb 100644 --- a/mojo/edk/system/waiter.cc +++ b/mojo/edk/system/waiter.cc @@ -49,7 +49,7 @@ MojoResult Waiter::Wait(MojoDeadline deadline, uint32_t* context) { if (awoken_) { DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL); if (context) - *context = awake_context_; + *context = static_cast<uint32_t>(awake_context_); return awake_result_; } @@ -78,11 +78,11 @@ MojoResult Waiter::Wait(MojoDeadline deadline, uint32_t* context) { DCHECK_NE(awake_result_, MOJO_RESULT_INTERNAL); if (context) - *context = awake_context_; + *context = static_cast<uint32_t>(awake_context_); return awake_result_; } -void Waiter::Awake(MojoResult result, uint32_t context) { +void Waiter::Awake(MojoResult result, uintptr_t context) { base::AutoLock locker(lock_); if (awoken_) diff --git a/mojo/edk/system/waiter.h b/mojo/edk/system/waiter.h index 03ada16..999f286 100644 --- a/mojo/edk/system/waiter.h +++ b/mojo/edk/system/waiter.h @@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" +#include "mojo/edk/system/awakable.h" #include "mojo/edk/system/system_impl_export.h" #include "mojo/public/c/system/types.h" @@ -20,7 +21,7 @@ namespace system { // under other locks, in particular, |Dispatcher::lock_|s, so |Waiter| methods // must never call out to other objects (in particular, |Dispatcher|s). This // class is thread-safe. -class MOJO_SYSTEM_IMPL_EXPORT Waiter { +class MOJO_SYSTEM_IMPL_EXPORT Waiter : public Awakable { public: Waiter(); ~Waiter(); @@ -39,12 +40,12 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter { // 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 + // |Dispatcher::AddAwakable()|, 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 + // |MojoWait()|/|MojoWaitMany()| (hence |Dispatcher::AddAwakable()|) was // satisfied; // - |MOJO_RESULT_CANCELLED| if a handle (on which // |MojoWait()|/|MojoWaitMany()| was called) was closed (hence the @@ -57,7 +58,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter { // 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); + void Awake(MojoResult result, uintptr_t context) override; private: base::ConditionVariable cv_; // Associated to |lock_|. @@ -67,10 +68,7 @@ class MOJO_SYSTEM_IMPL_EXPORT Waiter { #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_; + uintptr_t awake_context_; DISALLOW_COPY_AND_ASSIGN(Waiter); }; diff --git a/mojo/edk/system/waiter_list.cc b/mojo/edk/system/waiter_list.cc deleted file mode 100644 index 42dfe15..0000000 --- a/mojo/edk/system/waiter_list.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "mojo/edk/system/waiter_list.h" - -#include "base/logging.h" -#include "mojo/edk/system/handle_signals_state.h" -#include "mojo/edk/system/waiter.h" - -namespace mojo { -namespace system { - -WaiterList::WaiterList() { -} - -WaiterList::~WaiterList() { - DCHECK(waiters_.empty()); -} - -void WaiterList::AwakeWaitersForStateChange(const HandleSignalsState& state) { - for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end(); - ++it) { - if (state.satisfies(it->signals)) - it->waiter->Awake(MOJO_RESULT_OK, it->context); - else if (!state.can_satisfy(it->signals)) - 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(MOJO_RESULT_CANCELLED, it->context); - } - waiters_.clear(); -} - -void WaiterList::AddWaiter(Waiter* waiter, - MojoHandleSignals signals, - uint32_t context) { - waiters_.push_back(WaiterInfo(waiter, signals, context)); -} - -void WaiterList::RemoveWaiter(Waiter* waiter) { - // We allow a thread to wait on the same handle multiple times simultaneously, - // so we need to scan the entire list and remove all occurrences of |waiter|. - for (WaiterInfoList::iterator it = waiters_.begin(); it != waiters_.end();) { - WaiterInfoList::iterator maybe_delete = it; - ++it; - if (maybe_delete->waiter == waiter) - waiters_.erase(maybe_delete); - } -} - -} // namespace system -} // namespace mojo diff --git a/mojo/edk/system/waiter_list.h b/mojo/edk/system/waiter_list.h deleted file mode 100644 index 6bbc799..0000000 --- a/mojo/edk/system/waiter_list.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MOJO_EDK_SYSTEM_WAITER_LIST_H_ -#define MOJO_EDK_SYSTEM_WAITER_LIST_H_ - -#include <stdint.h> - -#include <list> - -#include "base/macros.h" -#include "mojo/edk/system/system_impl_export.h" -#include "mojo/public/c/system/types.h" - -namespace mojo { -namespace system { - -class Waiter; -struct HandleSignalsState; - -// |WaiterList| tracks all the |Waiter|s that are waiting on a given -// handle/|Dispatcher|. There should be a |WaiterList| for each handle that can -// be waited on (in any way). In the simple case, the |WaiterList| is owned by -// the |Dispatcher|, whereas in more complex cases it is owned by the secondary -// object (see simple_dispatcher.* and the explanatory comment in core.cc). This -// class is thread-unsafe (all concurrent access must be protected by some -// lock). -class MOJO_SYSTEM_IMPL_EXPORT WaiterList { - public: - WaiterList(); - ~WaiterList(); - - void AwakeWaitersForStateChange(const HandleSignalsState& state); - void CancelAllWaiters(); - void AddWaiter(Waiter* waiter, MojoHandleSignals signals, uint32_t context); - void RemoveWaiter(Waiter* waiter); - - private: - struct WaiterInfo { - WaiterInfo(Waiter* waiter, MojoHandleSignals signals, uint32_t context) - : waiter(waiter), signals(signals), context(context) {} - - Waiter* waiter; - MojoHandleSignals signals; - uint32_t context; - }; - typedef std::list<WaiterInfo> WaiterInfoList; - - WaiterInfoList waiters_; - - DISALLOW_COPY_AND_ASSIGN(WaiterList); -}; - -} // namespace system -} // namespace mojo - -#endif // MOJO_EDK_SYSTEM_WAITER_LIST_H_ diff --git a/mojo/edk/system/waiter_test_utils.cc b/mojo/edk/system/waiter_test_utils.cc index 39cb14e..ea243ed1 100644 --- a/mojo/edk/system/waiter_test_utils.cc +++ b/mojo/edk/system/waiter_test_utils.cc @@ -55,14 +55,14 @@ WaiterThread::~WaiterThread() { void WaiterThread::Run() { waiter_.Init(); - *result_out_ = dispatcher_->AddWaiter(&waiter_, handle_signals_, context_, - signals_state_out_); + *result_out_ = dispatcher_->AddAwakable(&waiter_, handle_signals_, context_, + signals_state_out_); if (*result_out_ != MOJO_RESULT_OK) return; *did_wait_out_ = true; *result_out_ = waiter_.Wait(deadline_, context_out_); - dispatcher_->RemoveWaiter(&waiter_, signals_state_out_); + dispatcher_->RemoveAwakable(&waiter_, signals_state_out_); } } // namespace test diff --git a/mojo/edk/system/waiter_test_utils.h b/mojo/edk/system/waiter_test_utils.h index cec0f3e..b11d78d 100644 --- a/mojo/edk/system/waiter_test_utils.h +++ b/mojo/edk/system/waiter_test_utils.h @@ -29,19 +29,19 @@ namespace test { // // MojoResult result; // { -// WaiterList waiter_list; +// AwakableList awakable_list; // test::SimpleWaiterThread thread(&result); -// waiter_list.AddWaiter(thread.waiter(), ...); +// awakable_list.Add(thread.waiter(), ...); // thread.Start(); // ... some stuff to wake the waiter ... -// waiter_list.RemoveWaiter(thread.waiter()); +// awakable_list.Remove(thread.waiter()); // } // Join |thread|. // EXPECT_EQ(..., result); // // There's a bit of unrealism in its use: In this sort of usage, calls such as -// |Waiter::Init()|, |AddWaiter()|, and |RemoveWaiter()| are done in the main -// (test) thread, not the waiter thread (as would actually happen in real code). -// (We accept this unrealism for simplicity, since |WaiterList| is +// |Waiter::Init()|, |AddAwakable()|, and |RemoveAwakable()| are done in the +// main (test) thread, not the waiter thread (as would actually happen in real +// code). (We accept this unrealism for simplicity, since |AwakableList| is // thread-unsafe so making it more realistic would require adding nontrivial // synchronization machinery.) class SimpleWaiterThread : public base::SimpleThread { diff --git a/mojo/edk/test/BUILD.gn b/mojo/edk/test/BUILD.gn index 42e8c03..3cf8ae8 100644 --- a/mojo/edk/test/BUILD.gn +++ b/mojo/edk/test/BUILD.gn @@ -2,8 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../mojo_edk.gni") + # GYP version: mojo/edk/mojo_edk.gyp:mojo_common_test_support -source_set("test_support") { +mojo_edk_source_set("test_support") { testonly = true sources = [ "multiprocess_test_helper.cc", @@ -16,37 +18,52 @@ source_set("test_support") { deps = [ "//base", "//base/test:test_support", - "//mojo/edk/system", "//testing/gtest", ] + + mojo_edk_deps = [ + "mojo/edk/system", + ] } # GYP version: mojo/edk/mojo_edk.gyp:mojo_run_all_unittests -source_set("run_all_unittests") { +mojo_edk_source_set("run_all_unittests") { testonly = true + sources = [ + "run_all_unittests.cc" + ] + deps = [ ":test_support_impl", "//base", "//base/test:test_support", - "//mojo/edk/system", - "//mojo/public/c/test_support", "//testing/gtest", ] - sources = [ - "run_all_unittests.cc", + mojo_edk_deps = [ + "mojo/edk/system", + ] + + mojo_sdk_deps = [ + "mojo/public/c/test_support", ] } # GYP version: mojo/edk/mojo_edk.gyp:mojo_run_all_perftests -source_set("run_all_perftests") { +mojo_edk_source_set("run_all_perftests") { testonly = true deps = [ ":test_support_impl", "//base", "//base/test:test_support", - "//mojo/edk/system", - "//mojo/public/c/test_support", + ] + + mojo_edk_deps = [ + "mojo/edk/system", + ] + + mojo_sdk_deps = [ + "mojo/public/c/test_support", ] sources = [ @@ -55,12 +72,15 @@ source_set("run_all_perftests") { } # GYP version: mojo/edk/mojo_edk.gyp:mojo_test_support_impl -source_set("test_support_impl") { +mojo_edk_source_set("test_support_impl") { testonly = true deps = [ "//base", "//base/test:test_support", - "//mojo/public/c/test_support", + ] + + mojo_sdk_deps = [ + "mojo/public/c/test_support", ] sources = [ diff --git a/mojo/edk/test/multiprocess_test_helper.cc b/mojo/edk/test/multiprocess_test_helper.cc index 30aa0be..758520a 100644 --- a/mojo/edk/test/multiprocess_test_helper.cc +++ b/mojo/edk/test/multiprocess_test_helper.cc @@ -27,7 +27,7 @@ MultiprocessTestHelper::~MultiprocessTestHelper() { } void MultiprocessTestHelper::StartChild(const std::string& test_child_name) { - CHECK(platform_channel_pair_.get()); + CHECK(platform_channel_pair_); CHECK(!test_child_name.empty()); CHECK_EQ(test_child_handle_, base::kNullProcessHandle); diff --git a/mojo/mojo_nacl.gyp b/mojo/mojo_nacl.gyp index ea16dee..397924f 100644 --- a/mojo/mojo_nacl.gyp +++ b/mojo/mojo_nacl.gyp @@ -54,6 +54,7 @@ ], 'dependencies': [ '<(DEPTH)/native_client/src/trusted/service_runtime/service_runtime.gyp:sel', + 'monacl_codegen', ], }, { diff --git a/mojo/nacl/generator/libmojo.cc.tmpl b/mojo/nacl/generator/libmojo.cc.tmpl index 7690d82..7a70376 100644 --- a/mojo/nacl/generator/libmojo.cc.tmpl +++ b/mojo/nacl/generator/libmojo.cc.tmpl @@ -9,7 +9,10 @@ #include "native_client/src/public/imc_syscalls.h" #include "native_client/src/public/imc_types.h" -#define NACL_MOJO_DESC (NACL_CHROME_DESC_BASE + 2) +// The value for this FD must not conflict with uses inside Chromium. However, +// mojo/nacl doesn't depend on any Chromium headers, so we can't use a #define +// from there. +#define NACL_MOJO_DESC (NACL_CHROME_DESC_BASE + 3) static void DoMojoCall(uint32_t params[], nacl_abi_size_t num_params) { NaClAbiNaClImcMsgIoVec iov[1] = { diff --git a/mojo/nacl/generator/mojo_syscall.cc.tmpl b/mojo/nacl/generator/mojo_syscall.cc.tmpl index 136e672..8ba7665 100644 --- a/mojo/nacl/generator/mojo_syscall.cc.tmpl +++ b/mojo/nacl/generator/mojo_syscall.cc.tmpl @@ -57,10 +57,42 @@ struct NaClDesc* MakeMojoDesc(struct NaClApp* nap) { return NaClDescMakeCustomDesc(nap, &funcs); } +void MojoDisabledDescDestroy(void* handle) { +} + +ssize_t MojoDisabledDescSendMsg(void* handle, + const struct NaClImcTypedMsgHdr* msg, + int flags) { + fprintf(stderr, "Mojo is not currently supported."); + abort(); +} + +ssize_t MojoDisabledDescRecvMsg(void* handle, + struct NaClImcTypedMsgHdr* msg, + int flags) { + fprintf(stderr, "Mojo is not currently supported."); + abort(); +} + +struct NaClDesc* MakeDisabledMojoDesc(struct NaClApp* nap) { + struct NaClDescCustomFuncs funcs = NACL_DESC_CUSTOM_FUNCS_INITIALIZER; + funcs.Destroy = MojoDisabledDescDestroy; + funcs.SendMsg = MojoDisabledDescSendMsg; + funcs.RecvMsg = MojoDisabledDescRecvMsg; + return NaClDescMakeCustomDesc(nap, &funcs); +} + } // namespace -#define NACL_MOJO_DESC (NACL_CHROME_DESC_BASE + 2) +// The value for this FD must not conflict with uses inside Chromium. However, +// mojo/nacl doesn't depend on any Chromium headers, so we can't use a #define +// from there. +#define NACL_MOJO_DESC (NACL_CHROME_DESC_BASE + 3) void InjectMojo(struct NaClApp* nap) { NaClAppSetDesc(nap, NACL_MOJO_DESC, MakeMojoDesc(nap)); } + +void InjectDisabledMojo(struct NaClApp* nap) { + NaClAppSetDesc(nap, NACL_MOJO_DESC, MakeDisabledMojoDesc(nap)); +} diff --git a/mojo/nacl/mojo_syscall.h b/mojo/nacl/mojo_syscall.h index f195769..71822b5 100644 --- a/mojo/nacl/mojo_syscall.h +++ b/mojo/nacl/mojo_syscall.h @@ -5,6 +5,12 @@ #ifndef MOJO_NACL_MOJO_SYSCALL_H_ #define MOJO_NACL_MOJO_SYSCALL_H_ +// Injects a NaClDesc for Mojo support. This provides the implementation of the +// Mojo system API outside the NaCl sandbox. void InjectMojo(struct NaClApp* nap); +// Injects a "disabled" NaClDesc for Mojo support. This is to make debugging +// more straightforward in the case where Mojo is not enabled for NaCl plugins. +void InjectDisabledMojo(struct NaClApp* nap); + #endif // MOJO_NACL_MOJO_SYSCALL_H_ diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn index 4cc5548..33e05c6 100644 --- a/mojo/public/BUILD.gn +++ b/mojo/public/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/mojo.gni") +import("mojo.gni") group("public") { # Meta-target, don't link into production code. @@ -10,39 +10,35 @@ group("public") { deps = [ ":libmojo_sdk", ":sdk", - "//mojo/public/cpp/application:standalone", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/utility", - "//mojo/public/interfaces/bindings/tests:test_interfaces", - "//mojo/public/sky", + "cpp/application:standalone", + "cpp/bindings", + "cpp/environment:standalone", + "cpp/utility", + "interfaces/bindings/tests:test_interfaces", + "sky", ] if (is_linux) { - deps += [ "//mojo/public/python" ] - } - - if (mojo_use_dart) { - deps += [ "//mojo/public/dart" ] + deps += [ "python" ] } if (is_android) { deps += [ - "//mojo/public/java:system", - "//mojo/public/java:bindings", + "java:system", + "java:bindings", ] } } group("sdk") { deps = [ - "//mojo/public/c/system", - "//mojo/public/cpp/application:standalone", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/utility", - "//mojo/public/interfaces/application", - "//mojo/public/js", + "c/system", + "cpp/application:standalone", + "cpp/bindings", + "cpp/environment:standalone", + "cpp/utility", + "interfaces/application", + "js", ] } diff --git a/mojo/public/VERSION b/mojo/public/VERSION index eca68d9..ed3fd02 100644 --- a/mojo/public/VERSION +++ b/mojo/public/VERSION @@ -1 +1 @@ -98d8236f7eea383e5214254c8d045df6c7a6297a
\ No newline at end of file +f6c8ec07c01deebc13178d516225fd12695c3dc2
\ No newline at end of file diff --git a/mojo/public/build/config/BUILD.gn b/mojo/public/build/config/BUILD.gn new file mode 100644 index 0000000..c104b8b --- /dev/null +++ b/mojo/public/build/config/BUILD.gn @@ -0,0 +1,16 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../../mojo_sdk.gni") + +config("mojo_sdk") { + include_dirs = [ + # Include paths in the Mojo public SDK are specified relative to the + # directory holding the SDK. + mojo_root, + + # The same goes for files generated from mojoms. + root_gen_dir + mojo_root, + ] +} diff --git a/mojo/public/c/environment/BUILD.gn b/mojo/public/c/environment/BUILD.gn index 26e8256..3fd1689 100644 --- a/mojo/public/c/environment/BUILD.gn +++ b/mojo/public/c/environment/BUILD.gn @@ -2,13 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("environment") { +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("environment") { sources = [ "async_waiter.h", "logger.h", ] - deps = [ - "//mojo/public/c/system", - ] + mojo_sdk_deps = [ "mojo/public/c/system" ] } diff --git a/mojo/public/c/gles2/BUILD.gn b/mojo/public/c/gles2/BUILD.gn index df0007b8..0a4d151 100644 --- a/mojo/public/c/gles2/BUILD.gn +++ b/mojo/public/c/gles2/BUILD.gn @@ -2,11 +2,23 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../../mojo_sdk.gni") + config("gles2_config") { defines = [ "GLES2_USE_MOJO" ] } -source_set("gles2") { +group("gles2") { + public_configs = [ "//third_party/khronos:khronos_headers" ] + public_deps = [ + ":headers", + ] + deps = [ + "../../platform/native:gles2_thunks", + ] +} + +mojo_sdk_source_set("headers") { sources = [ "gles2.h", "gles2_export.h", @@ -14,8 +26,8 @@ source_set("gles2") { public_configs = [ ":gles2_config" ] - public_deps = [ - "//mojo/public/c/environment", - "//mojo/public/c/system", + mojo_sdk_public_deps = [ + "mojo/public/c/environment", + "mojo/public/c/system", ] } diff --git a/mojo/public/c/system/BUILD.gn b/mojo/public/c/system/BUILD.gn index b12755f..d2393a4 100644 --- a/mojo/public/c/system/BUILD.gn +++ b/mojo/public/c/system/BUILD.gn @@ -2,11 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../../mojo_sdk.gni") + # Depend on this target to use the types etc defined in the system without # linking against a specific implementation of the system. To link against a # particular implementation, use the :for_component or # :for_shared_library targets, depending on the type of target you are. -source_set("system") { +mojo_sdk_source_set("system") { sources = [ "buffer.h", "core.h", @@ -31,17 +33,18 @@ source_set("system") { # For shared_library targets (e.g., a Mojo App), add # //mojo/public/c/system:for_shared_library to your deps +# TODO(jamesr): Eliminate the need for these targets. crbug.com/438701 group("for_shared_library") { public_deps = [ ":system", ] if (is_component_build) { deps = [ - "//mojo/edk/system", + "../../../edk/system", ] } else { deps = [ - "//mojo/public/platform/native:system_thunks", + "../../platform/native:system_thunks", ] } } @@ -52,7 +55,7 @@ group("for_component") { ] if (is_component_build) { deps = [ - "//mojo/edk/system", + "../../../edk/system", ] } } diff --git a/mojo/public/c/system/functions.h b/mojo/public/c/system/functions.h index 6045f2f..21a0db5 100644 --- a/mojo/public/c/system/functions.h +++ b/mojo/public/c/system/functions.h @@ -26,7 +26,7 @@ extern "C" { // whether a given "in/out" parameter is used for input, output, or both.) // Platform-dependent monotonically increasing tick count representing "right -// now." The resolution of this clock is ~1-15ms. Resolution varies depending +// now." The resolution of this clock is ~1-15ms. Resolution varies depending // on hardware/operating system configuration. MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow(void); @@ -101,6 +101,90 @@ MOJO_SYSTEM_EXPORT MojoResult MojoWaitMany(const MojoHandle* handles, uint32_t num_handles, MojoDeadline deadline); +// Waits on the given handle until one of the following happens: +// - A signal indicated by |signals| is satisfied. +// - It becomes known that no signal indicated by |signals| will ever be +// satisfied. (See the description of the |MOJO_RESULT_CANCELLED| and +// |MOJO_RESULT_FAILED_PRECONDITION| return values below.) +// - Until |deadline| has passed. +// +// If |deadline| is |MOJO_DEADLINE_INDEFINITE|, this will wait "forever" (until +// one of the other wait termination conditions is satisfied). If |deadline| is +// 0, this will return |MOJO_RESULT_DEADLINE_EXCEEDED| only if one of the other +// termination conditions (e.g., a signal is satisfied, or all signals are +// unsatisfiable) is not already satisfied. +// +// |signals_state| (optional): See documentation for |MojoHandleSignalsState|. +// +// Returns: +// |MOJO_RESULT_OK| if some signal in |signals| was satisfied (or is already +// satisfied). +// |MOJO_RESULT_CANCELLED| if |handle| was closed (necessarily from another +// thread) during the wait. +// |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle (e.g., if +// it has already been closed). The |signals_state| value is unchanged. +// |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of +// the signals being satisfied. +// |MOJO_RESULT_FAILED_PRECONDITION| if it becomes known that none of the +// signals in |signals| can ever be satisfied (e.g., when waiting on one +// end of a message pipe and the other end is closed). +// +// If there are multiple waiters (on different threads, obviously) waiting on +// the same handle and signal, and that signal becomes is satisfied, all waiters +// will be awoken. +MOJO_SYSTEM_EXPORT MojoResult +MojoNewWait(MojoHandle handle, + MojoHandleSignals signals, + MojoDeadline deadline, + struct MojoHandleSignalsState* signals_state); // Optional out. + +// Waits on |handles[0]|, ..., |handles[num_handles-1]| until: +// - (At least) one handle satisfies a signal indicated in its respective +// |signals[0]|, ..., |signals[num_handles-1]|. +// - It becomes known that no signal in some |signals[i]| will ever be +// satisfied. +// - |deadline| has passed. +// +// This means that |MojoWaitMany()| behaves as if |MojoWait()| were called on +// each handle/signals pair simultaneously, completing when the first +// |MojoWait()| would complete. +// +// See |MojoWait()| for more details about |deadline|. +// +// |result_index| (optional) is used to return the index of the handle that +// caused the call to return. For example, the index |i| (from 0 to +// |num_handles-1|) if |handle[i]| satisfies a signal from |signals[i]|. You +// must manually initialize this to a suitable sentinel value (e.g. -1) +// before you make this call because this value is not updated if there is +// no specific handle that causes the function to return. Pass null if you +// don't need this value to be returned. +// +// |signals_states| (optional) points to an array of size |num_handles| of +// MojoHandleSignalsState. See |MojoHandleSignalsState| for more details +// about the meaning of each array entry. This array is not an atomic +// snapshot. The array will be updated if the function does not return +// |MOJO_RESULT_INVALID_ARGUMENT| or |MOJO_RESULT_RESOURCE_EXHAUSTED|. +// +// Returns: +// |MOJO_RESULT_CANCELLED| if some |handle[i]| was closed (necessarily from +// another thread) during the wait. +// |MOJO_RESULT_RESOURCE_EXHAUSTED| if there are too many handles. The +// |signals_state| array is unchanged. +// |MOJO_RESULT_INVALID_ARGUMENT| if some |handle[i]| is not a valid handle +// (e.g., if it is zero or if it has already been closed). The +// |signals_state| array is unchanged. +// |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of +// handles satisfying any of its signals. +// |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that SOME +// |handle[i]| will ever satisfy any of the signals in |signals[i]|. +MOJO_SYSTEM_EXPORT MojoResult +MojoNewWaitMany(const MojoHandle* handles, + const MojoHandleSignals* signals, + uint32_t num_handles, + MojoDeadline deadline, + uint32_t* result_index, // Optional out + struct MojoHandleSignalsState* signals_states); // Optional out + #ifdef __cplusplus } // extern "C" #endif diff --git a/mojo/public/c/system/tests/BUILD.gn b/mojo/public/c/system/tests/BUILD.gn index 67e166d..d1eba41 100644 --- a/mojo/public/c/system/tests/BUILD.gn +++ b/mojo/public/c/system/tests/BUILD.gn @@ -28,7 +28,6 @@ test("perftests") { ] deps = [ - "//base", "//mojo/edk/test:run_all_perftests", "//mojo/public/c/environment", "//mojo/public/cpp/system", diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc index d071f48..d8ae4b0 100644 --- a/mojo/public/c/system/tests/core_unittest.cc +++ b/mojo/public/c/system/tests/core_unittest.cc @@ -13,6 +13,13 @@ namespace mojo { namespace { +const MojoHandleSignals kSignalReadadableWritable = + MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE; + +const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | + MOJO_HANDLE_SIGNAL_WRITABLE | + MOJO_HANDLE_SIGNAL_PEER_CLOSED; + TEST(CoreTest, GetTimeTicksNow) { const MojoTimeTicks start = MojoGetTimeTicksNow(); EXPECT_NE(static_cast<MojoTimeTicks>(0), start) @@ -34,21 +41,23 @@ TEST(CoreTest, InvalidHandle) { // Wait: EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000)); + MojoNewWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000, + NULL)); + h0 = MOJO_HANDLE_INVALID; sig = ~MOJO_HANDLE_SIGNAL_NONE; - EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE)); + EXPECT_EQ( + MOJO_RESULT_INVALID_ARGUMENT, + MojoNewWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, NULL, NULL)); // Message pipe: EXPECT_EQ( MOJO_RESULT_INVALID_ARGUMENT, MojoWriteMessage(h0, buffer, 3, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ( - MOJO_RESULT_INVALID_ARGUMENT, - MojoReadMessage( - h0, buffer, &buffer_size, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, + MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL, + MOJO_READ_MESSAGE_FLAG_NONE)); // Data pipe: buffer_size = static_cast<uint32_t>(sizeof(buffer)); @@ -56,16 +65,16 @@ TEST(CoreTest, InvalidHandle) { MojoWriteData(h0, buffer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE)); write_pointer = NULL; EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoBeginWriteData( - h0, &write_pointer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE)); + MojoBeginWriteData(h0, &write_pointer, &buffer_size, + MOJO_WRITE_DATA_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndWriteData(h0, 1)); buffer_size = static_cast<uint32_t>(sizeof(buffer)); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoReadData(h0, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); read_pointer = NULL; EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, - MojoBeginReadData( - h0, &read_pointer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); + MojoBeginReadData(h0, &read_pointer, &buffer_size, + MOJO_READ_DATA_FLAG_NONE)); EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndReadData(h0, 1)); // Shared buffer: @@ -88,45 +97,56 @@ TEST(CoreTest, BasicMessagePipe) { EXPECT_NE(h0, MOJO_HANDLE_INVALID); EXPECT_NE(h1, MOJO_HANDLE_INVALID); - // Shouldn't be readable. + // Shouldn't be readable, we haven't written anything. + MojoHandleSignalsState state; EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 0)); + MojoNewWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Should be writable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state)); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Try to read. buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ( - MOJO_RESULT_SHOULD_WAIT, - MojoReadMessage( - h0, buffer, &buffer_size, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, + MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL, + MOJO_READ_MESSAGE_FLAG_NONE)); // Write to |h1|. static const char kHello[] = "hello"; buffer_size = static_cast<uint32_t>(sizeof(kHello)); - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteMessage( - h1, kHello, buffer_size, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h1, kHello, buffer_size, NULL, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE)); // |h0| should be readable. + uint32_t result_index = 1; + MojoHandleSignalsState states[1]; sig = MOJO_HANDLE_SIGNAL_READABLE; EXPECT_EQ(MOJO_RESULT_OK, - MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE)); + MojoNewWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, + &result_index, states)); + + EXPECT_EQ(0u, result_index); + EXPECT_EQ(kSignalReadadableWritable, states[0].satisfied_signals); + EXPECT_EQ(kSignalAll, states[0].satisfiable_signals); // Read from |h0|. buffer_size = static_cast<uint32_t>(sizeof(buffer)); - EXPECT_EQ( - MOJO_RESULT_OK, - MojoReadMessage( - h0, buffer, &buffer_size, NULL, NULL, MOJO_READ_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoReadMessage(h0, buffer, &buffer_size, NULL, + NULL, MOJO_READ_MESSAGE_FLAG_NONE)); EXPECT_EQ(static_cast<uint32_t>(sizeof(kHello)), buffer_size); EXPECT_STREQ(kHello, buffer); // |h0| should no longer be readable. EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 10)); + MojoNewWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 10, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); + EXPECT_EQ(kSignalAll, state.satisfiable_signals); // Close |h0|. EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0)); @@ -134,8 +154,11 @@ TEST(CoreTest, BasicMessagePipe) { // |h1| should no longer be readable or writable. EXPECT_EQ( MOJO_RESULT_FAILED_PRECONDITION, - MojoWait( - h1, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, 1000)); + MojoNewWait(h1, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + 1000, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1)); } @@ -164,11 +187,21 @@ TEST(CoreTest, MAYBE_BasicDataPipe) { EXPECT_NE(hc, MOJO_HANDLE_INVALID); // The consumer |hc| shouldn't be readable. + MojoHandleSignalsState state; EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 0)); + MojoNewWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfiable_signals); // The producer |hp| should be writable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(hp, MOJO_HANDLE_SIGNAL_WRITABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(hp, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfiable_signals); // Try to read from |hc|. buffer_size = static_cast<uint32_t>(sizeof(buffer)); @@ -178,26 +211,32 @@ TEST(CoreTest, MAYBE_BasicDataPipe) { // Try to begin a two-phase read from |hc|. read_pointer = NULL; EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, - MojoBeginReadData( - hc, &read_pointer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); + MojoBeginReadData(hc, &read_pointer, &buffer_size, + MOJO_READ_DATA_FLAG_NONE)); // Write to |hp|. static const char kHello[] = "hello "; // Don't include terminating null. buffer_size = static_cast<uint32_t>(strlen(kHello)); - EXPECT_EQ( - MOJO_RESULT_OK, - MojoWriteData(hp, kHello, &buffer_size, MOJO_WRITE_MESSAGE_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(hp, kHello, &buffer_size, + MOJO_WRITE_MESSAGE_FLAG_NONE)); // |hc| should be(come) readable. + uint32_t result_index = 1; + MojoHandleSignalsState states[1]; sig = MOJO_HANDLE_SIGNAL_READABLE; EXPECT_EQ(MOJO_RESULT_OK, - MojoWaitMany(&hc, &sig, 1, MOJO_DEADLINE_INDEFINITE)); + MojoNewWaitMany(&hc, &sig, 1, MOJO_DEADLINE_INDEFINITE, + &result_index, states)); + + EXPECT_EQ(0u, result_index); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, states[0].satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + states[0].satisfiable_signals); // Do a two-phase write to |hp|. - EXPECT_EQ(MOJO_RESULT_OK, - MojoBeginWriteData( - hp, &write_pointer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoBeginWriteData(hp, &write_pointer, &buffer_size, + MOJO_WRITE_DATA_FLAG_NONE)); static const char kWorld[] = "world"; ASSERT_GE(buffer_size, sizeof(kWorld)); // Include the terminating null. @@ -215,13 +254,18 @@ TEST(CoreTest, MAYBE_BasicDataPipe) { EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hp)); // |hc| should still be readable. - EXPECT_EQ(MOJO_RESULT_OK, MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 0)); + EXPECT_EQ(MOJO_RESULT_OK, + MojoNewWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 0, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfiable_signals); // Do a two-phase read from |hc|. read_pointer = NULL; - EXPECT_EQ(MOJO_RESULT_OK, - MojoBeginReadData( - hc, &read_pointer, &buffer_size, MOJO_READ_DATA_FLAG_NONE)); + EXPECT_EQ(MOJO_RESULT_OK, MojoBeginReadData(hc, &read_pointer, &buffer_size, + MOJO_READ_DATA_FLAG_NONE)); ASSERT_LE(buffer_size, sizeof(buffer) - 1); memcpy(&buffer[1], read_pointer, buffer_size); EXPECT_EQ(MOJO_RESULT_OK, MojoEndReadData(hc, buffer_size)); @@ -229,7 +273,10 @@ TEST(CoreTest, MAYBE_BasicDataPipe) { // |hc| should no longer be readable. EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, - MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 1000)); + MojoNewWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 1000, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals); EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hc)); diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c index 33de688..bb00927 100644 --- a/mojo/public/c/system/tests/core_unittest_pure_c.c +++ b/mojo/public/c/system/tests/core_unittest_pure_c.c @@ -61,8 +61,18 @@ const char* MinimalCTest(void) { EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &handle0, &handle1)); signals = MOJO_HANDLE_SIGNAL_READABLE; + uint32_t result_index = 123; + struct MojoHandleSignalsState states[1]; EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, - MojoWaitMany(&handle0, &signals, 1, 1)); + MojoNewWaitMany(&handle0, &signals, 1, 1, &result_index, states)); + + // "Deadline exceeded" doesn't apply to a single handle, so this should leave + // |result_index| untouched. + EXPECT_EQ(123u, result_index); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | + MOJO_HANDLE_SIGNAL_PEER_CLOSED, + states[0].satisfiable_signals); EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(handle0, @@ -72,9 +82,17 @@ const char* MinimalCTest(void) { 0u, MOJO_WRITE_DATA_FLAG_NONE)); + struct MojoHandleSignalsState state; EXPECT_EQ( MOJO_RESULT_OK, - MojoWait(handle1, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE)); + MojoNewWait(handle1, MOJO_HANDLE_SIGNAL_READABLE, + MOJO_DEADLINE_INDEFINITE, &state)); + + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, + state.satisfied_signals); + EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | + MOJO_HANDLE_SIGNAL_PEER_CLOSED, + state.satisfiable_signals); num_bytes = (uint32_t)sizeof(buffer); EXPECT_EQ(MOJO_RESULT_OK, diff --git a/mojo/public/c/system/types.h b/mojo/public/c/system/types.h index 9b1eedc..a88b024 100644 --- a/mojo/public/c/system/types.h +++ b/mojo/public/c/system/types.h @@ -165,7 +165,14 @@ const MojoHandleSignals MOJO_HANDLE_SIGNAL_PEER_CLOSED = 1 << 2; #define MOJO_HANDLE_SIGNAL_PEER_CLOSED ((MojoHandleSignals)1 << 2) #endif -// TODO(vtl): Add out parameters with this to MojoWait/MojoWaitMany. +// |MojoHandleSignalsState|: Returned by wait functions to indicate the +// signaling state of handles. Members are as follows: +// - |satisfied signals|: Bitmask of signals that were satisfied at some time +// before the call returned. +// - |satisfiable signals|: These are the signals that are possible to +// satisfy. For example, if the return value was +// |MOJO_RESULT_FAILED_PRECONDITION|, you can use this field to +// determine which, if any, of the signals can still be satisfied. // Note: This struct is not extensible (and only has 32-bit quantities), so it's // 32-bit-aligned. MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int32_t) == 4, "int32_t has weird alignment"); diff --git a/mojo/public/cpp/application/BUILD.gn b/mojo/public/cpp/application/BUILD.gn index b224c4a..1c8842d 100644 --- a/mojo/public/cpp/application/BUILD.gn +++ b/mojo/public/cpp/application/BUILD.gn @@ -2,8 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../../mojo_sdk.gni") + # GYP version: mojo/public/mojo_public.gyp:mojo_application_base -source_set("application") { +mojo_sdk_source_set("application") { sources = [ "application_connection.h", "application_delegate.h", @@ -24,16 +26,16 @@ source_set("application") { "lib/weak_service_provider.h", ] - deps = [ - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", - "//mojo/public/interfaces/application", + mojo_sdk_deps = [ + "mojo/public/cpp/bindings", + "mojo/public/cpp/environment", + "mojo/public/cpp/system", + "mojo/public/interfaces/application", ] } # GYP version: mojo/public/mojo_public.gyp:mojo_application_standalone -source_set("standalone") { +mojo_sdk_source_set("standalone") { sources = [ "lib/application_runner.cc", ] @@ -42,13 +44,13 @@ source_set("standalone") { ":application", ] - deps = [ - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/utility", + mojo_sdk_deps = [ + "mojo/public/cpp/environment:standalone", + "mojo/public/cpp/utility", ] } -source_set("test_support") { +mojo_sdk_source_set("test_support") { testonly = true sources = [ "application_test_base.h", @@ -57,14 +59,17 @@ source_set("test_support") { deps = [ ":application", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", "//testing/gtest", ] + + mojo_sdk_deps = [ + "mojo/public/cpp/bindings", + "mojo/public/cpp/environment", + "mojo/public/cpp/system", + ] } -source_set("test_support_standalone") { +mojo_sdk_source_set("test_support_standalone") { testonly = true sources = [ "lib/application_test_main.cc", @@ -73,10 +78,14 @@ source_set("test_support_standalone") { public_deps = [ ":test_support", ] + deps = [ ":application", - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/system", - "//mojo/public/cpp/utility", + ] + + mojo_sdk_deps = [ + "mojo/public/cpp/environment:standalone", + "mojo/public/cpp/system", + "mojo/public/cpp/utility", ] } diff --git a/mojo/public/cpp/application/lib/application_test_main.cc b/mojo/public/cpp/application/lib/application_test_main.cc index 1c1395c..31919f9 100644 --- a/mojo/public/cpp/application/lib/application_test_main.cc +++ b/mojo/public/cpp/application/lib/application_test_main.cc @@ -27,7 +27,7 @@ MojoResult MojoMain(MojoHandle shell_handle) { mojo::ApplicationImpl app(&dummy_application_delegate, shell_handle); MOJO_CHECK(app.WaitForInitialize()); - // InitGoogleTest expects (argc + 1) elements, including a terminating NULL. + // InitGoogleTest expects (argc + 1) elements, including a terminating null. // It also removes GTEST arguments from |argv| and updates the |argc| count. const std::vector<std::string>& args = app.args(); MOJO_CHECK(args.size() < diff --git a/mojo/public/cpp/application/tests/BUILD.gn b/mojo/public/cpp/application/tests/BUILD.gn index 64c477e..0462e29 100644 --- a/mojo/public/cpp/application/tests/BUILD.gn +++ b/mojo/public/cpp/application/tests/BUILD.gn @@ -5,7 +5,6 @@ # GYP version: mojo/mojo_base.gyp:mojo_public_application_unittests test("mojo_public_application_unittests") { deps = [ - "//base", "//mojo/edk/test:run_all_unittests", "//mojo/public/cpp/application:standalone", "//mojo/public/cpp/environment:standalone", diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 4299fc6..1eb99d9 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("bindings") { +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("bindings") { sources = [ "array.h", "binding.h", @@ -55,12 +57,15 @@ source_set("bindings") { deps = [ ":callback", - "//mojo/public/cpp/environment", - "//mojo/public/cpp/system", + ] + + mojo_sdk_deps = [ + "mojo/public/cpp/environment", + "mojo/public/cpp/system", ] } -source_set("callback") { +mojo_sdk_source_set("callback") { sources = [ "callback.h", "lib/callback_internal.h", @@ -69,7 +74,5 @@ source_set("callback") { "lib/shared_ptr.h", ] - deps = [ - "//mojo/public/cpp/system", - ] + mojo_sdk_deps = [ "mojo/public/cpp/system" ] } diff --git a/mojo/public/cpp/environment/BUILD.gn b/mojo/public/cpp/environment/BUILD.gn index f322c55..87f24ff 100644 --- a/mojo/public/cpp/environment/BUILD.gn +++ b/mojo/public/cpp/environment/BUILD.gn @@ -2,24 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("environment") { +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("environment") { sources = [ "async_waiter.h", "logging.h", "environment.h", ] - public_deps = [ - "//mojo/public/c/environment", - ] + mojo_sdk_public_deps = [ "mojo/public/c/environment" ] - deps = [ - "//mojo/public/cpp/bindings:callback", - "//mojo/public/cpp/system", + mojo_sdk_deps = [ + "mojo/public/cpp/bindings:callback", + "mojo/public/cpp/system", ] } -source_set("standalone") { +mojo_sdk_source_set("standalone") { sources = [ "lib/async_waiter.cc", "lib/default_async_waiter.cc", @@ -34,8 +34,8 @@ source_set("standalone") { ":environment", ] - deps = [ - "//mojo/public/c/environment", - "//mojo/public/cpp/utility", + mojo_sdk_deps = [ + "mojo/public/c/environment", + "mojo/public/cpp/utility", ] } diff --git a/mojo/public/cpp/system/BUILD.gn b/mojo/public/cpp/system/BUILD.gn index 91b8b28..e120462 100644 --- a/mojo/public/cpp/system/BUILD.gn +++ b/mojo/public/cpp/system/BUILD.gn @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("system") { +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("system") { sources = [ "buffer.h", "core.h", @@ -13,7 +15,5 @@ source_set("system") { "message_pipe.h", ] - public_deps = [ - "//mojo/public/c/system", - ] + mojo_sdk_public_deps = [ "mojo/public/c/system" ] } diff --git a/mojo/public/cpp/test_support/BUILD.gn b/mojo/public/cpp/test_support/BUILD.gn index ad0280b..a1f7d31 100644 --- a/mojo/public/cpp/test_support/BUILD.gn +++ b/mojo/public/cpp/test_support/BUILD.gn @@ -2,19 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../../mojo_sdk.gni") + # GYP version: mojo/public/mojo_public.gyp:mojo_public_test_utils -source_set("test_utils") { +mojo_sdk_source_set("test_utils") { testonly = true - deps = [ - "//base", - "//mojo/public/c/test_support", - "//mojo/public/cpp/system", - "//testing/gtest", - ] sources = [ "lib/test_support.cc", "lib/test_utils.cc", "test_utils.h", ] + + deps = [ + "//testing/gtest", + ] + + mojo_sdk_deps = [ + "mojo/public/c/test_support", + "mojo/public/cpp/system", + ] } diff --git a/mojo/public/cpp/utility/BUILD.gn b/mojo/public/cpp/utility/BUILD.gn index a0898b9..9660a07 100644 --- a/mojo/public/cpp/utility/BUILD.gn +++ b/mojo/public/cpp/utility/BUILD.gn @@ -2,7 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("utility") { +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("utility") { sources = [ "mutex.h", "run_loop.h", @@ -16,9 +18,9 @@ source_set("utility") { "lib/thread_local_win.cc", ] - deps = [ - "//mojo/public/cpp/bindings:callback", - "//mojo/public/cpp/system", + mojo_sdk_deps = [ + "mojo/public/cpp/bindings:callback", + "mojo/public/cpp/system", ] if (is_win) { diff --git a/mojo/public/cpp/utility/lib/run_loop.cc b/mojo/public/cpp/utility/lib/run_loop.cc index 9707e7e..432365f 100644 --- a/mojo/public/cpp/utility/lib/run_loop.cc +++ b/mojo/public/cpp/utility/lib/run_loop.cc @@ -37,7 +37,7 @@ struct RunLoop::RunState { }; RunLoop::RunLoop() - : run_state_(NULL), next_handler_id_(0), next_sequence_number_(0) { + : run_state_(nullptr), next_handler_id_(0), next_sequence_number_(0) { assert(!current()); current_run_loop.Set(this); } @@ -45,7 +45,7 @@ RunLoop::RunLoop() RunLoop::~RunLoop() { assert(current() == this); NotifyHandlers(MOJO_RESULT_ABORTED, IGNORE_DEADLINE); - current_run_loop.Set(NULL); + current_run_loop.Set(nullptr); } // static diff --git a/mojo/public/cpp/utility/lib/thread.cc b/mojo/public/cpp/utility/lib/thread.cc index a248b1a..40f0bdd 100644 --- a/mojo/public/cpp/utility/lib/thread.cc +++ b/mojo/public/cpp/utility/lib/thread.cc @@ -49,7 +49,7 @@ void Thread::Join() { assert(!joined_); joined_ = true; - int rv = pthread_join(thread_, NULL); + int rv = pthread_join(thread_, nullptr); MOJO_ALLOW_UNUSED_LOCAL(rv); assert(rv == 0); } @@ -58,7 +58,7 @@ void Thread::Join() { void* Thread::ThreadRunTrampoline(void* arg) { Thread* self = static_cast<Thread*>(arg); self->Run(); - return NULL; + return nullptr; } } // namespace mojo diff --git a/mojo/public/cpp/utility/lib/thread_local_posix.cc b/mojo/public/cpp/utility/lib/thread_local_posix.cc index b33dfc6..ea7343e 100644 --- a/mojo/public/cpp/utility/lib/thread_local_posix.cc +++ b/mojo/public/cpp/utility/lib/thread_local_posix.cc @@ -11,7 +11,7 @@ namespace internal { // static void ThreadLocalPlatform::AllocateSlot(SlotType* slot) { - if (pthread_key_create(slot, NULL) != 0) { + if (pthread_key_create(slot, nullptr) != 0) { assert(false); } } diff --git a/mojo/public/cpp/utility/run_loop.h b/mojo/public/cpp/utility/run_loop.h index cb324aa..feb5b92 100644 --- a/mojo/public/cpp/utility/run_loop.h +++ b/mojo/public/cpp/utility/run_loop.h @@ -27,7 +27,7 @@ class RunLoop { // Cleans state created by Setup(). static void TearDown(); - // Returns the RunLoop for the current thread. Returns NULL if not yet + // Returns the RunLoop for the current thread. Returns null if not yet // created. static RunLoop* current(); @@ -62,7 +62,7 @@ class RunLoop { // Contains the data needed to track a request to AddHandler(). struct HandlerData { HandlerData() - : handler(NULL), + : handler(nullptr), handle_signals(MOJO_HANDLE_SIGNAL_NONE), deadline(0), id(0) {} @@ -112,7 +112,7 @@ class RunLoop { HandleToHandlerData handler_data_; - // If non-NULL we're running (inside Run()). Member references a value on the + // If non-null we're running (inside Run()). Member references a value on the // stack. RunState* run_state_; diff --git a/mojo/public/cpp/utility/tests/mutex_unittest.cc b/mojo/public/cpp/utility/tests/mutex_unittest.cc index d6f75da..78e95c5 100644 --- a/mojo/public/cpp/utility/tests/mutex_unittest.cc +++ b/mojo/public/cpp/utility/tests/mutex_unittest.cc @@ -90,7 +90,7 @@ class Fiddler { 0, // Seconds. (rand() % 10) * kNanosPerMilli // Nanoseconds. }; - int rv = nanosleep(&req, NULL); + int rv = nanosleep(&req, nullptr); MOJO_ALLOW_UNUSED_LOCAL(rv); assert(rv == 0); } diff --git a/mojo/public/cpp/utility/tests/run_loop_unittest.cc b/mojo/public/cpp/utility/tests/run_loop_unittest.cc index 1e21a13..4ab4876 100644 --- a/mojo/public/cpp/utility/tests/run_loop_unittest.cc +++ b/mojo/public/cpp/utility/tests/run_loop_unittest.cc @@ -71,8 +71,7 @@ TEST_F(RunLoopTest, ExitsWithNoHandles) { class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler { public: - RemoveOnReadyRunLoopHandler() : run_loop_(NULL) { - } + RemoveOnReadyRunLoopHandler() : run_loop_(nullptr) {} ~RemoveOnReadyRunLoopHandler() override {} void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } @@ -107,8 +106,7 @@ TEST_F(RunLoopTest, HandleReady) { class QuitOnReadyRunLoopHandler : public TestRunLoopHandler { public: - QuitOnReadyRunLoopHandler() : run_loop_(NULL) { - } + QuitOnReadyRunLoopHandler() : run_loop_(nullptr) {} ~QuitOnReadyRunLoopHandler() override {} void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } @@ -143,8 +141,7 @@ TEST_F(RunLoopTest, QuitFromReady) { class QuitOnErrorRunLoopHandler : public TestRunLoopHandler { public: - QuitOnErrorRunLoopHandler() : run_loop_(NULL) { - } + QuitOnErrorRunLoopHandler() : run_loop_(nullptr) {} ~QuitOnErrorRunLoopHandler() override {} void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } @@ -194,8 +191,7 @@ TEST_F(RunLoopTest, Destruction) { class RemoveManyRunLoopHandler : public TestRunLoopHandler { public: - RemoveManyRunLoopHandler() : run_loop_(NULL) { - } + RemoveManyRunLoopHandler() : run_loop_(nullptr) {} ~RemoveManyRunLoopHandler() override {} void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } @@ -246,8 +242,7 @@ TEST_F(RunLoopTest, MultipleHandleDestruction) { class AddHandlerOnErrorHandler : public TestRunLoopHandler { public: - AddHandlerOnErrorHandler() : run_loop_(NULL) { - } + AddHandlerOnErrorHandler() : run_loop_(nullptr) {} ~AddHandlerOnErrorHandler() override {} void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; } @@ -282,12 +277,12 @@ TEST_F(RunLoopTest, AddHandlerOnError) { } TEST_F(RunLoopTest, Current) { - EXPECT_TRUE(RunLoop::current() == NULL); + EXPECT_TRUE(RunLoop::current() == nullptr); { RunLoop run_loop; EXPECT_EQ(&run_loop, RunLoop::current()); } - EXPECT_TRUE(RunLoop::current() == NULL); + EXPECT_TRUE(RunLoop::current() == nullptr); } class NestingRunLoopHandler : public TestRunLoopHandler { @@ -296,8 +291,8 @@ class NestingRunLoopHandler : public TestRunLoopHandler { static const char kSignalMagic; NestingRunLoopHandler() - : run_loop_(NULL), - pipe_(NULL), + : run_loop_(nullptr), + pipe_(nullptr), depth_(0), reached_depth_limit_(false) {} @@ -335,9 +330,9 @@ class NestingRunLoopHandler : public TestRunLoopHandler { void WriteSignal() { char write_byte = kSignalMagic; - MojoResult write_result = WriteMessageRaw( - pipe_->handle1.get(), - &write_byte, 1, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); + MojoResult write_result = + WriteMessageRaw(pipe_->handle1.get(), &write_byte, 1, nullptr, 0, + MOJO_WRITE_MESSAGE_FLAG_NONE); EXPECT_EQ(write_result, MOJO_RESULT_OK); } @@ -345,10 +340,9 @@ class NestingRunLoopHandler : public TestRunLoopHandler { char read_byte = 0; uint32_t bytes_read = 1; uint32_t handles_read = 0; - MojoResult read_result = ReadMessageRaw( - pipe_->handle0.get(), - &read_byte, &bytes_read, NULL, &handles_read, - MOJO_READ_MESSAGE_FLAG_NONE); + MojoResult read_result = + ReadMessageRaw(pipe_->handle0.get(), &read_byte, &bytes_read, nullptr, + &handles_read, MOJO_READ_MESSAGE_FLAG_NONE); EXPECT_EQ(read_result, MOJO_RESULT_OK); EXPECT_EQ(read_byte, kSignalMagic); } diff --git a/mojo/public/dart/BUILD.gn b/mojo/public/dart/BUILD.gn deleted file mode 100644 index ce9373d..0000000 --- a/mojo/public/dart/BUILD.gn +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -group("dart") { - testonly = true - deps = [ - ":core", - ":bindings", - ] -} - -group("core") { - deps = [ - ":mojo_dart_core", - ":copy_core_library", - ] -} - -shared_library("mojo_dart_core") { - defines = [ "DART_SHARED_LIB" ] - sources = [ - "src/mojo_dart_core.cc", - ] - deps = [ - "//mojo/public/c/environment", - "//mojo/public/c/system:for_shared_library", - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/system", - "//mojo/public/cpp/utility", - "//mojo/public/cpp/bindings:callback", - ] -} - -copy("copy_core_library") { - sources = [ - "$root_out_dir/libmojo_dart_core.so", - ] - outputs = [ - "$root_out_dir/gen/mojo/public/dart/src/libmojo_dart_core.so", - ] - deps = [ - ":mojo_dart_core", - ] -} - -copy("bindings") { - sources = [ - "bindings.dart", - "core.dart", - "mojo_init.dart", - "src/buffer.dart", - "src/client.dart", - "src/codec.dart", - "src/data_pipe.dart", - "src/handle.dart", - "src/handle_watcher.dart", - "src/interface.dart", - "src/message_pipe.dart", - "src/types.dart", - ] - outputs = [ - "{{source_gen_dir}}/{{source_file_part}}", - ] -} diff --git a/mojo/public/dart/README b/mojo/public/dart/README index 5ff7ee3..f9cd6e6 100644 --- a/mojo/public/dart/README +++ b/mojo/public/dart/README @@ -2,54 +2,26 @@ These are interim instructions for building and testing Dart's Mojo bindings. These instructions currently only work for Linux, and assume you already have a Mojo checkout. -1.) Install the Dart SDK. +1.) Add a Dart VM source checkout to your client: -- apt-get - + Edit your .gclient file. Replace "DEPS" with "DEPS.dart". + Then, run: -Follow instructions at: https://www.dartlang.org/tools/debian.html + $ gclient sync -- Debian package - - -Download from: - -$ wget https://storage.googleapis.com/dart-archive/channels/dev/release/latest/linux_packages/debian_wheezy/dart_1.8.0-dev.2.0-1_amd64.deb -$ dpkg -i dart_1.8.0-dev.2.0-1_amd64.deb - -- From source - - -Follow instructions here: https://code.google.com/p/dart/wiki/Building - -and build the "create_sdk" target. - -With the first two options, dart is on your path and you are ready to go. -When building from source, you must explicitly add -e.g. out/ReleaseX64/dart-sdk/bin to your path. + You should now have a directory //dart 2.) Configure Mojo with Dart. - $ ./mojob.sh --release --with-dart gn + $ ./mojo/tools/mojob.py gn --release --with-dart 3.) Build Mojo with Dart. - $ ./mojob.sh --release build + $ ./mojo/tools/mojob.py build --release 4.) Run Dart tests. - $ ./mojob.sh --release darttest - - -These are instructions for adding a Dart VM source checkout to your client. - -1. Edit your .gclient file. - - Replace "DEPS" with "DEPS.dart" - -2. Run: - - $ gclient sync - - You should now have a directory //src/dart - + $ ./mojo/tools/mojob.py darttest --release diff --git a/mojo/public/dart/bindings.dart b/mojo/public/dart/bindings.dart index 1ae9697..63bb1e1 100644 --- a/mojo/public/dart/bindings.dart +++ b/mojo/public/dart/bindings.dart @@ -4,11 +4,10 @@ library bindings; -import 'core.dart' as core; import 'dart:async'; import 'dart:convert'; -import 'dart:core'; import 'dart:mirrors'; +import 'dart:mojo_core' as core; import 'dart:typed_data'; part 'src/client.dart'; diff --git a/mojo/public/dart/core.dart b/mojo/public/dart/core.dart index 6f26104..15b5363 100644 --- a/mojo/public/dart/core.dart +++ b/mojo/public/dart/core.dart @@ -5,16 +5,15 @@ library core; import 'dart:async'; -import 'dart:core'; +import 'dart:collection'; import 'dart:isolate'; import 'dart:typed_data'; -import 'dart-ext:src/mojo_dart_core'; part 'src/buffer.dart'; part 'src/data_pipe.dart'; part 'src/handle.dart'; part 'src/handle_watcher.dart'; part 'src/message_pipe.dart'; +part 'src/timer_impl.dart'; +part 'src/timer_queue.dart'; part 'src/types.dart'; - -void mojoSystemThunksSet(int thunks) native "MojoSystemThunks_Set"; diff --git a/mojo/public/dart/mojo_init.dart b/mojo/public/dart/mojo_init.dart deleted file mode 100644 index 2a1cd6d..0000000 --- a/mojo/public/dart/mojo_init.dart +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -library mojo_init; - -import 'dart:async'; - -import 'core.dart' as core; -import 'dart-ext:src/mojo_dart_init'; - -void _init() native "MojoLibrary_Init"; -void _mojoSystemThunksMake(Function fn) native "MojoSystemThunks_Make"; - -Future<Isolate> mojoInit() { - _init(); - _mojoSystemThunksMake(core.mojoSystemThunksSet); - return core.MojoHandleWatcher.Start(); -} - -void mojoShutdown() { - core.MojoHandleWatcher.Stop(); -} diff --git a/mojo/public/dart/src/buffer.dart b/mojo/public/dart/src/buffer.dart index a00838e..0e6bc2c 100644 --- a/mojo/public/dart/src/buffer.dart +++ b/mojo/public/dart/src/buffer.dart @@ -11,7 +11,11 @@ class _MojoSharedBufferNatives { static List Duplicate(int buffer_handle, int flags) native "MojoSharedBuffer_Duplicate"; - static List Map(int buffer_handle, int offset, int num_bytes, int flags) + static List Map(MojoSharedBuffer buffer, + int buffer_handle, + int offset, + int num_bytes, + int flags) native "MojoSharedBuffer_Map"; static int Unmap(ByteData buffer) @@ -66,7 +70,7 @@ class MojoSharedBuffer { MojoSharedBuffer dupe = new MojoSharedBuffer._(); dupe.status = r; dupe.handle = new RawMojoHandle(result[1]); - dupe.mapping = msb.mapping; + dupe.mapping = null; // The buffer is not mapped in the duplicate. return dupe; } @@ -87,7 +91,7 @@ class MojoSharedBuffer { return status; } List result = _MojoSharedBufferNatives.Map( - handle.h, offset, num_bytes, flags); + this, handle.h, offset, num_bytes, flags); if (result == null) { status = MojoResult.INVALID_ARGUMENT; return status; diff --git a/mojo/public/dart/src/codec.dart b/mojo/public/dart/src/codec.dart index 286df12..b19ac5c 100644 --- a/mojo/public/dart/src/codec.dart +++ b/mojo/public/dart/src/codec.dart @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// TODO(zra): Rewrite MojoDecoder and MojoEncoder using Dart idioms, and make +// corresponding changes to the bindings generation script. + part of bindings; const int kAlignment = 8; @@ -563,17 +566,10 @@ class MessageReader { } -abstract class MojoType<T> { - static const int encodedSize = 0; - static T decode(MojoDecoder decoder) { return null; } - static void encode(MojoEncoder encoder, T val) {} -} - - class PackedBool {} -class Int8 implements MojoType<int> { +class Int8 { static const int encodedSize = 1; static int decode(MojoDecoder decoder) => decoder.readInt8(); static void encode(MojoEncoder encoder, int val) { @@ -582,7 +578,7 @@ class Int8 implements MojoType<int> { } -class Uint8 implements MojoType<int> { +class Uint8 { static const int encodedSize = 1; static int decode(MojoDecoder decoder) => decoder.readUint8(); static void encode(MojoEncoder encoder, int val) { @@ -591,7 +587,7 @@ class Uint8 implements MojoType<int> { } -class Int16 implements MojoType<int> { +class Int16 { static const int encodedSize = 2; static int decode(MojoDecoder decoder) => decoder.readInt16(); static void encode(MojoEncoder encoder, int val) { @@ -600,7 +596,7 @@ class Int16 implements MojoType<int> { } -class Uint16 implements MojoType<int> { +class Uint16 { static const int encodedSize = 2; static int decode(MojoDecoder decoder) => decoder.readUint16(); static void encode(MojoEncoder encoder, int val) { @@ -609,7 +605,7 @@ class Uint16 implements MojoType<int> { } -class Int32 implements MojoType<int> { +class Int32 { static const int encodedSize = 4; static int decode(MojoDecoder decoder) => decoder.readInt32(); static void encode(MojoEncoder encoder, int val) { @@ -618,7 +614,7 @@ class Int32 implements MojoType<int> { } -class Uint32 implements MojoType<int> { +class Uint32 { static const int encodedSize = 4; static int decode(MojoDecoder decoder) => decoder.readUint32(); static void encode(MojoEncoder encoder, int val) { @@ -627,7 +623,7 @@ class Uint32 implements MojoType<int> { } -class Int64 implements MojoType<int> { +class Int64 { static const int encodedSize = 8; static int decode(MojoDecoder decoder) => decoder.readInt64(); static void encode(MojoEncoder encoder, int val) { @@ -636,7 +632,7 @@ class Int64 implements MojoType<int> { } -class Uint64 implements MojoType<int> { +class Uint64 { static const int encodedSize = 8; static int decode(MojoDecoder decoder) => decoder.readUint64(); static void encode(MojoEncoder encoder, int val) { @@ -645,7 +641,7 @@ class Uint64 implements MojoType<int> { } -class MojoString implements MojoType<String> { +class MojoString { static const int encodedSize = 8; static String decode(MojoDecoder decoder) => decoder.decodeStringPointer(); static void encode(MojoEncoder encoder, String val) { @@ -654,14 +650,14 @@ class MojoString implements MojoType<String> { } -class NullableMojoString implements MojoType<String> { +class NullableMojoString { static const int encodedSize = MojoString.encodedSize; static var decode = MojoString.decode; static var encode = MojoString.encode; } -class Float implements MojoType<double> { +class Float { static const int encodedSize = 4; static double decode(MojoDecoder decoder) => decoder.readFloat(); static void encode(MojoEncoder encoder, double val) { @@ -670,7 +666,7 @@ class Float implements MojoType<double> { } -class Double implements MojoType<double> { +class Double { static const int encodedSize = 8; static double decode(MojoDecoder decoder) => decoder.readDouble(); static void encode(MojoEncoder encoder, double val) { @@ -730,16 +726,17 @@ class NullableArrayOf extends ArrayOf { } -class Handle implements MojoType<core.RawMojoHandle> { +class Handle { static const int encodedSize = 4; - static core.RawMojoHandle decode(MojoDecoder decoder) => decoder.decodeHandle(); + static core.RawMojoHandle decode(MojoDecoder decoder) => + decoder.decodeHandle(); static void encode(MojoEncoder encoder, core.RawMojoHandle val) { encoder.encodeHandle(val); } } -class NullableHandle implements MojoType<int> { +class NullableHandle { static const int encodedSize = Handle.encodedSize; static const decode = Handle.decode; static const encode = Handle.encode; diff --git a/mojo/public/dart/src/handle_watcher.dart b/mojo/public/dart/src/handle_watcher.dart index 5f05654..1af15fd 100644 --- a/mojo/public/dart/src/handle_watcher.dart +++ b/mojo/public/dart/src/handle_watcher.dart @@ -45,7 +45,8 @@ class MojoHandleWatcher { static const int REMOVE = 1; static const int TOGGLE_WRITE = 2; static const int CLOSE = 3; - static const int SHUTDOWN = 4; + static const int TIMER = 4; + static const int SHUTDOWN = 5; static int _encodeCommand(int cmd, [int signals = 0]) => (cmd << 2) | (signals & MojoHandleSignals.READWRITE); @@ -75,6 +76,9 @@ class MojoHandleWatcher { // a RawMojoHandle. RawMojoHandle _tempHandle; + // Priority queue of timers registered with the watcher. + TimerQueue _timerQueue; + MojoHandleWatcher(this._controlHandle) : _shutdown = false, _handles = new List<int>(), @@ -82,7 +86,8 @@ class MojoHandleWatcher { _signals = new List<int>(), _handleIndices = new Map<int, int>(), _handleCount = 1, - _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID) { + _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID), + _timerQueue = new TimerQueue() { // Setup control handle. _handles.add(_controlHandle); _ports.add(null); // There is no port for the control handle. @@ -90,11 +95,13 @@ class MojoHandleWatcher { _handleIndices[_controlHandle] = 0; } - static void _handleWatcherIsolate(MojoHandleWatcher watcher) { + static void _handleWatcherIsolate(int consumerHandle) { + MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); while (!watcher._shutdown) { + int deadline = watcher._processTimerDeadlines(); int res = RawMojoHandle.waitMany(watcher._handles, watcher._signals, - RawMojoHandle.DEADLINE_INDEFINITE); + deadline); if (res == 0) { watcher._handleControlMessage(); } else if (res > 0) { @@ -103,7 +110,7 @@ class MojoHandleWatcher { watcher._routeEvent(res); // Remove the handle from the list. watcher._removeHandle(handle); - } else { + } else if (res != MojoResult.kDeadlineExceeded) { // Some handle was closed, but not by us. // We have to go through the list and find it. watcher._pruneClosedHandles(); @@ -133,8 +140,8 @@ class MojoHandleWatcher { void _handleControlMessage() { List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle); - // result[0] = mojo handle if any - // result[1] = SendPort if any + // result[0] = mojo handle if any, or a timer deadline in milliseconds. + // result[1] = SendPort if any. // result[2] = command << 2 | WRITABLE | READABLE int signals = result[2] & MojoHandleSignals.READWRITE; @@ -152,6 +159,9 @@ class MojoHandleWatcher { case CLOSE: _close(result[0]); break; + case TIMER: + _timer(result[1], result[0]); + break; case SHUTDOWN: _shutdownHandleWatcher(); break; @@ -217,6 +227,22 @@ class MojoHandleWatcher { _removeHandle(mojoHandle); } + // Returns the next timer deadline in units of microseconds from 'now'. + int _processTimerDeadlines() { + int now = (new DateTime.now()).millisecondsSinceEpoch; + while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { + _timerQueue.currentPort.send(null); + _timerQueue.removeCurrent(); + now = (new DateTime.now()).millisecondsSinceEpoch; + } + return _timerQueue.hasTimer ? (_timerQueue.currentTimeout - now) * 1000 + : RawMojoHandle.DEADLINE_INDEFINITE; + } + + void _timer(SendPort port, int deadline) { + _timerQueue.updateTimer(port, deadline); + } + void _toggleWrite(int mojoHandle) { int idx = _handleIndices[mojoHandle]; if (idx == null) { @@ -274,14 +300,11 @@ class MojoHandleWatcher { int consumerHandle = pipe.endpoints[0].handle.h; int producerHandle = pipe.endpoints[1].handle.h; - // Make a MojoHandleWatcher with one end. - MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); - // Call setControlHandle with the other end. _MojoHandleWatcherNatives.setControlHandle(producerHandle); // Spawn the handle watcher isolate with the MojoHandleWatcher, - return Isolate.spawn(_handleWatcherIsolate, watcher); + return Isolate.spawn(_handleWatcherIsolate, consumerHandle); } static void Stop() { @@ -292,6 +315,9 @@ class MojoHandleWatcher { int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); var handle = new RawMojoHandle(controlHandle); handle.close(); + + // Invalidate the control handle. + _MojoHandleWatcherNatives.setControlHandle(RawMojoHandle.INVALID); } static MojoResult close(RawMojoHandle mojoHandle) { @@ -309,4 +335,10 @@ class MojoHandleWatcher { static MojoResult remove(RawMojoHandle mojoHandle) { return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); } + + static MojoResult timer(SendPort port, int deadline) { + // The deadline will be unwrapped before sending to the handle watcher. + return _sendControlData( + new RawMojoHandle(deadline), port, _encodeCommand(TIMER)); + } } diff --git a/mojo/public/dart/src/interface.dart b/mojo/public/dart/src/interface.dart index 298ab72..76807ed 100644 --- a/mojo/public/dart/src/interface.dart +++ b/mojo/public/dart/src/interface.dart @@ -30,7 +30,7 @@ abstract class Interface { // Read the data and view as a message. var bytes = new ByteData(result.bytesRead); - var handles = new List<RawMojoHandle>(result.handlesRead); + var handles = new List<core.RawMojoHandle>(result.handlesRead); result = _endpoint.read(bytes, result.bytesRead, handles); if (!result.status.isOk && !result.status.isResourceExhausted) { // If something else happens, it means the handle wasn't really ready diff --git a/mojo/public/dart/src/mojo_dart_core.cc b/mojo/public/dart/src/mojo_dart_core.cc deleted file mode 100644 index 27b2e3f..0000000 --- a/mojo/public/dart/src/mojo_dart_core.cc +++ /dev/null @@ -1,809 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stdio.h> -#include <string.h> - -#include "base/memory/scoped_ptr.h" -#include "dart/runtime/include/dart_api.h" -#include "mojo/public/c/system/core.h" -#include "mojo/public/platform/native/system_thunks.h" - - -static Dart_NativeFunction ResolveName( - Dart_Handle name, int argc, bool* auto_setup_scope); - - -DART_EXPORT Dart_Handle mojo_dart_core_Init(Dart_Handle parent_library) { - if (Dart_IsError(parent_library)) { - return parent_library; - } - - Dart_Handle result_code = Dart_SetNativeResolver( - parent_library, ResolveName, NULL); - if (Dart_IsError(result_code)) { - return result_code; - } - - return Dart_Null(); -} - - -static Dart_Handle HandleError(Dart_Handle handle) { - if (Dart_IsError(handle)) { - Dart_PropagateError(handle); - } - return handle; -} - - -static void SetNullReturn(Dart_NativeArguments arguments) { - Dart_SetReturnValue(arguments, Dart_Null()); -} - - -static void SetInvalidArgumentReturn(Dart_NativeArguments arguments) { - Dart_SetIntegerReturnValue( - arguments, static_cast<int64_t>(MOJO_RESULT_INVALID_ARGUMENT)); -} - - -#define CHECK_INTEGER_ARGUMENT(args, num, result, failure) \ - { \ - Dart_Handle __status; \ - __status = Dart_GetNativeIntegerArgument(args, num, result); \ - if (Dart_IsError(__status)) { \ - Set##failure##Return(arguments); \ - return; \ - } \ - } \ - - -extern "C" { - extern size_t MojoSetSystemThunks(const MojoSystemThunks* system_thunks); -} - - -static void MojoSystemThunks_Set(Dart_NativeArguments arguments) { - int64_t thunks_addr = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &thunks_addr, Null); - - MojoSystemThunks* thunks = reinterpret_cast<MojoSystemThunks*>(thunks_addr); - MojoSetSystemThunks(thunks); - - Dart_SetReturnValue(arguments, Dart_Null()); -} - - -struct CloserCallbackPeer { - MojoHandle handle; -}; - - -static void MojoHandleCloserCallback(void* isolate_data, - Dart_WeakPersistentHandle handle, - void* peer) { - CloserCallbackPeer* callback_peer = - reinterpret_cast<CloserCallbackPeer*>(peer); - if (callback_peer->handle != MOJO_HANDLE_INVALID) { - MojoClose(callback_peer->handle); - } - delete callback_peer; -} - - -// Setup a weak persistent handle for a Dart MojoHandle that calls MojoClose -// on the handle when the MojoHandle is GC'd or the VM is going down. -static void MojoHandle_Register(Dart_NativeArguments arguments) { - // An instance of Dart class MojoHandle. - Dart_Handle mojo_handle_instance = Dart_GetNativeArgument(arguments, 0); - if (!Dart_IsInstance(mojo_handle_instance)) { - SetInvalidArgumentReturn(arguments); - return; - } - // TODO(zra): Here, we could check that mojo_handle_instance is really a - // MojoHandle instance, but with the Dart API it's not too easy to get a Type - // object from the class name outside of the root library. For now, we'll rely - // on the existence of the right fields to be sufficient. - - Dart_Handle raw_mojo_handle_instance = Dart_GetField( - mojo_handle_instance, Dart_NewStringFromCString("_handle")); - if (Dart_IsError(raw_mojo_handle_instance)) { - SetInvalidArgumentReturn(arguments); - return; - } - - Dart_Handle mojo_handle = Dart_GetField( - raw_mojo_handle_instance, Dart_NewStringFromCString("h")); - if (Dart_IsError(mojo_handle)) { - SetInvalidArgumentReturn(arguments); - return; - } - - int64_t raw_handle = static_cast<int64_t>(MOJO_HANDLE_INVALID); - Dart_Handle result = Dart_IntegerToInt64(mojo_handle, &raw_handle); - if (Dart_IsError(result)) { - SetInvalidArgumentReturn(arguments); - return; - } - - if (raw_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) { - SetInvalidArgumentReturn(arguments); - return; - } - - CloserCallbackPeer* callback_peer = new CloserCallbackPeer(); - callback_peer->handle = static_cast<MojoHandle>(raw_handle); - Dart_NewWeakPersistentHandle(mojo_handle_instance, - reinterpret_cast<void*>(callback_peer), - sizeof(CloserCallbackPeer), - MojoHandleCloserCallback); - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK)); -} - - -static void MojoHandle_Close(Dart_NativeArguments arguments) { - int64_t handle; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); - - MojoResult res = MojoClose(static_cast<MojoHandle>(handle)); - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoHandle_Wait(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t signals = 0; - int64_t deadline = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 1, &signals, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 2, &deadline, InvalidArgument); - - MojoResult r = MojoWait(static_cast<MojoHandle>(handle), - static_cast<MojoHandleSignals>(signals), - static_cast<MojoDeadline>(deadline)); - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(r)); -} - - -static void MojoHandle_WaitMany(Dart_NativeArguments arguments) { - int64_t num_handles = 0; - int64_t deadline = 0; - Dart_Handle handles = Dart_GetNativeArgument(arguments, 0); - Dart_Handle signals = Dart_GetNativeArgument(arguments, 1); - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_handles, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 3, &deadline, InvalidArgument); - - if (!Dart_IsList(handles) || !Dart_IsList(signals)) { - SetInvalidArgumentReturn(arguments); - return; - } - - intptr_t handles_len = 0; - intptr_t signals_len = 0; - Dart_ListLength(handles, &handles_len); - Dart_ListLength(signals, &signals_len); - if ((handles_len != num_handles) || (signals_len != num_handles)) { - SetInvalidArgumentReturn(arguments); - return; - } - - scoped_ptr<MojoHandle[]> mojo_handles(new MojoHandle[num_handles]); - scoped_ptr<MojoHandleSignals[]> mojo_signals( - new MojoHandleSignals[num_handles]); - - for (int i = 0; i < num_handles; i++) { - Dart_Handle dart_handle = Dart_ListGetAt(handles, i); - Dart_Handle dart_signal = Dart_ListGetAt(signals, i); - if (!Dart_IsInteger(dart_handle) || !Dart_IsInteger(dart_signal)) { - SetInvalidArgumentReturn(arguments); - return; - } - int64_t mojo_handle = 0; - int64_t mojo_signal = 0; - Dart_IntegerToInt64(dart_handle, &mojo_handle); - Dart_IntegerToInt64(dart_signal, &mojo_signal); - mojo_handles[i] = static_cast<MojoHandle>(mojo_handle); - mojo_signals[i] = static_cast<MojoHandleSignals>(mojo_signal); - } - - MojoResult res = MojoWaitMany(mojo_handles.get(), mojo_signals.get(), - static_cast<uint32_t>(num_handles), - static_cast<MojoDeadline>(deadline)); - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoSharedBuffer_Create(Dart_NativeArguments arguments) { - int64_t num_bytes = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &num_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); - - MojoCreateSharedBufferOptions options; - options.struct_size = sizeof(MojoCreateSharedBufferOptions); - options.flags = static_cast<MojoCreateSharedBufferOptionsFlags>(flags); - - MojoHandle out = MOJO_HANDLE_INVALID;; - MojoResult res = MojoCreateSharedBuffer( - &options, static_cast<int32_t>(num_bytes), &out); - - Dart_Handle list = Dart_NewList(2); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(out)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoSharedBuffer_Duplicate(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &flags, Null); - - MojoDuplicateBufferHandleOptions options; - options.struct_size = sizeof(MojoDuplicateBufferHandleOptions); - options.flags = static_cast<MojoDuplicateBufferHandleOptionsFlags>(flags); - - MojoHandle out = MOJO_HANDLE_INVALID;; - MojoResult res = MojoDuplicateBufferHandle( - static_cast<MojoHandle>(handle), &options, &out); - - Dart_Handle list = Dart_NewList(2); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(out)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoSharedBuffer_Map(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t offset = 0; - int64_t num_bytes = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &offset, Null); - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); - - void* out; - MojoResult res = MojoMapBuffer(static_cast<MojoHandle>(handle), - offset, - num_bytes, - &out, - static_cast<MojoMapBufferFlags>(flags)); - - Dart_Handle list = Dart_NewList(2); - Dart_Handle typed_data; - if (res == MOJO_RESULT_OK) { - typed_data = Dart_NewExternalTypedData( - Dart_TypedData_kByteData, out, num_bytes); - } else { - typed_data = Dart_Null(); - } - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, typed_data); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoSharedBuffer_Unmap(Dart_NativeArguments arguments) { - Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 0); - if (!Dart_IsTypedData(typed_data)) { - SetInvalidArgumentReturn(arguments); - return; - } - - Dart_TypedData_Type typ; - void *data; - intptr_t len; - Dart_TypedDataAcquireData(typed_data, &typ, &data, &len); - MojoResult res = MojoUnmapBuffer(data); - Dart_TypedDataReleaseData(typed_data); - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoDataPipe_Create(Dart_NativeArguments arguments) { - int64_t element_bytes = 0; - int64_t capacity_bytes = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &element_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &capacity_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); - - MojoCreateDataPipeOptions options; - options.struct_size = sizeof(MojoCreateDataPipeOptions); - options.flags = static_cast<MojoCreateDataPipeOptionsFlags>(flags); - options.element_num_bytes = static_cast<uint32_t>(element_bytes); - options.capacity_num_bytes = static_cast<uint32_t>(capacity_bytes); - - MojoHandle producer = MOJO_HANDLE_INVALID; - MojoHandle consumer = MOJO_HANDLE_INVALID; - MojoResult res = MojoCreateDataPipe(&options, &producer, &consumer); - - Dart_Handle list = Dart_NewList(3); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(producer)); - Dart_ListSetAt(list, 2, Dart_NewInteger(consumer)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoDataPipe_WriteData(Dart_NativeArguments arguments) { - int64_t handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - - Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); - if (!Dart_IsTypedData(typed_data)) { - SetNullReturn(arguments); - return; - } - - int64_t num_bytes = 0; - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); - - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); - - Dart_TypedData_Type type; - void* data; - intptr_t data_length; - Dart_TypedDataAcquireData(typed_data, &type, &data, &data_length); - uint32_t length = static_cast<uint32_t>(num_bytes); - MojoResult res = MojoWriteData( - static_cast<MojoHandle>(handle), - data, - &length, - static_cast<MojoWriteDataFlags>(flags)); - Dart_TypedDataReleaseData(typed_data); - - Dart_Handle list = Dart_NewList(2); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(length)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoDataPipe_BeginWriteData(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t buffer_bytes = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); - - void* buffer; - uint32_t size = static_cast<uint32_t>(buffer_bytes); - MojoResult res = MojoBeginWriteData( - static_cast<MojoHandle>(handle), - &buffer, - &size, - static_cast<MojoWriteDataFlags>(flags)); - - Dart_Handle list = Dart_NewList(2); - Dart_Handle typed_data; - if (res == MOJO_RESULT_OK) { - typed_data = Dart_NewExternalTypedData( - Dart_TypedData_kByteData, buffer, size); - } else { - typed_data = Dart_Null(); - } - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, typed_data); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoDataPipe_EndWriteData(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t num_bytes_written = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_written, InvalidArgument); - - MojoResult res = MojoEndWriteData( - static_cast<MojoHandle>(handle), - static_cast<uint32_t>(num_bytes_written)); - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoDataPipe_ReadData(Dart_NativeArguments arguments) { - int64_t handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - - Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); - if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { - SetNullReturn(arguments); - return; - } - - int64_t num_bytes = 0; - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); - - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 3, &flags, Null); - - Dart_TypedData_Type typ; - void* data = NULL; - intptr_t bdlen = 0; - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataAcquireData(typed_data, &typ, &data, &bdlen); - } - uint32_t len = static_cast<uint32_t>(num_bytes); - MojoResult res = MojoReadData( - static_cast<MojoHandle>(handle), - data, - &len, - static_cast<MojoReadDataFlags>(flags)); - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataReleaseData(typed_data); - } - - Dart_Handle list = Dart_NewList(2); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(len)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoDataPipe_BeginReadData(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t buffer_bytes = 0; - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - CHECK_INTEGER_ARGUMENT(arguments, 1, &buffer_bytes, Null); - CHECK_INTEGER_ARGUMENT(arguments, 2, &flags, Null); - - void* buffer; - uint32_t size = static_cast<uint32_t>(buffer_bytes); - MojoResult res = MojoBeginReadData( - static_cast<MojoHandle>(handle), - const_cast<const void**>(&buffer), - &size, - static_cast<MojoWriteDataFlags>(flags)); - - Dart_Handle list = Dart_NewList(2); - Dart_Handle typed_data; - if (res == MOJO_RESULT_OK) { - typed_data = Dart_NewExternalTypedData( - Dart_TypedData_kByteData, buffer, size); - } else { - typed_data = Dart_Null(); - } - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, typed_data); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoDataPipe_EndReadData(Dart_NativeArguments arguments) { - int64_t handle = 0; - int64_t num_bytes_read = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 1, &num_bytes_read, InvalidArgument); - - MojoResult res = MojoEndReadData( - static_cast<MojoHandle>(handle), - static_cast<uint32_t>(num_bytes_read)); - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoMessagePipe_Create(Dart_NativeArguments arguments) { - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &flags, Null); - - MojoCreateMessagePipeOptions options; - options.struct_size = sizeof(MojoCreateMessagePipeOptions); - options.flags = static_cast<MojoCreateMessagePipeOptionsFlags>(flags); - - MojoHandle end1 = MOJO_HANDLE_INVALID; - MojoHandle end2 = MOJO_HANDLE_INVALID; - MojoResult res = MojoCreateMessagePipe(&options, &end1, &end2); - - Dart_Handle list = Dart_NewList(3); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(end1)); - Dart_ListSetAt(list, 2, Dart_NewInteger(end2)); - Dart_SetReturnValue(arguments, list); -} - - -static void MojoMessagePipe_Write(Dart_NativeArguments arguments) { - int64_t handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, InvalidArgument); - - Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); - if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { - SetInvalidArgumentReturn(arguments); - return; - } - - int64_t num_bytes = 0; - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, InvalidArgument); - - Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); - if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { - SetInvalidArgumentReturn(arguments); - return; - } - - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, InvalidArgument); - - // Grab the data if there is any. - Dart_TypedData_Type typ; - void* bytes = NULL; - intptr_t bdlen = 0; - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &bdlen); - } - - // Grab the handles if there are any. - scoped_ptr<MojoHandle[]> mojo_handles; - intptr_t handles_len = 0; - if (!Dart_IsNull(handles)) { - Dart_ListLength(handles, &handles_len); - mojo_handles.reset(new MojoHandle[handles_len]); - for (int i = 0; i < handles_len; i++) { - Dart_Handle dart_handle = Dart_ListGetAt(handles, i); - if (!Dart_IsInteger(dart_handle)) { - SetInvalidArgumentReturn(arguments); - return; - } - int64_t mojo_handle = 0; - Dart_IntegerToInt64(dart_handle, &mojo_handle); - mojo_handles[i] = static_cast<MojoHandle>(mojo_handle); - } - } - - MojoResult res = MojoWriteMessage( - static_cast<MojoHandle>(handle), - const_cast<const void*>(bytes), - static_cast<uint32_t>(num_bytes), - mojo_handles.get(), - static_cast<uint32_t>(handles_len), - static_cast<MojoWriteMessageFlags>(flags)); - - // Release the data. - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataReleaseData(typed_data); - } - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoMessagePipe_Read(Dart_NativeArguments arguments) { - int64_t handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &handle, Null); - - Dart_Handle typed_data = Dart_GetNativeArgument(arguments, 1); - if (!Dart_IsTypedData(typed_data) && !Dart_IsNull(typed_data)) { - SetNullReturn(arguments); - return; - } - - int64_t num_bytes = 0; - CHECK_INTEGER_ARGUMENT(arguments, 2, &num_bytes, Null); - - Dart_Handle handles = Dart_GetNativeArgument(arguments, 3); - if (!Dart_IsList(handles) && !Dart_IsNull(handles)) { - SetNullReturn(arguments); - return; - } - - int64_t flags = 0; - CHECK_INTEGER_ARGUMENT(arguments, 4, &flags, Null); - - // Grab the data if there is any. - Dart_TypedData_Type typ; - void* bytes = NULL; - intptr_t byte_data_len = 0; - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataAcquireData(typed_data, &typ, &bytes, &byte_data_len); - } - uint32_t blen = static_cast<uint32_t>(num_bytes); - - // Grab the handles if there are any. - scoped_ptr<MojoHandle[]> mojo_handles; - intptr_t handles_len = 0; - if (!Dart_IsNull(handles)) { - Dart_ListLength(handles, &handles_len); - mojo_handles.reset(new MojoHandle[handles_len]); - } - uint32_t hlen = static_cast<uint32_t>(handles_len); - - MojoResult res = MojoReadMessage( - static_cast<MojoHandle>(handle), - bytes, - &blen, - mojo_handles.get(), - &hlen, - static_cast<MojoReadMessageFlags>(flags)); - - // Release the data. - if (!Dart_IsNull(typed_data)) { - Dart_TypedDataReleaseData(typed_data); - } - - if (!Dart_IsNull(handles)) { - for (int i = 0; i < handles_len; i++) { - Dart_ListSetAt(handles, i, Dart_NewInteger(mojo_handles[i])); - } - } - - Dart_Handle list = Dart_NewList(3); - Dart_ListSetAt(list, 0, Dart_NewInteger(res)); - Dart_ListSetAt(list, 1, Dart_NewInteger(blen)); - Dart_ListSetAt(list, 2, Dart_NewInteger(hlen)); - Dart_SetReturnValue(arguments, list); -} - - -struct ControlData { - int64_t handle; - Dart_Port port; - int64_t data; -}; - - -static void MojoHandleWatcher_SendControlData(Dart_NativeArguments arguments) { - int64_t control_handle = 0; - int64_t client_handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); - CHECK_INTEGER_ARGUMENT(arguments, 1, &client_handle, InvalidArgument); - - Dart_Handle send_port_handle = Dart_GetNativeArgument(arguments, 2); - Dart_Port send_port_id = 0; - if (!Dart_IsNull(send_port_handle)) { - Dart_Handle result = Dart_SendPortGetId(send_port_handle, &send_port_id); - if (Dart_IsError(result)) { - SetInvalidArgumentReturn(arguments); - return; - } - } - - int64_t data = 0; - CHECK_INTEGER_ARGUMENT(arguments, 3, &data, InvalidArgument); - - ControlData cd; - cd.handle = client_handle; - cd.port = send_port_id; - cd.data = data; - const void* bytes = reinterpret_cast<const void*>(&cd); - MojoResult res = MojoWriteMessage( - control_handle, bytes, sizeof(cd), NULL, 0, 0); - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(res)); -} - - -static void MojoHandleWatcher_RecvControlData(Dart_NativeArguments arguments) { - int64_t control_handle = 0; - CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, Null); - - ControlData cd; - void* bytes = reinterpret_cast<void*>(&cd); - uint32_t num_bytes = sizeof(cd); - uint32_t num_handles = 0; - MojoResult res = MojoReadMessage( - control_handle, bytes, &num_bytes, NULL, &num_handles, 0); - if (res != MOJO_RESULT_OK) { - SetNullReturn(arguments); - return; - } - - Dart_Handle list = Dart_NewList(3); - Dart_ListSetAt(list, 0, Dart_NewInteger(cd.handle)); - Dart_ListSetAt(list, 1, Dart_NewSendPort(cd.port)); - Dart_ListSetAt(list, 2, Dart_NewInteger(cd.data)); - Dart_SetReturnValue(arguments, list); -} - - -static int64_t mojo_control_handle = MOJO_HANDLE_INVALID; -static void MojoHandleWatcher_SetControlHandle(Dart_NativeArguments arguments) { - int64_t control_handle; - CHECK_INTEGER_ARGUMENT(arguments, 0, &control_handle, InvalidArgument); - - if (mojo_control_handle == static_cast<int64_t>(MOJO_HANDLE_INVALID)) { - mojo_control_handle = control_handle; - } - - Dart_SetIntegerReturnValue(arguments, static_cast<int64_t>(MOJO_RESULT_OK)); -} - - -static void MojoHandleWatcher_GetControlHandle(Dart_NativeArguments arguments) { - Dart_SetIntegerReturnValue(arguments, mojo_control_handle); -} - - -#define SCOPE_FUNCTIONS(V) \ - V(MojoSharedBuffer_Create) \ - V(MojoSharedBuffer_Duplicate) \ - V(MojoSharedBuffer_Map) \ - V(MojoSharedBuffer_Unmap) \ - V(MojoDataPipe_Create) \ - V(MojoDataPipe_WriteData) \ - V(MojoDataPipe_BeginWriteData) \ - V(MojoDataPipe_ReadData) \ - V(MojoDataPipe_BeginReadData) \ - V(MojoDataPipe_EndReadData) \ - V(MojoMessagePipe_Create) \ - V(MojoMessagePipe_Write) \ - V(MojoMessagePipe_Read) \ - V(MojoHandle_Register) \ - V(MojoHandle_WaitMany) \ - V(MojoHandleWatcher_SendControlData) \ - V(MojoHandleWatcher_RecvControlData) \ - -#define NOSCOPE_FUNCTIONS(V) \ - V(MojoSystemThunks_Set) \ - V(MojoHandle_Close) \ - V(MojoHandle_Wait) \ - V(MojoDataPipe_EndWriteData) \ - V(MojoHandleWatcher_SetControlHandle) \ - V(MojoHandleWatcher_GetControlHandle) \ - -#define FUNCTION_STRING_MAP(name) {#name, name}, - -struct FunctionLookup { - const char* name; - Dart_NativeFunction function; -}; - -FunctionLookup function_list[] = { - SCOPE_FUNCTIONS(FUNCTION_STRING_MAP) - {NULL, NULL} -}; - -FunctionLookup no_scope_function_list[] = { - NOSCOPE_FUNCTIONS(FUNCTION_STRING_MAP) - {NULL, NULL} -}; - -#undef FUNCTION_STRING_MAP - - -Dart_NativeFunction ResolveName(Dart_Handle name, - int argc, - bool* auto_setup_scope) { - if (!Dart_IsString(name)) { - return NULL; - } - Dart_NativeFunction result = NULL; - if (auto_setup_scope == NULL) { - return NULL; - } - - Dart_EnterScope(); - const char* cname; - HandleError(Dart_StringToCString(name, &cname)); - - for (int i=0; function_list[i].name != NULL; ++i) { - if (strcmp(function_list[i].name, cname) == 0) { - *auto_setup_scope = true; - Dart_ExitScope(); - return function_list[i].function; - } - } - - for (int i=0; no_scope_function_list[i].name != NULL; ++i) { - if (strcmp(no_scope_function_list[i].name, cname) == 0) { - *auto_setup_scope = false; - result = no_scope_function_list[i].function; - break; - } - } - - Dart_ExitScope(); - return result; -} diff --git a/mojo/public/dart/src/timer_impl.dart b/mojo/public/dart/src/timer_impl.dart new file mode 100644 index 0000000..61fee6d --- /dev/null +++ b/mojo/public/dart/src/timer_impl.dart @@ -0,0 +1,333 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This code is adapted from the Timer implementation in the standalone Dart VM +// for use in the Mojo embedder. + +part of core; + +// Timer heap implemented as a array-based binary heap[0]. +// This allows for O(1) `first`, O(log(n)) `remove`/`removeFirst` and O(log(n)) +// `add`. +// +// To ensure the timers are ordered by insertion time, the _Timer class has a +// `_id` field set when added to the heap. +// +// [0] http://en.wikipedia.org/wiki/Binary_heap +class _TimerHeap { + List<_Timer> _list; + int _used = 0; + + _TimerHeap([int initSize = 7]) + : _list = new List<_Timer>(initSize); + + bool get isEmpty => _used == 0; + bool get isNotEmpty => _used > 0; + + _Timer get first => _list[0]; + + bool isFirst(_Timer timer) => timer._indexOrNext == 0; + + void add(_Timer timer) { + if (_used == _list.length) { + _resize(); + } + timer._indexOrNext = _used++; + _list[timer._indexOrNext] = timer; + _bubbleUp(timer); + } + + _Timer removeFirst() { + var f = first; + remove(f); + return f; + } + + void remove(_Timer timer) { + _used--; + timer._id = -1; + if (isEmpty) { + _list[0] = null; + timer._indexOrNext = null; + return; + } + var last = _list[_used]; + if (!identical(last, timer)) { + last._indexOrNext = timer._indexOrNext; + _list[last._indexOrNext] = last; + if (last._compareTo(timer) < 0) { + _bubbleUp(last); + } else { + _bubbleDown(last); + } + } + _list[_used] = null; + timer._indexOrNext = null; + } + + void _resize() { + var newList = new List(_list.length * 2 + 1); + newList.setRange(0, _used, _list); + _list = newList; + } + + void _bubbleUp(_Timer timer) { + while (!isFirst(timer)) { + Timer parent = _parent(timer); + if (timer._compareTo(parent) < 0) { + _swap(timer, parent); + } else { + break; + } + } + } + + void _bubbleDown(_Timer timer) { + while (true) { + int leftIndex = _leftChildIndex(timer._indexOrNext); + int rightIndex = _rightChildIndex(timer._indexOrNext); + _Timer newest = timer; + if (leftIndex < _used && _list[leftIndex]._compareTo(newest) < 0) { + newest = _list[leftIndex]; + } + if (rightIndex < _used && _list[rightIndex]._compareTo(newest) < 0) { + newest = _list[rightIndex]; + } + if (identical(newest, timer)) { + // We are where we should be, break. + break; + } + _swap(newest, timer); + } + } + + void _swap(_Timer first, _Timer second) { + int tmp = first._indexOrNext; + first._indexOrNext = second._indexOrNext; + second._indexOrNext = tmp; + _list[first._indexOrNext] = first; + _list[second._indexOrNext] = second; + } + + Timer _parent(_Timer timer) => _list[_parentIndex(timer._indexOrNext)]; + Timer _leftChild(_Timer timer) => _list[_leftChildIndex(timer._indexOrNext)]; + Timer _rightChild(_Timer timer) => + _list[_rightChildIndex(timer._indexOrNext)]; + + static int _parentIndex(int index) => (index - 1) ~/ 2; + static int _leftChildIndex(int index) => 2 * index + 1; + static int _rightChildIndex(int index) => 2 * index + 2; +} + +class _Timer implements Timer { + // Disables the timer. + static const int _NO_TIMER = -1; + + // Timers are ordered by wakeup time. + static _TimerHeap _heap = new _TimerHeap(); + static _Timer _firstZeroTimer; + static _Timer _lastZeroTimer; + static int _idCount = 0; + + static RawReceivePort _receivePort; + static SendPort _sendPort; + static bool _handlingCallbacks = false; + + Function _callback; + int _milliSeconds; + int _wakeupTime = 0; + var _indexOrNext; + int _id = -1; + + static Timer _createTimer(void callback(Timer timer), + int milliSeconds, + bool repeating) { + _Timer timer = new _Timer._internal(); + timer._callback = callback; + if (milliSeconds > 0) { + // Add one because DateTime.now() is assumed to round down + // to nearest millisecond, not up, so that time + duration is before + // duration milliseconds from now. Using micosecond timers like + // Stopwatch allows detecting that the timer fires early. + timer._wakeupTime = + new DateTime.now().millisecondsSinceEpoch + 1 + milliSeconds; + } + timer._milliSeconds = repeating ? milliSeconds : -1; + if (timer._addTimerToHeap()) { + // The new timer is the first in queue. Update event handler. + _notifyEventHandler(); + } + return timer; + } + + factory _Timer(int milliSeconds, void callback(Timer timer)) { + return _createTimer(callback, milliSeconds, false); + } + + factory _Timer.periodic(int milliSeconds, void callback(Timer timer)) { + return _createTimer(callback, milliSeconds, true); + } + + _Timer._internal() {} + + bool get _isInHeap => _id >= 0; + + void _clear() { + _callback = null; + } + + int _compareTo(_Timer other) { + int c = _wakeupTime - other._wakeupTime; + if (c != 0) return c; + return _id - other._id; + } + + bool get _repeating => _milliSeconds >= 0; + + bool get isActive => _callback != null; + + // Cancels a set timer. The timer is removed from the timer list and if + // the given timer is the earliest timer the native timer is reset. + void cancel() { + _clear(); + if (!_isInHeap) return; + assert(_wakeupTime != 0); + bool update = (_firstZeroTimer == null) && _heap.isFirst(this); + _heap.remove(this); + if (update) { + _notifyEventHandler(); + } + } + + void _advanceWakeupTime() { + assert(_milliSeconds >= 0); + _wakeupTime += _milliSeconds; + } + + // Adds a timer to the timer list. Timers with the same wakeup time are + // enqueued in order and notified in FIFO order. + bool _addTimerToHeap() { + if (_wakeupTime == 0) { + if (_firstZeroTimer == null) { + _lastZeroTimer = this; + _firstZeroTimer = this; + return true; + } else { + _lastZeroTimer._indexOrNext = this; + _lastZeroTimer = this; + return false; + } + } else { + _id = _idCount++; + _heap.add(this); + return _firstZeroTimer == null && _heap.isFirst(this); + } + } + + + static void _notifyEventHandler() { + if (_handlingCallbacks) { + // While we are already handling callbacks we will not notify the event + // handler. _handleTimeout will call _notifyEventHandler once all pending + // timers are processed. + return; + } + + if (_firstZeroTimer == null && _heap.isEmpty) { + // No pending timers: Close the receive port and let the event handler + // know. + if (_receivePort != null) { + MojoHandleWatcher.timer(_sendPort, _NO_TIMER); + _shutdownTimerHandler(); + } + } else { + if (_receivePort == null) { + // Create a receive port and register a message handler for the timer + // events. + _createTimerHandler(); + } + if (_firstZeroTimer != null) { + _sendPort.send(null); + } else { + MojoHandleWatcher.timer(_sendPort, _heap.first._wakeupTime); + } + } + } + + static void _handleTimeout(_) { + int currentTime = new DateTime.now().millisecondsSinceEpoch; + // Collect all pending timers. + var timer = _firstZeroTimer; + var nextTimer = _lastZeroTimer; + _firstZeroTimer = null; + _lastZeroTimer = null; + while (_heap.isNotEmpty && _heap.first._wakeupTime <= currentTime) { + var next = _heap.removeFirst(); + if (timer == null) { + nextTimer = next; + timer = next; + } else { + nextTimer._indexOrNext = next; + nextTimer = next; + } + } + + // Trigger all of the pending timers. New timers added as part of the + // callbacks will be enqueued now and notified in the next spin at the + // earliest. + _handlingCallbacks = true; + try { + while (timer != null) { + var next = timer._indexOrNext; + timer._indexOrNext = null; + // One of the timers in the pending_timers list can cancel + // one of the later timers which will set the callback to + // null. + if (timer._callback != null) { + var callback = timer._callback; + if (!timer._repeating) { + // Mark timer as inactive. + timer._callback = null; + } + callback(timer); + // Re-insert repeating timer if not canceled. + if (timer._repeating && timer._callback != null) { + timer._advanceWakeupTime(); + timer._addTimerToHeap(); + } + } + timer = next; + } + } finally { + _handlingCallbacks = false; + _notifyEventHandler(); + } + } + + // Creates a receive port and registers the timer handler on that + // receive port. + static void _createTimerHandler() { + if(_receivePort == null) { + _receivePort = new RawReceivePort(_handleTimeout); + _sendPort = _receivePort.sendPort; + } + } + + static void _shutdownTimerHandler() { + _receivePort.close(); + _receivePort = null; + _sendPort = null; + } +} + +// Provide a closure which will allocate a Timer object to be able to hook +// up the Timer interface in dart:isolate with the implementation here. +_getTimerFactoryClosure() { + return (int milliSeconds, void callback(Timer timer), bool repeating) { + if (repeating) { + return new _Timer.periodic(milliSeconds, callback); + } + return new _Timer(milliSeconds, callback); + }; +} diff --git a/mojo/public/dart/src/timer_queue.dart b/mojo/public/dart/src/timer_queue.dart new file mode 100644 index 0000000..477337c --- /dev/null +++ b/mojo/public/dart/src/timer_queue.dart @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of core; + +class Timeout implements Comparable<Timeout> { + int deadline; // milliseconds since the Unix epoch. + SendPort port; + + Timeout(this.port, this.deadline); + + int compareTo(Timeout other) => other.daedline - deadline; +} + +class TimerQueue { + SplayTreeSet _set; + Timeout _nextTimer; + + TimerQueue() : _set = new SplayTreeSet(); + + void updateTimer(SendPort port, int deadline) { + var removedTimeout = null; + _set.removeWhere((timeout) { + if (timeout.port == port) { + removedTimeout = timeout; + return true; + } + return false; + }); + + if ((removedTimeout == null) && (deadline >= 0)) { + _set.add(new Timeout(port, deadline)); + } else { + if (deadline > 0) { + removedTimeout.deadline = deadline; + _set.add(removedTimeout); + } + } + + if (_set.isNotEmpty) { + _nextTimer = _set.first; + } else { + _nextTimer = null; + } + } + + void removeCurrent() => updateTimer(currentPort, -1); + + bool get hasTimer => _nextTimer != null; + int get currentTimeout => _nextTimer.deadline; + SendPort get currentPort => _nextTimer.port; +} diff --git a/mojo/public/gles2/BUILD.gn b/mojo/public/gles2/BUILD.gn deleted file mode 100644 index 79e7bde..0000000 --- a/mojo/public/gles2/BUILD.gn +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2014 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# In an is_component_build build, everything can link against //mojo/gles2 -# because it is built as a shared library. However, in a static build, -# //mojo/gles2 is linked into an executable (e.g., mojo_shell), and must be -# injected into other shared libraries (i.e., Mojo Apps) that need the mojo -# gles2 API. -# -# For component targets, add //mojo/public/gles2:for_component to your deps -# section. -# -# For shared_library targets (e.g., a Mojo App), add -# //mojo/public/gles2:for_shared_library to your deps - -group("for_shared_library") { - public_configs = [ "//third_party/khronos:khronos_headers" ] - public_deps = [ - "//mojo/public/c/gles2", - ] - - if (is_component_build) { - deps = [ - "//mojo/gles2", - ] - } else { - deps = [ - "//mojo/public/platform/native:gles2_thunks", - ] - } -} - -group("for_component") { - public_configs = [ "//third_party/khronos:khronos_headers" ] - public_deps = [ - "//mojo/public/c/gles2", - ] - - if (is_component_build) { - deps = [ - "//mojo/gles2", - ] - } -} diff --git a/mojo/public/interfaces/application/BUILD.gn b/mojo/public/interfaces/application/BUILD.gn index 8634597..463df55 100644 --- a/mojo/public/interfaces/application/BUILD.gn +++ b/mojo/public/interfaces/application/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/tools/bindings/mojom.gni") +import("../../tools/bindings/mojom.gni") # GYP version: mojo/public/mojo_public.gyp:mojo_application_bindings mojom("application") { diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn index 70aa60e..2b99728 100644 --- a/mojo/public/interfaces/bindings/tests/BUILD.gn +++ b/mojo/public/interfaces/bindings/tests/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/tools/bindings/mojom.gni") +import("../../../tools/bindings/mojom.gni") mojom("test_interfaces") { testonly = true diff --git a/mojo/public/mojo.gni b/mojo/public/mojo.gni index 5cff440f..b310260 100644 --- a/mojo/public/mojo.gni +++ b/mojo/public/mojo.gni @@ -10,3 +10,9 @@ declare_args() { # Whether to build the dart bindings. mojo_use_dart = false } + +# The absolute path to the directory containing the mojo public SDK (i.e., the +# directory containing mojo/public). The build files within the Mojo public +# SDK use this variable to allow themselves to be parameterized by the location +# of the public SDK within a client repo. +mojo_root = get_path_info("../..", "abspath") diff --git a/mojo/public/mojo_application.gni b/mojo/public/mojo_application.gni index 05ec369..d28cb440 100644 --- a/mojo/public/mojo_application.gni +++ b/mojo/public/mojo_application.gni @@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/mojo.gni") +import("mojo.gni") +import("mojo_sdk.gni") # Generate a binary mojo application.The parameters of this template are those # of a shared library. @@ -58,19 +59,28 @@ template("mojo_native_application") { if (defined(invoker.libs)) { libs = invoker.libs } + + if (use_prebuilt_mojo_shell) { + copy_mojo_shell = + rebase_path("mojo/public/tools:copy_mojo_shell", ".", mojo_root) + } + # Copy the prebuilt mojo_shell if using it. if (defined(invoker.datadeps)) { datadeps = invoker.datadeps if (use_prebuilt_mojo_shell) { - datadeps += [ "//mojo/public/tools:copy_mojo_shell" ] + datadeps += [ copy_mojo_shell ] } } else { if (use_prebuilt_mojo_shell) { - datadeps = [ "//mojo/public/tools:copy_mojo_shell" ] + datadeps = [ copy_mojo_shell ] } } + deps = rebase_path([ + "mojo/public/c/system:for_shared_library", + ], ".", mojo_root) if (defined(invoker.deps)) { - deps = invoker.deps + deps += invoker.deps } if (defined(invoker.forward_dependent_configs_from)) { forward_dependent_configs_from = invoker.forward_dependent_configs_from @@ -166,7 +176,7 @@ if (is_android) { } action(target_name) { - script = "//mojo/public/tools/prepend.py" + script = rebase_path("mojo/public/tools/prepend.py", ".", mojo_root) input = zip_action_output inputs = [ input ] diff --git a/mojo/public/mojo_sdk.gni b/mojo/public/mojo_sdk.gni new file mode 100644 index 0000000..eab8037 --- /dev/null +++ b/mojo/public/mojo_sdk.gni @@ -0,0 +1,136 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# The absolute path to the directory containing the mojo public SDK (i.e., the +# directory containing mojo/public). The build files within the Mojo public +# SDK use this variable to allow themselves to be parameterized by the location +# of the public SDK within a client repo. +mojo_root = get_path_info("../..", "abspath") + +# Takes as input a "source_set" that includes dependencies that are relative to +# the parent directory of the Mojo public SDK (given in |mojo_sdk_deps|). +# Generates a source_set that has the mojo_sdk_deps added as ordinary deps +# rebased to the current directory. +# By default, restricts the entries that are given in invoker.deps and +# invoker.public_deps to be only within the same file and on a small set of +# whitelisted external dependencies. This check can be elided by setting +# restrict_external_dependencies to false in the invoker. DO NOT DO THIS in +# //mojo/public. +# +# Example of a mojo_sdk_source_set: +# +# mojo_sdk_source_set("foo") { +# sources = [ +# "foo.h", +# "foo.cc", +# ] +# +# # Same-file deps are specified in the ordinary way. Any external +# dependencies are specified the same way (although in general there should +# be very few of these). +# deps = [ +# ":bar", +# ] +# +# # Mojo SDK deps are specified relative to the containing directory of the +# SDK via mojo_sdk_deps. +# mojo_sdk_deps = [ +# "mojo/public/cpp/bindings", +# "mojo/public/cpp/environment", +# "mojo/public/cpp/system", +# ] +# } +# +template("mojo_sdk_source_set") { + source_set(target_name) { + if (defined(invoker.visibility)) { + visibility = invoker.visibility + } else { + visibility = [ "*" ] + } + if (defined(invoker.mojo_sdk_visibility)) { + foreach(sdk_target, invoker.mojo_sdk_visibility) { + # Check that the SDK target was not mistakenly given as an absolute + # path. + assert(get_path_info(sdk_target, "abspath") != sdk_target) + visibility += [ rebase_path(sdk_target, ".", mojo_root) ] + } + } + + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + + if (defined(invoker.sources)) { + sources = invoker.sources + } + + if (defined(invoker.defines)) { + defines = invoker.defines + } + + public_configs = [ + rebase_path("mojo/public/build/config:mojo_sdk", ".", mojo_root), + ] + if (defined(invoker.public_configs)) { + public_configs += invoker.public_configs + } + + if (defined(invoker.configs)) { + configs += invoker.configs + } + + if (defined(invoker.allow_circular_includes_from)) { + allow_circular_includes_from = invoker.allow_circular_includes_from + } + + if (defined(invoker.public_deps) || (defined(invoker.deps))) { + restrict_external_deps = true + if (defined(invoker.restrict_external_deps)) { + restrict_external_deps = invoker.restrict_external_deps + } + } + + public_deps = [] + if (defined(invoker.public_deps)) { + foreach(dep, invoker.public_deps) { + if (restrict_external_deps) { + # The only deps that are not specified relative to the location of + # the Mojo SDK should be on targets within the same file or on a + # whitelisted set of external dependencies. + assert(get_path_info(dep, "dir") == ".") + } + public_deps += [ dep ] + } + } + if (defined(invoker.mojo_sdk_public_deps)) { + foreach(sdk_dep, invoker.mojo_sdk_public_deps) { + # Check that the SDK dep was not mistakenly given as an absolute path. + assert(get_path_info(sdk_dep, "abspath") != sdk_dep) + public_deps += [ rebase_path(sdk_dep, ".", mojo_root) ] + } + } + + deps = [] + if (defined(invoker.deps)) { + foreach(dep, invoker.deps) { + if (restrict_external_deps) { + # The only deps that are not specified relative to the location of + # the Mojo SDK should be on targets within the same file or on a + # whitelisted set of external dependencies. + dep_dir = get_path_info(dep, "dir") + assert(dep_dir == "." || dep == "//testing/gtest") + } + deps += [ dep ] + } + } + if (defined(invoker.mojo_sdk_deps)) { + foreach(sdk_dep, invoker.mojo_sdk_deps) { + # Check that the SDK dep was not mistakenly given as an absolute path. + assert(get_path_info(sdk_dep, "abspath") != sdk_dep) + deps += [ rebase_path(sdk_dep, ".", mojo_root) ] + } + } + } +} diff --git a/mojo/public/platform/native/BUILD.gn b/mojo/public/platform/native/BUILD.gn index 63a0136..21382a6 100644 --- a/mojo/public/platform/native/BUILD.gn +++ b/mojo/public/platform/native/BUILD.gn @@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("system_thunks") { - visibility = [ - "//mojo/public/c/system:for_component", - "//mojo/public/c/system:for_shared_library", +import("../../mojo_sdk.gni") + +mojo_sdk_source_set("system_thunks") { + mojo_sdk_visibility = [ + "mojo/public/c/system:for_component", + "mojo/public/c/system:for_shared_library", ] sources = [ @@ -13,9 +15,7 @@ source_set("system_thunks") { "system_thunks.cc", ] defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ] - deps = [ - "//mojo/public/c/system", - ] + mojo_sdk_deps = [ "mojo/public/c/system" ] # The GYP target analogous to this one builds this code into a # static library. When building for Android, both the GYP and GN @@ -27,9 +27,8 @@ source_set("system_thunks") { # source_set here, this flag change is not needed. } -# GYP version: mojo/mojo_public_gles2_for_loadable_module.gypi -source_set("gles2_thunks") { - visibility = [ "//mojo/public/gles2:for_shared_library" ] +mojo_sdk_source_set("gles2_thunks") { + mojo_sdk_visibility = [ "mojo/public/gles2:for_shared_library" ] sources = [ "gles2_thunks.cc", @@ -44,12 +43,12 @@ source_set("gles2_thunks") { defines = [ "MOJO_GLES2_IMPLEMENTATION" ] - configs += [ "//third_party/khronos:khronos_headers" ] + configs = [ "//third_party/khronos:khronos_headers" ] - deps = [ - "//mojo/public/c/gles2", - "//mojo/public/c/environment", - "//mojo/public/c/system", + mojo_sdk_deps = [ + "mojo/public/c/gles2:headers", + "mojo/public/c/environment", + "mojo/public/c/system", ] if (is_mac) { diff --git a/mojo/public/python/BUILD.gn b/mojo/public/python/BUILD.gn index 66f132f..70402e7 100644 --- a/mojo/public/python/BUILD.gn +++ b/mojo/public/python/BUILD.gn @@ -9,6 +9,7 @@ group("python") { ":base", ":bindings", ":system", + ":system_impl", ] } @@ -17,21 +18,38 @@ python_binary_module("system") { python_base_module = "mojo" sources = [ "mojo/c_core.pxd", - "mojo/c_environment.pxd", "mojo/system.pyx", ] + deps = [ + ":base", + "../c/environment", + "../c/system:for_shared_library", + "../cpp/environment:standalone", + "../cpp/system", + "../cpp/utility", + "../cpp/bindings:callback", + ] +} + +python_binary_module("system_impl") { + python_base_module = "mojo" + sources = [ + "mojo/c_core.pxd", + "mojo/c_environment.pxd", + "mojo/system_impl.pyx", + ] additional_sources = [ "src/python_system_helper.cc", "src/python_system_helper.h", ] deps = [ - "//mojo/public/c/environment", - "//mojo/public/c/system:for_shared_library", - "//mojo/public/cpp/environment:standalone", - "//mojo/public/cpp/system", - "//mojo/public/cpp/utility", - "//mojo/public/cpp/bindings:callback", ":base", + "../c/environment", + "../c/system:for_shared_library", + "../cpp/environment:standalone", + "../cpp/system", + "../cpp/utility", + "../cpp/bindings:callback", ] } diff --git a/mojo/public/python/mojo/system.pyx b/mojo/public/python/mojo/system.pyx index f0a814a..35b8093 100644 --- a/mojo/public/python/mojo/system.pyx +++ b/mojo/public/python/mojo/system.pyx @@ -5,7 +5,6 @@ # distutils language = c++ cimport c_core -cimport c_environment from cpython.buffer cimport PyBUF_CONTIG @@ -21,6 +20,8 @@ from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t, uintptr_t import ctypes import threading +import mojo.system_impl + def SetSystemThunks(system_thunks_as_object): """Bind the basic Mojo Core functions. @@ -29,6 +30,7 @@ def SetSystemThunks(system_thunks_as_object): cdef const c_core.MojoSystemThunks* system_thunks = ( <const c_core.MojoSystemThunks*><uintptr_t>system_thunks_as_object) c_core.MojoSetSystemThunks(system_thunks) + mojo.system_impl.SetSystemThunks(system_thunks_as_object) HANDLE_INVALID = c_core.MOJO_HANDLE_INVALID RESULT_OK = c_core.MOJO_RESULT_OK @@ -347,7 +349,7 @@ cdef class Handle(object): cdef c_core.MojoHandle handle = self._mojo_handle cdef c_core.MojoHandleSignals csignals = signals cdef c_core.MojoDeadline cdeadline = deadline - cdef c_environment.MojoAsyncWaitID wait_id = _ASYNC_WAITER.AsyncWait( + wait_id = _ASYNC_WAITER.AsyncWait( handle, csignals, cdeadline, @@ -734,46 +736,40 @@ class DuplicateSharedBufferOptions(object): _RUN_LOOPS = threading.local() -cdef class RunLoop(object): +class RunLoop(object): """RunLoop to use when using asynchronous operations on handles.""" - cdef c_environment.CRunLoop* c_run_loop - def __init__(self): - assert not <uintptr_t>(c_environment.CRunLoopCurrent()) - self.c_run_loop = new c_environment.CRunLoop() + self.__run_loop = mojo.system_impl.RunLoop() _RUN_LOOPS.loop = id(self) - def __dealloc__(self): + def __del__(self): del _RUN_LOOPS.loop - del self.c_run_loop - - @staticmethod - def Current(): - if hasattr(_RUN_LOOPS, 'loop'): - return ctypes.cast(_RUN_LOOPS.loop, ctypes.py_object).value - return None def Run(self): """Run the runloop until Quit is called.""" - self.c_run_loop.Run() + return self.__run_loop.Run() def RunUntilIdle(self): """Run the runloop until Quit is called or no operation is waiting.""" - self.c_run_loop.RunUntilIdle() + return self.__run_loop.RunUntilIdle() def Quit(self): """Quit the runloop.""" - self.c_run_loop.Quit() + return self.__run_loop.Quit() def PostDelayedTask(self, runnable, delay=0): """ Post a task on the runloop. This must be called from the thread owning the runloop. """ - cdef c_environment.CClosure closure = c_environment.BuildClosure(runnable) - self.c_run_loop.PostDelayedTask(closure, delay) + return self.__run_loop.PostDelayedTask(runnable, delay) + + @staticmethod + def Current(): + if hasattr(_RUN_LOOPS, 'loop'): + return ctypes.cast(_RUN_LOOPS.loop, ctypes.py_object).value + return None -cdef c_environment.CEnvironment* _ENVIRONMENT = new c_environment.CEnvironment() -cdef c_environment.PythonAsyncWaiter* _ASYNC_WAITER = new c_environment.PythonAsyncWaiter() +_ASYNC_WAITER = mojo.system_impl.ASYNC_WAITER diff --git a/mojo/public/python/mojo/system_impl.pyx b/mojo/public/python/mojo/system_impl.pyx new file mode 100644 index 0000000..6e79c51 --- /dev/null +++ b/mojo/public/python/mojo/system_impl.pyx @@ -0,0 +1,75 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# distutils language = c++ + +cimport c_core +cimport c_environment + + +from libc.stdint cimport uintptr_t + +def SetSystemThunks(system_thunks_as_object): + """Bind the basic Mojo Core functions. + """ + cdef const c_core.MojoSystemThunks* system_thunks = ( + <const c_core.MojoSystemThunks*><uintptr_t>system_thunks_as_object) + c_core.MojoSetSystemThunks(system_thunks) + + +cdef class RunLoop(object): + """RunLoop to use when using asynchronous operations on handles.""" + + cdef c_environment.CRunLoop* c_run_loop + + def __init__(self): + assert not <uintptr_t>(c_environment.CRunLoopCurrent()) + self.c_run_loop = new c_environment.CRunLoop() + + def __dealloc__(self): + del self.c_run_loop + + def Run(self): + """Run the runloop until Quit is called.""" + self.c_run_loop.Run() + + def RunUntilIdle(self): + """Run the runloop until Quit is called or no operation is waiting.""" + self.c_run_loop.RunUntilIdle() + + def Quit(self): + """Quit the runloop.""" + self.c_run_loop.Quit() + + def PostDelayedTask(self, runnable, delay=0): + """ + Post a task on the runloop. This must be called from the thread owning the + runloop. + """ + cdef c_environment.CClosure closure = c_environment.BuildClosure(runnable) + self.c_run_loop.PostDelayedTask(closure, delay) + + +# We use a wrapping class to be able to call the C++ class PythonAsyncWaiter +# across module boundaries. +cdef class _AsyncWaiter(object): + cdef c_environment.CEnvironment* _cenvironment + cdef c_environment.PythonAsyncWaiter* _c_async_waiter + + def __init__(self): + self._cenvironment = new c_environment.CEnvironment() + self._c_async_waiter = new c_environment.PythonAsyncWaiter() + + def __dealloc__(self): + del self._c_async_waiter + del self._cenvironment + + def AsyncWait(self, handle, signals, deadline, callback): + return self._c_async_waiter.AsyncWait(handle, signals, deadline, callback) + + def CancelWait(self, wait_id): + self._c_async_waiter.CancelWait(wait_id) + + +ASYNC_WAITER = _AsyncWaiter() diff --git a/mojo/public/sky/BUILD.gn b/mojo/public/sky/BUILD.gn index c3b5366..a24dde4 100644 --- a/mojo/public/sky/BUILD.gn +++ b/mojo/public/sky/BUILD.gn @@ -5,13 +5,13 @@ action_foreach("sky") { script = "convert_amd_modules_to_sky.py" sources = [ - "//mojo/public/js/buffer.js", - "//mojo/public/js/codec.js", - "//mojo/public/js/connection.js", - "//mojo/public/js/connector.js", - "//mojo/public/js/router.js", - "//mojo/public/js/unicode.js", - "//mojo/public/js/validator.js", + "../js/buffer.js", + "../js/codec.js", + "../js/connection.js", + "../js/connector.js", + "../js/router.js", + "../js/unicode.js", + "../js/validator.js", ] outputs = [ "$target_gen_dir/{{source_name_part}}.sky", diff --git a/mojo/public/tools/BUILD.gn b/mojo/public/tools/BUILD.gn index 5fb9785..12cca6d 100644 --- a/mojo/public/tools/BUILD.gn +++ b/mojo/public/tools/BUILD.gn @@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//mojo/public/mojo.gni") +import("../mojo.gni") if (use_prebuilt_mojo_shell) { copy("copy_mojo_shell") { diff --git a/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl b/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl index 17e1b78..3512480 100644 --- a/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl +++ b/mojo/public/tools/bindings/generators/dart_templates/module.lib.tmpl @@ -5,9 +5,9 @@ library {{module.name}}; import 'dart:async'; +import 'dart:mojo_bindings' as bindings; +import 'dart:mojo_core' as core; -import 'package:mojo/public/dart/core.dart' as core; -import 'package:mojo/public/dart/bindings.dart' as bindings; {%- for import in imports %} import 'package:{{import.module.path}}.dart' as {{import.unique_name}}; {%- endfor %} diff --git a/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl b/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl index 632a99c..88f2794 100644 --- a/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl +++ b/mojo/public/tools/bindings/generators/dart_templates/struct_definition.tmpl @@ -1,6 +1,6 @@ {#--- Begin #} -class {{struct.name}} implements bindings.MojoType<{{struct.name}}> { +class {{struct.name}} { {#--- Enums #} {%- from "enum_definition.tmpl" import enum_def %} {% for enum in struct.enums %} diff --git a/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/mojo/public/tools/bindings/generators/mojom_dart_generator.py index 6c1fed3..8021c8b 100644 --- a/mojo/public/tools/bindings/generators/mojom_dart_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_dart_generator.py @@ -45,16 +45,16 @@ _kind_to_dart_decl_type = { mojom.INT32: "int", mojom.UINT32: "int", mojom.FLOAT: "double", - mojom.HANDLE: "RawMojoHandle", - mojom.DCPIPE: "RawMojoHandle", - mojom.DPPIPE: "RawMojoHandle", - mojom.MSGPIPE: "RawMojoHandle", - mojom.SHAREDBUFFER: "RawMojoHandle", - mojom.NULLABLE_HANDLE: "RawMojoHandle", - mojom.NULLABLE_DCPIPE: "RawMojoHandle", - mojom.NULLABLE_DPPIPE: "RawMojoHandle", - mojom.NULLABLE_MSGPIPE: "RawMojoHandle", - mojom.NULLABLE_SHAREDBUFFER: "RawMojoHandle", + mojom.HANDLE: "core.RawMojoHandle", + mojom.DCPIPE: "core.RawMojoHandle", + mojom.DPPIPE: "core.RawMojoHandle", + mojom.MSGPIPE: "core.RawMojoHandle", + mojom.SHAREDBUFFER: "core.RawMojoHandle", + mojom.NULLABLE_HANDLE: "core.RawMojoHandle", + mojom.NULLABLE_DCPIPE: "core.RawMojoHandle", + mojom.NULLABLE_DPPIPE: "core.RawMojoHandle", + mojom.NULLABLE_MSGPIPE: "core.RawMojoHandle", + mojom.NULLABLE_SHAREDBUFFER: "core.RawMojoHandle", mojom.INT64: "int", mojom.UINT64: "int", mojom.DOUBLE: "double", diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index 69f4b76..d7c83d6 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni @@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("../../mojo_sdk.gni") + # Generate C++ and JavaScript source files from mojom files. The output files # will go under the generated file directory tree with the same path as each # input file. @@ -24,7 +26,8 @@ template("mojom") { assert(defined(invoker.sources), "\"sources\" must be defined for the $target_name template.") - generator_root = "//mojo/public/tools/bindings" + generator_root = + rebase_path("mojo/public/tools/bindings", ".", mojo_root) generator_script = "$generator_root/mojom_bindings_generator.py" generator_sources = [ generator_script, @@ -132,6 +135,7 @@ template("mojom") { "--use_chromium_bundled_pylibs", "-d", rebase_path("//", root_build_dir), "-I", rebase_path("//", root_build_dir), + "-I", rebase_path(mojo_root, root_build_dir), "-o", rebase_path(root_gen_dir), ] } @@ -145,16 +149,24 @@ template("mojom") { } sources = process_file_template(invoker.sources, generator_cpp_outputs) data = process_file_template(invoker.sources, generator_js_outputs) + + public_configs = rebase_path([ + "mojo/public/build/config:mojo_sdk", + ], ".", mojo_root) + + public_deps = rebase_path([ + "mojo/public/cpp/bindings", + ], ".", mojo_root) + if (defined(invoker.public_deps)) { + public_deps += invoker.public_deps + } + deps = [ ":$generator_target_name", - "//mojo/public/cpp/bindings", ] if (defined(invoker.deps)) { deps += invoker.deps } - if (defined(invoker.public_deps)) { - public_deps = invoker.public_deps - } } all_deps = [] @@ -184,10 +196,10 @@ template("mojom") { java_target_name = target_name + "_java" android_library(java_target_name) { - deps = [ - "//mojo/public/java:bindings", - "//mojo/public/java:system", - ] + deps = rebase_path([ + "mojo/public/java:bindings", + "mojo/public/java:system", + ], ".", mojo_root) foreach(d, all_deps) { # Resolve the name, so that a target //mojo/something becomes diff --git a/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi b/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi index 512e22f..52b2452 100644 --- a/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi +++ b/mojo/public/tools/bindings/mojom_bindings_generator_explicit.gypi @@ -45,6 +45,10 @@ 'message': 'Generating Mojo bindings from <@(mojom_files)', } ], + # Prevent the generated sources from being injected into the "all" target by + # preventing the code generator from being directly depended on by the "all" + # target. + 'suppress_wildcard': '1', 'direct_dependent_settings': { # A target directly depending on this action will compile the generated # sources. diff --git a/mojo/services/public/cpp/network/BUILD.gn b/mojo/services/public/cpp/network/BUILD.gn index f8db162..5f6ab06 100644 --- a/mojo/services/public/cpp/network/BUILD.gn +++ b/mojo/services/public/cpp/network/BUILD.gn @@ -17,7 +17,7 @@ source_set("network") { "//mojo/application", "//mojo/common", "//mojo/environment:chromium", - "//mojo/public/c/system:for_component", + "//mojo/public/c/system", "//mojo/public/cpp/system", "//mojo/services/public/interfaces/network", ] diff --git a/mojo/services/public/cpp/view_manager/BUILD.gn b/mojo/services/public/cpp/view_manager/BUILD.gn index dffa4f1..90193d4 100644 --- a/mojo/services/public/cpp/view_manager/BUILD.gn +++ b/mojo/services/public/cpp/view_manager/BUILD.gn @@ -28,7 +28,7 @@ source_set("view_manager") { ] deps = [ "//base", - "//mojo/public/c/gles2", + "//mojo/public/c/gles2:headers", "//mojo/public/cpp/application", "//mojo/public/cpp/bindings:bindings", "//mojo/public/interfaces/application", diff --git a/mojo/services/public/cpp/view_manager/lib/view.cc b/mojo/services/public/cpp/view_manager/lib/view.cc index 1ed7a62..0880958 100644 --- a/mojo/services/public/cpp/view_manager/lib/view.cc +++ b/mojo/services/public/cpp/view_manager/lib/view.cc @@ -4,10 +4,13 @@ #include "mojo/services/public/cpp/view_manager/view.h" +#include <set> + #include "mojo/public/cpp/application/service_provider_impl.h" #include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h" #include "mojo/services/public/cpp/view_manager/lib/view_private.h" #include "mojo/services/public/cpp/view_manager/view_observer.h" +#include "mojo/services/public/cpp/view_manager/view_tracker.h" namespace mojo { @@ -225,7 +228,7 @@ void View::SetVisible(bool value) { static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value); FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this)); visible_ = value; - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(this)); + NotifyViewVisibilityChanged(this); } void View::SetSharedProperty(const std::string& name, @@ -503,4 +506,52 @@ void View::LocalSetDrawn(bool value) { FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanged(this)); } +void View::NotifyViewVisibilityChanged(View* target) { + if (!NotifyViewVisibilityChangedDown(target)) { + return; // |this| has been deleted. + } + NotifyViewVisibilityChangedUp(target); +} + +bool View::NotifyViewVisibilityChangedAtReceiver(View* target) { + // |this| may be deleted during a call to OnViewVisibilityChanged() on one + // of the observers. We create an local observer for that. In that case we + // exit without further access to any members. + ViewTracker tracker; + tracker.Add(this); + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(target)); + return tracker.Contains(this); +} + +bool View::NotifyViewVisibilityChangedDown(View* target) { + if (!NotifyViewVisibilityChangedAtReceiver(target)) + return false; // |this| was deleted. + std::set<const View*> child_already_processed; + bool child_destroyed = false; + do { + child_destroyed = false; + for (View::Children::const_iterator it = children_.begin(); + it != children_.end(); ++it) { + if (!child_already_processed.insert(*it).second) + continue; + if (!(*it)->NotifyViewVisibilityChangedDown(target)) { + // |*it| was deleted, |it| is invalid and |children_| has changed. We + // exit the current for-loop and enter a new one. + child_destroyed = true; + break; + } + } + } while (child_destroyed); + return true; +} + +void View::NotifyViewVisibilityChangedUp(View* target) { + // Start with the parent as we already notified |this| + // in NotifyViewVisibilityChangedDown. + for (View* view = parent(); view; view = view->parent()) { + bool ret = view->NotifyViewVisibilityChangedAtReceiver(target); + DCHECK(ret); + } +} + } // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/tests/BUILD.gn b/mojo/services/public/cpp/view_manager/tests/BUILD.gn index d04bb34..c4a117a 100644 --- a/mojo/services/public/cpp/view_manager/tests/BUILD.gn +++ b/mojo/services/public/cpp/view_manager/tests/BUILD.gn @@ -13,18 +13,16 @@ test("mojo_view_manager_lib_unittests") { deps = [ "//base", "//base/test:test_support", - "//testing/gtest", - "//ui/gfx", - "//ui/gfx:test_support", "//mojo/application_manager", "//mojo/converters/geometry", "//mojo/environment:chromium", "//mojo/public/cpp/application", "//mojo/services/public/cpp/geometry", + "//mojo/services/public/cpp/view_manager", "//mojo/services/public/interfaces/geometry", - "//mojo/shell:test_support", "//mojo/services/public/interfaces/view_manager", - "//mojo/services/public/cpp/view_manager", + "//shell:test_support", + "//testing/gtest", ] if (use_aura) { deps += [ "//mojo/services/public/cpp/view_manager/lib:run_unittests" ] diff --git a/mojo/services/public/cpp/view_manager/tests/DEPS b/mojo/services/public/cpp/view_manager/tests/DEPS index 2ecf3db..24dd6d3 100644 --- a/mojo/services/public/cpp/view_manager/tests/DEPS +++ b/mojo/services/public/cpp/view_manager/tests/DEPS @@ -1,3 +1,4 @@ include_rules = [ "+mojo/application_manager", + "+shell/shell_test_helper.h", ] diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc index 540b145..6b2294e 100644 --- a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc +++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc @@ -20,7 +20,7 @@ #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" #include "mojo/services/public/cpp/view_manager/view_observer.h" -#include "mojo/shell/shell_test_helper.h" +#include "shell/shell_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" namespace mojo { diff --git a/mojo/services/public/cpp/view_manager/tests/view_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc index b0bd08b..96b2d5c 100644 --- a/mojo/services/public/cpp/view_manager/tests/view_unittest.cc +++ b/mojo/services/public/cpp/view_manager/tests/view_unittest.cc @@ -695,6 +695,46 @@ TEST_F(ViewObserverTest, SetVisible) { } } +TEST_F(ViewObserverTest, SetVisibleParent) { + TestView parent; + ViewPrivate(&parent).set_id(1); + TestView child; + ViewPrivate(&child).set_id(2); + parent.AddChild(&child); + EXPECT_TRUE(parent.visible()); + EXPECT_TRUE(child.visible()); + { + // Change visibility from true to false and make sure we get notifications + // on the parent. + VisibilityChangeObserver observer(&parent); + child.SetVisible(false); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ("view=0,2 phase=changed visibility=false", changes[0]); + } +} + +TEST_F(ViewObserverTest, SetVisibleChild) { + TestView parent; + ViewPrivate(&parent).set_id(1); + TestView child; + ViewPrivate(&child).set_id(2); + parent.AddChild(&child); + EXPECT_TRUE(parent.visible()); + EXPECT_TRUE(child.visible()); + { + // Change visibility from true to false and make sure we get notifications + // on the child. + VisibilityChangeObserver observer(&child); + parent.SetVisible(false); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[0]); + } +} + namespace { class SharedPropertyChangeObserver : public ViewObserver { diff --git a/mojo/services/public/cpp/view_manager/view.h b/mojo/services/public/cpp/view_manager/view.h index 56d930f..c585dd5 100644 --- a/mojo/services/public/cpp/view_manager/view.h +++ b/mojo/services/public/cpp/view_manager/view.h @@ -154,6 +154,18 @@ class View { void LocalSetBounds(const Rect& old_bounds, const Rect& new_bounds); void LocalSetDrawn(bool drawn); + // Methods implementing visibility change notifications. See ViewObserver + // for more details. + void NotifyViewVisibilityChanged(View* target); + // Notifies this view's observers. Returns false if |this| was deleted during + // the call (by an observer), otherwise true. + bool NotifyViewVisibilityChangedAtReceiver(View* target); + // Notifies this view and its child hierarchy. Returns false if |this| was + // deleted during the call (by an observer), otherwise true. + bool NotifyViewVisibilityChangedDown(View* target); + // Notifies this view and its parent hierarchy. + void NotifyViewVisibilityChangedUp(View* target); + ViewManager* manager_; Id id_; View* parent_; diff --git a/mojo/services/public/interfaces/gpu/gpu_capabilities.mojom b/mojo/services/public/interfaces/gpu/gpu_capabilities.mojom index ef28389..2450139 100644 --- a/mojo/services/public/interfaces/gpu/gpu_capabilities.mojom +++ b/mojo/services/public/interfaces/gpu/gpu_capabilities.mojom @@ -51,5 +51,4 @@ struct GpuCapabilities { bool future_sync_points; bool blend_equation_advanced; bool blend_equation_advanced_coherent; - bool texture_rg; }; diff --git a/mojo/services/public/interfaces/view_manager/BUILD.gn b/mojo/services/public/interfaces/view_manager/BUILD.gn index 97374e5..10e7b43 100644 --- a/mojo/services/public/interfaces/view_manager/BUILD.gn +++ b/mojo/services/public/interfaces/view_manager/BUILD.gn @@ -6,6 +6,7 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("view_manager") { sources = [ + "animations.mojom", "view_manager.mojom", "view_manager_constants.mojom", ] diff --git a/mojo/services/public/interfaces/view_manager/animations.mojom b/mojo/services/public/interfaces/view_manager/animations.mojom new file mode 100644 index 0000000..fad22ea --- /dev/null +++ b/mojo/services/public/interfaces/view_manager/animations.mojom @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module mojo; + +import "mojo/services/public/interfaces/geometry/geometry.mojom"; + +enum AnimationTweenType { + LINEAR, + EASE_IN, + EASE_OUT, + EASE_IN_OUT, +}; + +enum AnimationProperty { + // Used for pausing. + NONE, + OPACITY, + TRANSFORM, +}; + +struct AnimationValue { + float float_value; + Transform transform; +}; + +// Identifies how a particular property should be animated between a start and +// target value. +struct AnimationElement { + AnimationProperty property; + + // Duration is in microseconds. + int64 duration; + + AnimationTweenType tween_type; + + // If not specified the start value is taken from either the current value + // (for the first element) or the target_value of the previous element. + AnimationValue? start_value; + + // target_value may be null when property is NONE. + AnimationValue? target_value; +}; + +// An AnimationSequence consists of a number of AnimationElements to animate. +// Each element is animated serially. +struct AnimationSequence { + // Number of times to run the sequence. Value of 0 means run until + // explicitly stopped. + uint32 cycle_count; + + array<AnimationElement> elements; +}; + +// AnimationGroup identifies a view and a set of AnimationSequences to apply +// to the view. Each sequence is run in parallel. +struct AnimationGroup { + uint32 view_id; + array<AnimationSequence> sequences; +}; diff --git a/mojo/services/public/js/application.js b/mojo/services/public/js/application.js new file mode 100644 index 0000000..5893424 --- /dev/null +++ b/mojo/services/public/js/application.js @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +define("mojo/services/public/js/application", [ + "services/js/app_bridge", + "mojo/services/public/js/service_provider", + "mojo/services/public/js/shell", +], function(appBridgeModule, spModule, shellModule) { + + class Application { + constructor(appShell, url) { + this.shell = new shellModule.Shell(appShell); + this.url = url; + this.serviceProviders = []; + } + + initialize(args) { + } + + acceptConnection_(url, spHandle) { + var serviceProvider = new spModule.ServiceProvider(spHandle); + this.serviceProviders.push(serviceProvider); + this.acceptConnection(url, serviceProvider); + } + + acceptConnection(url, serviceProvider) { + } + + quit() { + this.shell.close(); + this.serviceProviders.forEach(function(sp) { + sp.close(); + }); + appBridgeModule.quit(); + } + } + + var exports = {}; + exports.Application = Application; + return exports; +}); diff --git a/mojo/services/public/js/mojo.js b/mojo/services/public/js/mojo.js deleted file mode 100644 index f607833..0000000 --- a/mojo/services/public/js/mojo.js +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -define("mojo/services/public/js/mojo", [ - "mojo/public/interfaces/application/service_provider.mojom", - "mojo/public/js/connection", - "mojo/public/js/core", - "services/js/bridge", -], function(service, connection, core, bridge) { - - function Shell() { - this.applications_ = new Map(); - } - - Shell.prototype.connectToApplication = function(url) { - var application = this.applications_.get(url); - if (application) - return application; - application = new ServiceProvider(bridge.connectToApplication(url)); - this.applications_.set(url, application); - return application; - }; - - Shell.prototype.connectToService = function (url, service, client) { - return this.connectToApplication(url).connectToService(service, client); - }; - - Shell.prototype.close = function() { - shell().applications_.forEach(function(application, url) { - application.close(); - }); - shell().applications_.clear(); - }; - - var shellValue = null; - - function shell() { - if (!shellValue) - shellValue = new Shell(); - return shellValue; - } - - var requestorValue = null; - - function requestor() { - if (!requestorValue) { - var handle = bridge.requestorMessagePipeHandle(); - requestorValue = handle && new ServiceProvider(handle); - } - return requestorValue; - } - - function connectToServiceImpl(serviceName, serviceHandle) { - var provider = this.providers_.get(serviceName); - if (!provider) { - this.pendingRequests_.set(serviceName, serviceHandle); - return; - } - - var serviceConnection = new connection.Connection( - serviceHandle, - provider.service.stubClass, - provider.service.client && provider.service.client.proxyClass); - - serviceConnection.local.connection$ = serviceConnection; - serviceConnection.local.delegate$ = - new provider.factory(serviceConnection.remote); - - provider.connections.push(serviceConnection); - } - - function ServiceProvider(messagePipeHandle) { - // TODO(hansmuller): if messagePipeHandle is null, throw an exception. - this.connections_ = new Map(); - this.providers_ = new Map(); - this.pendingRequests_ = new Map(); - this.connection_ = null; - this.handle_ = messagePipeHandle; - this.connection_ = new connection.Connection( - this.handle_, - service.ServiceProvider.client.stubClass, - service.ServiceProvider.proxyClass); - this.connection_.local.delegate$ = { - connectToService: connectToServiceImpl.bind(this) - }; - } - - ServiceProvider.prototype.provideService = function(service, factory) { - // TODO(hansmuller): if !factory, remove provider and close its connections. - // TODO(hansmuller): if this.connection_ is null, throw an error. - var provider = { - service: service, - factory: factory, - connections: [], - }; - this.providers_.set(service.name, provider); - - if (this.pendingRequests_.has(service.name)) { - connectToServiceImpl(service.name, pendingRequests_.get(service.name)); - pendingRequests_.delete(service.name); - } - - return this; - }; - - ServiceProvider.prototype.connectToService = function(service, client) { - // TODO(hansmuler): if service.name isn't defined, throw an error. - // TODO(hansmuller): if this.connection_ is null, throw an error. - var serviceConnection = this.connections_.get(service.name); - if (serviceConnection) - return serviceConnection.remote; - - var pipe = core.createMessagePipe(); - this.connection_.remote.connectToService(service.name, pipe.handle1); - var clientClass = client && service.client.stubClass; - var serviceConnection = - new connection.Connection(pipe.handle0, clientClass, service.proxyClass); - if (serviceConnection.local) - serviceConnection.local.delegate$ = client; - - this.connections_.set(service.name, serviceConnection); - return serviceConnection.remote; - }; - - ServiceProvider.prototype.close = function() { - if (!this.connection_) - return; - - try { - // Outgoing connections - this.connections_.forEach(function(connection, serviceName) { - connection.close(); - }); - // Incoming connections - this.providers_.forEach(function(provider, serviceName) { - provider.connections.forEach(function(connection) { - connection.close(); - }); - }); - this.connection_.close(); - } finally { - this.connections_ = null; - this.providers_ = null; - this.pendingRequests_ = null; - this.connection_ = null; - this.handle_ = null; - - shell().applications_.forEach(function(application, url) { - if (application === this) - shell().applications_.delete(url); - }, this); - } - }; - - function quit() { - if (requestorValue) - requestor().close(); - if (shellValue) - shell().close(); - bridge.quit(); - } - - var exports = {}; - exports.requestor = requestor; - exports.shell = shell; - exports.quit = quit; - return exports; -}); diff --git a/mojo/services/public/js/service_provider.js b/mojo/services/public/js/service_provider.js new file mode 100644 index 0000000..7c82775 --- /dev/null +++ b/mojo/services/public/js/service_provider.js @@ -0,0 +1,118 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +define("mojo/services/public/js/service_provider", [ + "mojo/public/interfaces/application/service_provider.mojom", + "mojo/public/js/connection", + "mojo/public/js/core", +], function(spInterfaceModule, connectionModule, coreModule) { + + function connectToServiceImpl(serviceName, serviceHandle) { + var provider = this.providers_.get(serviceName); + if (!provider) { + this.pendingRequests_.set(serviceName, serviceHandle); + return; + } + + var serviceConnection = new connectionModule.Connection( + serviceHandle, + provider.service.stubClass, + provider.service.client && provider.service.client.proxyClass); + + serviceConnection.local.connection$ = serviceConnection; + serviceConnection.local.delegate$ = + new provider.factory(serviceConnection.remote); + + provider.connections.push(serviceConnection); + } + + class ServiceProvider { + constructor(service) { + this.connections_ = new Map(); + this.providers_ = new Map(); + this.pendingRequests_ = new Map(); + this.connection_ = null; + + if (service instanceof spInterfaceModule.ServiceProvider.proxyClass) { + this.connection_ = service.getConnection$(); + } else { + this.handle_ = service; // service is-a MessagePipe handle + this.connection_ = new connectionModule.Connection( + this.handle_, + spInterfaceModule.ServiceProvider.client.stubClass, + spInterfaceModule.ServiceProvider.proxyClass); + }; + this.connection_.local.delegate$ = { + connectToService: connectToServiceImpl.bind(this) + } + } + + provideService(service, factory) { + // TODO(hansmuller): if !factory, remove provider and close its + // connections. + // TODO(hansmuller): if this.connection_ is null, throw an error. + var provider = { + service: service, + factory: factory, + connections: [], + }; + this.providers_.set(service.name, provider); + + if (this.pendingRequests_.has(service.name)) { + connectToServiceImpl(service.name, pendingRequests_.get(service.name)); + pendingRequests_.delete(service.name); + } + + return this; + } + + connectToService(service, client) { + // TODO(hansmuler): if service.name isn't defined, throw an error. + // TODO(hansmuller): if this.connection_ is null, throw an error. + var serviceConnection = this.connections_.get(service.name); + if (serviceConnection) + return serviceConnection.remote; + + var pipe = coreModule.createMessagePipe(); + this.connection_.remote.connectToService(service.name, pipe.handle1); + var clientClass = client && service.client.stubClass; + var serviceConnection = new connectionModule.Connection( + pipe.handle0, clientClass, service.proxyClass); + if (serviceConnection.local) + serviceConnection.local.delegate$ = client; + + this.connections_.set(service.name, serviceConnection); + return serviceConnection.remote; + }; + + close() { + if (!this.connection_) + return; + + try { + // Outgoing connections + this.connections_.forEach(function(connection, serviceName) { + connection.close(); + }); + // Incoming connections + this.providers_.forEach(function(provider, serviceName) { + provider.connections.forEach(function(connection) { + connection.close(); + }); + }); + this.connection_.close(); + } finally { + this.connections_ = null; + this.providers_ = null; + this.pendingRequests_ = null; + this.connection_ = null; + this.handle_ = null; + } + } + } + + var exports = {}; + exports.ServiceProvider = ServiceProvider; + return exports; +}); diff --git a/mojo/services/public/js/shell.js b/mojo/services/public/js/shell.js new file mode 100644 index 0000000..82d5292 --- /dev/null +++ b/mojo/services/public/js/shell.js @@ -0,0 +1,43 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +define("mojo/services/public/js/shell", [ + "mojo/public/interfaces/application/service_provider.mojom", + "mojo/services/public/js/service_provider", +], function(spInterfaceModule, spModule) { + + class Shell { + constructor(appShell) { + this.appShell_ = appShell; + this.applications_ = new Map(); + } + + connectToApplication(url) { + var application = this.applications_.get(url); + if (application) + return application; + + var proxy = new spInterfaceModule.ServiceProvider.proxyClass; + this.appShell_.connectToApplication(url, proxy); + application = new spModule.ServiceProvider(proxy); + this.applications_.set(url, application); + return application; + } + + connectToService(url, service, client) { + return this.connectToApplication(url).connectToService(service, client); + }; + + close() { + this.applications_.forEach(function(application, url) { + application.close(); + }); + this.applications_.clear(); + } + } + + var exports = {}; + exports.Shell = Shell; + return exports; +}); |