diff options
author | sky <sky@chromium.org> | 2015-08-06 18:06:18 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-07 01:07:34 +0000 |
commit | add030b55dee834423004bde2a0d92afd8a7be7e (patch) | |
tree | d7e3af2db33ba8e700d15a80f40a003336ba9523 /mojo/common | |
parent | 1efe8793da85ee6e25185175047c077adfe8e55c (diff) | |
download | chromium_src-add030b55dee834423004bde2a0d92afd8a7be7e.zip chromium_src-add030b55dee834423004bde2a0d92afd8a7be7e.tar.gz chromium_src-add030b55dee834423004bde2a0d92afd8a7be7e.tar.bz2 |
Straightens outs DEPS in mojo/common
Prior to this change //mojo/environment depended upon //mojo/common. //mojo/common's deps are wrong and it needs to be depend upon various things in //third_party/mojo/src/mojo... When these DEPS are added link errors result because Environment and and a couple of other things need to be defined. These are defined in //mojo/environment. But //mojo/environment can't be a dep of //mojo/common, else we get a cycle.
To straighten this out I've moved the files //mojo/environment needs from //mojo/common to //mojo/message_pump. //mojo/environment no longer depends upon //mojo/common, only //mojo/message_pump. //mojo/common can then depend upon //mojo/environment and we no longer have the cycle. Yay!
BUG=none
TEST=none
Committed: https://crrev.com/a11b4d76a27816fe025af647825becac5f633c34
Cr-Commit-Position: refs/heads/master@{#341979}
Review URL: https://codereview.chromium.org/1262173005
Cr-Commit-Position: refs/heads/master@{#342252}
Diffstat (limited to 'mojo/common')
-rw-r--r-- | mojo/common/BUILD.gn | 18 | ||||
-rw-r--r-- | mojo/common/handle_watcher.cc | 475 | ||||
-rw-r--r-- | mojo/common/handle_watcher.h | 64 | ||||
-rw-r--r-- | mojo/common/handle_watcher_unittest.cc | 483 | ||||
-rw-r--r-- | mojo/common/message_pump_mojo.cc | 295 | ||||
-rw-r--r-- | mojo/common/message_pump_mojo.h | 136 | ||||
-rw-r--r-- | mojo/common/message_pump_mojo_handler.h | 29 | ||||
-rw-r--r-- | mojo/common/message_pump_mojo_unittest.cc | 124 | ||||
-rw-r--r-- | mojo/common/time_helper.cc | 33 | ||||
-rw-r--r-- | mojo/common/time_helper.h | 34 |
10 files changed, 9 insertions, 1682 deletions
diff --git a/mojo/common/BUILD.gn b/mojo/common/BUILD.gn index 99f0ba5..6dfed2f 100644 --- a/mojo/common/BUILD.gn +++ b/mojo/common/BUILD.gn @@ -21,13 +21,6 @@ component("common_base") { "data_pipe_file_utils.cc", "data_pipe_utils.cc", "data_pipe_utils.h", - "handle_watcher.cc", - "handle_watcher.h", - "message_pump_mojo.cc", - "message_pump_mojo.h", - "message_pump_mojo_handler.h", - "time_helper.cc", - "time_helper.h", "user_agent.cc", "user_agent.h", "weak_binding_set.h", @@ -39,7 +32,11 @@ component("common_base") { deps = [ "//base", "//base/third_party/dynamic_annotations", + "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/c/system:for_component", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//third_party/mojo/src/mojo/public/cpp/environment", + "//third_party/mojo/src/mojo/public/cpp/system", ] } @@ -78,6 +75,7 @@ test("mojo_common_unittests") { "//base:message_loop_tests", "//base/test:test_support", "//mojo/environment:chromium", + "//mojo/message_pump", "//testing/gtest", "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//third_party/mojo/src/mojo/edk/test:test_support", @@ -87,9 +85,11 @@ test("mojo_common_unittests") { ] sources = [ + # The message_pump tests are so small and some what related to this code + # that we put them here. + "../message_pump/handle_watcher_unittest.cc", + "../message_pump/message_pump_mojo_unittest.cc", "common_type_converters_unittest.cc", - "handle_watcher_unittest.cc", - "message_pump_mojo_unittest.cc", ] } diff --git a/mojo/common/handle_watcher.cc b/mojo/common/handle_watcher.cc deleted file mode 100644 index 6bff0cd..0000000 --- a/mojo/common/handle_watcher.cc +++ /dev/null @@ -1,475 +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/common/handle_watcher.h" - -#include <map> - -#include "base/atomic_sequence_num.h" -#include "base/bind.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/thread_task_runner_handle.h" -#include "base/threading/thread.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "mojo/common/message_pump_mojo.h" -#include "mojo/common/message_pump_mojo_handler.h" -#include "mojo/common/time_helper.h" - -namespace mojo { -namespace common { - -typedef int WatcherID; - -namespace { - -const char kWatcherThreadName[] = "handle-watcher-thread"; - -base::TimeTicks MojoDeadlineToTimeTicks(MojoDeadline deadline) { - return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() : - internal::NowTicks() + base::TimeDelta::FromMicroseconds(deadline); -} - -// Tracks the data for a single call to Start(). -struct WatchData { - WatchData() - : id(0), handle_signals(MOJO_HANDLE_SIGNAL_NONE), task_runner(NULL) {} - - WatcherID id; - Handle handle; - MojoHandleSignals handle_signals; - base::TimeTicks deadline; - base::Callback<void(MojoResult)> callback; - scoped_refptr<base::SingleThreadTaskRunner> task_runner; -}; - -// WatcherBackend -------------------------------------------------------------- - -// WatcherBackend is responsible for managing the requests and interacting with -// MessagePumpMojo. All access (outside of creation/destruction) is done on the -// thread WatcherThreadManager creates. -class WatcherBackend : public MessagePumpMojoHandler { - public: - WatcherBackend(); - ~WatcherBackend() override; - - void StartWatching(const WatchData& data); - - // Cancels a previously scheduled request to start a watch. - void StopWatching(WatcherID watcher_id); - - private: - typedef std::map<Handle, WatchData> HandleToWatchDataMap; - - // Invoked when a handle needs to be removed and notified. - void RemoveAndNotify(const Handle& handle, MojoResult result); - - // Searches through |handle_to_data_| for |watcher_id|. Returns true if found - // and sets |handle| to the Handle. Returns false if not a known id. - bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const; - - // MessagePumpMojoHandler overrides: - void OnHandleReady(const Handle& handle) override; - void OnHandleError(const Handle& handle, MojoResult result) override; - - // Maps from assigned id to WatchData. - HandleToWatchDataMap handle_to_data_; - - DISALLOW_COPY_AND_ASSIGN(WatcherBackend); -}; - -WatcherBackend::WatcherBackend() { -} - -WatcherBackend::~WatcherBackend() { -} - -void WatcherBackend::StartWatching(const WatchData& data) { - RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED); - - DCHECK_EQ(0u, handle_to_data_.count(data.handle)); - - handle_to_data_[data.handle] = data; - MessagePumpMojo::current()->AddHandler(this, data.handle, - data.handle_signals, - data.deadline); -} - -void WatcherBackend::StopWatching(WatcherID watcher_id) { - // Because of the thread hop it is entirely possible to get here and not - // have a valid handle registered for |watcher_id|. - Handle handle; - if (GetMojoHandleByWatcherID(watcher_id, &handle)) { - handle_to_data_.erase(handle); - MessagePumpMojo::current()->RemoveHandler(handle); - } -} - -void WatcherBackend::RemoveAndNotify(const Handle& handle, - MojoResult result) { - if (handle_to_data_.count(handle) == 0) - return; - - const WatchData data(handle_to_data_[handle]); - handle_to_data_.erase(handle); - MessagePumpMojo::current()->RemoveHandler(handle); - - data.task_runner->PostTask(FROM_HERE, base::Bind(data.callback, result)); -} - -bool WatcherBackend::GetMojoHandleByWatcherID(WatcherID watcher_id, - Handle* handle) const { - for (HandleToWatchDataMap::const_iterator i = handle_to_data_.begin(); - i != handle_to_data_.end(); ++i) { - if (i->second.id == watcher_id) { - *handle = i->second.handle; - return true; - } - } - return false; -} - -void WatcherBackend::OnHandleReady(const Handle& handle) { - RemoveAndNotify(handle, MOJO_RESULT_OK); -} - -void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) { - RemoveAndNotify(handle, result); -} - -// WatcherThreadManager -------------------------------------------------------- - -// WatcherThreadManager manages the background thread that listens for handles -// to be ready. All requests are handled by WatcherBackend. -} // namespace - -class WatcherThreadManager { - public: - ~WatcherThreadManager(); - - // Returns the shared instance. - static WatcherThreadManager* GetInstance(); - - // Starts watching the requested handle. Returns a unique ID that is used to - // stop watching the handle. When the handle is ready |callback| is notified - // on the thread StartWatching() was invoked on. - // This may be invoked on any thread. - WatcherID StartWatching(const Handle& handle, - MojoHandleSignals handle_signals, - base::TimeTicks deadline, - const base::Callback<void(MojoResult)>& callback); - - // Stops watching a handle. - // This may be invoked on any thread. - void StopWatching(WatcherID watcher_id); - - private: - enum RequestType { - REQUEST_START, - REQUEST_STOP, - }; - - // See description of |requests_| for details. - struct RequestData { - RequestData() : type(REQUEST_START), stop_id(0), stop_event(NULL) {} - - RequestType type; - WatchData start_data; - WatcherID stop_id; - base::WaitableEvent* stop_event; - }; - - typedef std::vector<RequestData> Requests; - - friend struct DefaultSingletonTraits<WatcherThreadManager>; - - WatcherThreadManager(); - - // Schedules a request on the background thread. See |requests_| for details. - void AddRequest(const RequestData& data); - - // Processes requests added to |requests_|. This is invoked on the backend - // thread. - void ProcessRequestsOnBackendThread(); - - base::Thread thread_; - - base::AtomicSequenceNumber watcher_id_generator_; - - WatcherBackend backend_; - - // Protects |requests_|. - base::Lock lock_; - - // Start/Stop result in adding a RequestData to |requests_| (protected by - // |lock_|). When the background thread wakes up it processes the requests. - Requests requests_; - - DISALLOW_COPY_AND_ASSIGN(WatcherThreadManager); -}; - -WatcherThreadManager::~WatcherThreadManager() { - thread_.Stop(); -} - -WatcherThreadManager* WatcherThreadManager::GetInstance() { - return Singleton<WatcherThreadManager>::get(); -} - -WatcherID WatcherThreadManager::StartWatching( - const Handle& handle, - MojoHandleSignals handle_signals, - base::TimeTicks deadline, - const base::Callback<void(MojoResult)>& callback) { - RequestData request_data; - request_data.type = REQUEST_START; - request_data.start_data.id = watcher_id_generator_.GetNext(); - request_data.start_data.handle = handle; - request_data.start_data.callback = callback; - request_data.start_data.handle_signals = handle_signals; - request_data.start_data.deadline = deadline; - request_data.start_data.task_runner = base::ThreadTaskRunnerHandle::Get(); - AddRequest(request_data); - return request_data.start_data.id; -} - -void WatcherThreadManager::StopWatching(WatcherID watcher_id) { - // Handle the case of StartWatching() followed by StopWatching() before - // |thread_| woke up. - { - base::AutoLock auto_lock(lock_); - for (Requests::iterator i = requests_.begin(); i != requests_.end(); ++i) { - if (i->type == REQUEST_START && i->start_data.id == watcher_id) { - // Watcher ids are not reused, so if we find it we can stop. - requests_.erase(i); - return; - } - } - } - - base::ThreadRestrictions::ScopedAllowWait allow_wait; - base::WaitableEvent event(true, false); - RequestData request_data; - request_data.type = REQUEST_STOP; - request_data.stop_id = watcher_id; - request_data.stop_event = &event; - AddRequest(request_data); - - // We need to block until the handle is actually removed. - event.Wait(); -} - -void WatcherThreadManager::AddRequest(const RequestData& data) { - { - base::AutoLock auto_lock(lock_); - const bool was_empty = requests_.empty(); - requests_.push_back(data); - if (!was_empty) - return; - } - // We own |thread_|, so it's safe to use Unretained() here. - thread_.task_runner()->PostTask( - FROM_HERE, - base::Bind(&WatcherThreadManager::ProcessRequestsOnBackendThread, - base::Unretained(this))); -} - -void WatcherThreadManager::ProcessRequestsOnBackendThread() { - DCHECK_EQ(thread_.message_loop(), base::MessageLoop::current()); - - Requests requests; - { - base::AutoLock auto_lock(lock_); - requests_.swap(requests); - } - for (size_t i = 0; i < requests.size(); ++i) { - if (requests[i].type == REQUEST_START) { - backend_.StartWatching(requests[i].start_data); - } else { - backend_.StopWatching(requests[i].stop_id); - requests[i].stop_event->Signal(); - } - } -} - -WatcherThreadManager::WatcherThreadManager() - : thread_(kWatcherThreadName) { - base::Thread::Options thread_options; - thread_options.message_pump_factory = base::Bind(&MessagePumpMojo::Create); - thread_.StartWithOptions(thread_options); -} - -// HandleWatcher::StateBase and subclasses ------------------------------------- - -// The base class of HandleWatcher's state. Owns the user's callback and -// monitors the current thread's MessageLoop to know when to force the callback -// to run (with an error) even though the pipe hasn't been signaled yet. -class HandleWatcher::StateBase : public base::MessageLoop::DestructionObserver { - public: - StateBase(HandleWatcher* watcher, - const base::Callback<void(MojoResult)>& callback) - : watcher_(watcher), - callback_(callback), - got_ready_(false) { - base::MessageLoop::current()->AddDestructionObserver(this); - } - - ~StateBase() override { - base::MessageLoop::current()->RemoveDestructionObserver(this); - } - - protected: - void NotifyHandleReady(MojoResult result) { - got_ready_ = true; - NotifyAndDestroy(result); - } - - bool got_ready() const { return got_ready_; } - - private: - void WillDestroyCurrentMessageLoop() override { - // The current thread is exiting. Simulate a watch error. - NotifyAndDestroy(MOJO_RESULT_ABORTED); - } - - void NotifyAndDestroy(MojoResult result) { - base::Callback<void(MojoResult)> callback = callback_; - watcher_->Stop(); // Destroys |this|. - - callback.Run(result); - } - - HandleWatcher* watcher_; - base::Callback<void(MojoResult)> callback_; - - // Have we been notified that the handle is ready? - bool got_ready_; - - DISALLOW_COPY_AND_ASSIGN(StateBase); -}; - -// If the thread on which HandleWatcher is used runs MessagePumpMojo, -// SameThreadWatchingState is used to directly watch the handle on the same -// thread. -class HandleWatcher::SameThreadWatchingState : public StateBase, - public MessagePumpMojoHandler { - public: - SameThreadWatchingState(HandleWatcher* watcher, - const Handle& handle, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - const base::Callback<void(MojoResult)>& callback) - : StateBase(watcher, callback), - handle_(handle) { - DCHECK(MessagePumpMojo::IsCurrent()); - - MessagePumpMojo::current()->AddHandler( - this, handle, handle_signals, MojoDeadlineToTimeTicks(deadline)); - } - - ~SameThreadWatchingState() override { - if (!got_ready()) - MessagePumpMojo::current()->RemoveHandler(handle_); - } - - private: - // MessagePumpMojoHandler overrides: - void OnHandleReady(const Handle& handle) override { - StopWatchingAndNotifyReady(handle, MOJO_RESULT_OK); - } - - void OnHandleError(const Handle& handle, MojoResult result) override { - StopWatchingAndNotifyReady(handle, result); - } - - void StopWatchingAndNotifyReady(const Handle& handle, MojoResult result) { - DCHECK_EQ(handle.value(), handle_.value()); - MessagePumpMojo::current()->RemoveHandler(handle_); - NotifyHandleReady(result); - } - - Handle handle_; - - DISALLOW_COPY_AND_ASSIGN(SameThreadWatchingState); -}; - -// If the thread on which HandleWatcher is used runs a message pump different -// from MessagePumpMojo, SecondaryThreadWatchingState is used to watch the -// handle on the handle watcher thread. -class HandleWatcher::SecondaryThreadWatchingState : public StateBase { - public: - SecondaryThreadWatchingState(HandleWatcher* watcher, - const Handle& handle, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - const base::Callback<void(MojoResult)>& callback) - : StateBase(watcher, callback), - weak_factory_(this) { - watcher_id_ = WatcherThreadManager::GetInstance()->StartWatching( - handle, - handle_signals, - MojoDeadlineToTimeTicks(deadline), - base::Bind(&SecondaryThreadWatchingState::NotifyHandleReady, - weak_factory_.GetWeakPtr())); - } - - ~SecondaryThreadWatchingState() override { - // If we've been notified the handle is ready (|got_ready()| is true) then - // the watch has been implicitly removed by - // WatcherThreadManager/MessagePumpMojo and we don't have to call - // StopWatching(). To do so would needlessly entail posting a task and - // blocking until the background thread services it. - if (!got_ready()) - WatcherThreadManager::GetInstance()->StopWatching(watcher_id_); - } - - private: - WatcherID watcher_id_; - - // Used to weakly bind |this| to the WatcherThreadManager. - base::WeakPtrFactory<SecondaryThreadWatchingState> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(SecondaryThreadWatchingState); -}; - -// HandleWatcher --------------------------------------------------------------- - -HandleWatcher::HandleWatcher() { -} - -HandleWatcher::~HandleWatcher() { -} - -void HandleWatcher::Start(const Handle& handle, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - const base::Callback<void(MojoResult)>& callback) { - DCHECK(handle.is_valid()); - DCHECK_NE(MOJO_HANDLE_SIGNAL_NONE, handle_signals); - - // Need to clear the state before creating a new one. - state_.reset(); - if (MessagePumpMojo::IsCurrent()) { - state_.reset(new SameThreadWatchingState( - this, handle, handle_signals, deadline, callback)); - } else { - state_.reset(new SecondaryThreadWatchingState( - this, handle, handle_signals, deadline, callback)); - } -} - -void HandleWatcher::Stop() { - state_.reset(); -} - -} // namespace common -} // namespace mojo diff --git a/mojo/common/handle_watcher.h b/mojo/common/handle_watcher.h deleted file mode 100644 index 9056ec4..0000000 --- a/mojo/common/handle_watcher.h +++ /dev/null @@ -1,64 +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_COMMON_HANDLE_WATCHER_H_ -#define MOJO_COMMON_HANDLE_WATCHER_H_ - -#include "base/basictypes.h" -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" -#include "base/run_loop.h" -#include "mojo/common/mojo_common_export.h" -#include "third_party/mojo/src/mojo/public/cpp/system/core.h" - -namespace base { -class Thread; -} - -namespace mojo { -namespace common { -namespace test { -class HandleWatcherTest; -} - -// HandleWatcher is used to asynchronously wait on a handle and notify a Closure -// when the handle is ready, or the deadline has expired. -class MOJO_COMMON_EXPORT HandleWatcher { - public: - HandleWatcher(); - - // The destructor implicitly stops listening. See Stop() for details. - ~HandleWatcher(); - - // Starts listening for |handle|. This implicitly invokes Stop(). In other - // words, Start() performs one asynchronous watch at a time. It is ok to call - // Start() multiple times, but it cancels any existing watches. |callback| is - // notified when the handle is ready, invalid or deadline has passed and is - // notified on the thread Start() was invoked on. If the current thread exits - // before the handle is ready, then |callback| is invoked with a result of - // MOJO_RESULT_ABORTED. - void Start(const Handle& handle, - MojoHandleSignals handle_signals, - MojoDeadline deadline, - const base::Callback<void(MojoResult)>& callback); - - // Stops listening. Does nothing if not in the process of listening. Blocks - // until no longer listening on the handle. - void Stop(); - - private: - class StateBase; - class SameThreadWatchingState; - class SecondaryThreadWatchingState; - - // If non-NULL Start() has been invoked. - scoped_ptr<StateBase> state_; - - DISALLOW_COPY_AND_ASSIGN(HandleWatcher); -}; - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_HANDLE_WATCHER_H_ diff --git a/mojo/common/handle_watcher_unittest.cc b/mojo/common/handle_watcher_unittest.cc deleted file mode 100644 index 41d5ffb..0000000 --- a/mojo/common/handle_watcher_unittest.cc +++ /dev/null @@ -1,483 +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/common/handle_watcher.h" - -#include <string> - -#include "base/at_exit.h" -#include "base/auto_reset.h" -#include "base/bind.h" -#include "base/memory/scoped_vector.h" -#include "base/run_loop.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/threading/thread.h" -#include "mojo/common/message_pump_mojo.h" -#include "mojo/common/time_helper.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/public/cpp/system/core.h" -#include "third_party/mojo/src/mojo/public/cpp/test_support/test_utils.h" - -namespace mojo { -namespace common { -namespace test { - -enum MessageLoopConfig { - MESSAGE_LOOP_CONFIG_DEFAULT = 0, - MESSAGE_LOOP_CONFIG_MOJO = 1 -}; - -void ObserveCallback(bool* was_signaled, - MojoResult* result_observed, - MojoResult result) { - *was_signaled = true; - *result_observed = result; -} - -void RunUntilIdle() { - base::RunLoop run_loop; - run_loop.RunUntilIdle(); -} - -void DeleteWatcherAndForwardResult( - HandleWatcher* watcher, - base::Callback<void(MojoResult)> next_callback, - MojoResult result) { - delete watcher; - next_callback.Run(result); -} - -scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { - scoped_ptr<base::MessageLoop> loop; - if (config == MESSAGE_LOOP_CONFIG_DEFAULT) - loop.reset(new base::MessageLoop()); - else - loop.reset(new base::MessageLoop(MessagePumpMojo::Create())); - return loop.Pass(); -} - -// Helper class to manage the callback and running the message loop waiting for -// message to be received. Typical usage is something like: -// Schedule callback returned from GetCallback(). -// RunUntilGotCallback(); -// EXPECT_TRUE(got_callback()); -// clear_callback(); -class CallbackHelper { - public: - CallbackHelper() - : got_callback_(false), - run_loop_(NULL), - weak_factory_(this) {} - ~CallbackHelper() {} - - // See description above |got_callback_|. - bool got_callback() const { return got_callback_; } - void clear_callback() { got_callback_ = false; } - - // Runs the current MessageLoop until the callback returned from GetCallback() - // is notified. - void RunUntilGotCallback() { - ASSERT_TRUE(run_loop_ == NULL); - base::RunLoop run_loop; - base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); - run_loop.Run(); - } - - base::Callback<void(MojoResult)> GetCallback() { - return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); - } - - void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { - StartWithCallback(watcher, handle, GetCallback()); - } - - void StartWithCallback(HandleWatcher* watcher, - const MessagePipeHandle& handle, - const base::Callback<void(MojoResult)>& callback) { - watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, callback); - } - - private: - void OnCallback(MojoResult result) { - got_callback_ = true; - if (run_loop_) - run_loop_->Quit(); - } - - // Set to true when the callback is called. - bool got_callback_; - - // If non-NULL we're in RunUntilGotCallback(). - base::RunLoop* run_loop_; - - base::WeakPtrFactory<CallbackHelper> weak_factory_; - - private: - DISALLOW_COPY_AND_ASSIGN(CallbackHelper); -}; - -class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> { - public: - HandleWatcherTest() : message_loop_(CreateMessageLoop(GetParam())) {} - virtual ~HandleWatcherTest() { - test::SetTickClockForTest(NULL); - } - - protected: - void TearDownMessageLoop() { - message_loop_.reset(); - } - - void InstallTickClock() { - test::SetTickClockForTest(&tick_clock_); - } - - base::SimpleTestTickClock tick_clock_; - - private: - base::ShadowingAtExitManager at_exit_; - scoped_ptr<base::MessageLoop> message_loop_; - - DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); -}; - -INSTANTIATE_TEST_CASE_P( - MultipleMessageLoopConfigs, HandleWatcherTest, - testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, MESSAGE_LOOP_CONFIG_MOJO)); - -// Trivial test case with a single handle to watch. -TEST_P(HandleWatcherTest, SingleHandler) { - MessagePipe test_pipe; - ASSERT_TRUE(test_pipe.handle0.is_valid()); - CallbackHelper callback_helper; - HandleWatcher watcher; - callback_helper.Start(&watcher, test_pipe.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper.got_callback()); - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), - std::string())); - callback_helper.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper.got_callback()); -} - -// Creates three handles and notfies them in reverse order ensuring each one is -// notified appropriately. -TEST_P(HandleWatcherTest, ThreeHandles) { - MessagePipe test_pipe1; - MessagePipe test_pipe2; - MessagePipe test_pipe3; - CallbackHelper callback_helper1; - CallbackHelper callback_helper2; - CallbackHelper callback_helper3; - ASSERT_TRUE(test_pipe1.handle0.is_valid()); - ASSERT_TRUE(test_pipe2.handle0.is_valid()); - ASSERT_TRUE(test_pipe3.handle0.is_valid()); - - HandleWatcher watcher1; - callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - - HandleWatcher watcher2; - callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - - HandleWatcher watcher3; - callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - - // Write to 3 and make sure it's notified. - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), - std::string())); - callback_helper3.RunUntilGotCallback(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_TRUE(callback_helper3.got_callback()); - callback_helper3.clear_callback(); - - // Write to 1 and 3. Only 1 should be notified since 3 was is no longer - // running. - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), - std::string())); - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), - std::string())); - callback_helper1.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - callback_helper1.clear_callback(); - - // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), - std::string())); - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), - std::string())); - callback_helper2.RunUntilGotCallback(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_TRUE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); -} - -// Verifies Start() invoked a second time works. -TEST_P(HandleWatcherTest, Restart) { - MessagePipe test_pipe1; - MessagePipe test_pipe2; - CallbackHelper callback_helper1; - CallbackHelper callback_helper2; - ASSERT_TRUE(test_pipe1.handle0.is_valid()); - ASSERT_TRUE(test_pipe2.handle0.is_valid()); - - HandleWatcher watcher1; - callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - - HandleWatcher watcher2; - callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - - // Write to 1 and make sure it's notified. - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), - std::string())); - callback_helper1.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - callback_helper1.clear_callback(); - EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); - - // Write to 2 and make sure it's notified. - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), - std::string())); - callback_helper2.RunUntilGotCallback(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_TRUE(callback_helper2.got_callback()); - callback_helper2.clear_callback(); - - // Listen on 1 again. - callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - - // Write to 1 and make sure it's notified. - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), - std::string())); - callback_helper1.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); -} - -// Verifies Start() invoked a second time on the same handle works. -TEST_P(HandleWatcherTest, RestartOnSameHandle) { - MessagePipe test_pipe; - CallbackHelper callback_helper; - ASSERT_TRUE(test_pipe.handle0.is_valid()); - - HandleWatcher watcher; - callback_helper.Start(&watcher, test_pipe.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper.got_callback()); - - callback_helper.Start(&watcher, test_pipe.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper.got_callback()); -} - -// Verifies deadline is honored. -TEST_P(HandleWatcherTest, Deadline) { - InstallTickClock(); - - MessagePipe test_pipe1; - MessagePipe test_pipe2; - MessagePipe test_pipe3; - CallbackHelper callback_helper1; - CallbackHelper callback_helper2; - CallbackHelper callback_helper3; - ASSERT_TRUE(test_pipe1.handle0.is_valid()); - ASSERT_TRUE(test_pipe2.handle0.is_valid()); - ASSERT_TRUE(test_pipe3.handle0.is_valid()); - - // Add a watcher with an infinite timeout. - HandleWatcher watcher1; - callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - - // Add another watcher wth a timeout of 500 microseconds. - HandleWatcher watcher2; - watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500, - callback_helper2.GetCallback()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_FALSE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); - - // Advance the clock passed the deadline. We also have to start another - // watcher to wake up the background thread. - tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); - - HandleWatcher watcher3; - callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); - - callback_helper2.RunUntilGotCallback(); - EXPECT_FALSE(callback_helper1.got_callback()); - EXPECT_TRUE(callback_helper2.got_callback()); - EXPECT_FALSE(callback_helper3.got_callback()); -} - -TEST_P(HandleWatcherTest, DeleteInCallback) { - MessagePipe test_pipe; - CallbackHelper callback_helper; - - HandleWatcher* watcher = new HandleWatcher(); - callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), - base::Bind(&DeleteWatcherAndForwardResult, - watcher, - callback_helper.GetCallback())); - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), - std::string())); - callback_helper.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper.got_callback()); -} - -TEST_P(HandleWatcherTest, AbortedOnMessageLoopDestruction) { - bool was_signaled = false; - MojoResult result = MOJO_RESULT_OK; - - MessagePipe pipe; - HandleWatcher watcher; - watcher.Start(pipe.handle0.get(), - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, - base::Bind(&ObserveCallback, &was_signaled, &result)); - - // Now, let the MessageLoop get torn down. We expect our callback to run. - TearDownMessageLoop(); - - EXPECT_TRUE(was_signaled); - EXPECT_EQ(MOJO_RESULT_ABORTED, result); -} - -void NeverReached(MojoResult result) { - FAIL() << "Callback should never be invoked " << result; -} - -// Called on the main thread when a thread is done. Decrements |active_count| -// and if |active_count| is zero quits |run_loop|. -void StressThreadDone(base::RunLoop* run_loop, int* active_count) { - (*active_count)--; - EXPECT_GE(*active_count, 0); - if (*active_count == 0) - run_loop->Quit(); -} - -// See description of StressTest. This is called on the background thread. -// |count| is the number of HandleWatchers to create. |active_count| is the -// number of outstanding threads, |task_runner| the task runner for the main -// thread and |run_loop| the run loop that should be quit when there are no more -// threads running. When done StressThreadDone() is invoked on the main thread. -// |active_count| and |run_loop| should only be used on the main thread. -void RunStressTest(int count, - scoped_refptr<base::TaskRunner> task_runner, - base::RunLoop* run_loop, - int* active_count) { - struct TestData { - MessagePipe pipe; - HandleWatcher watcher; - }; - ScopedVector<TestData> data_vector; - for (int i = 0; i < count; ++i) { - if (i % 20 == 0) { - // Every so often we wait. This results in some level of thread balancing - // as well as making sure HandleWatcher has time to actually start some - // watches. - MessagePipe test_pipe; - ASSERT_TRUE(test_pipe.handle0.is_valid()); - CallbackHelper callback_helper; - HandleWatcher watcher; - callback_helper.Start(&watcher, test_pipe.handle0.get()); - RunUntilIdle(); - EXPECT_FALSE(callback_helper.got_callback()); - EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), - std::string())); - base::MessageLoop::ScopedNestableTaskAllower scoper( - base::MessageLoop::current()); - callback_helper.RunUntilGotCallback(); - EXPECT_TRUE(callback_helper.got_callback()); - } else { - scoped_ptr<TestData> test_data(new TestData); - ASSERT_TRUE(test_data->pipe.handle0.is_valid()); - test_data->watcher.Start(test_data->pipe.handle0.get(), - MOJO_HANDLE_SIGNAL_READABLE, - MOJO_DEADLINE_INDEFINITE, - base::Bind(&NeverReached)); - data_vector.push_back(test_data.release()); - } - if (i % 15 == 0) - data_vector.clear(); - } - task_runner->PostTask(FROM_HERE, - base::Bind(&StressThreadDone, run_loop, - active_count)); -} - -// This test is meant to stress HandleWatcher. It uses from various threads -// repeatedly starting and stopping watches. It spins up kThreadCount -// threads. Each thread creates kWatchCount watches. Every so often each thread -// writes to a pipe and waits for the response. -TEST(HandleWatcherCleanEnvironmentTest, StressTest) { -#if defined(NDEBUG) - const int kThreadCount = 15; - const int kWatchCount = 400; -#else - const int kThreadCount = 10; - const int kWatchCount = 250; -#endif - - base::ShadowingAtExitManager at_exit; - base::MessageLoop message_loop; - base::RunLoop run_loop; - ScopedVector<base::Thread> threads; - int threads_active_counter = kThreadCount; - // Starts the threads first and then post the task in hopes of having more - // threads running at once. - for (int i = 0; i < kThreadCount; ++i) { - scoped_ptr<base::Thread> thread(new base::Thread("test thread")); - if (i % 2) { - base::Thread::Options thread_options; - thread_options.message_pump_factory = - base::Bind(&MessagePumpMojo::Create); - thread->StartWithOptions(thread_options); - } else { - thread->Start(); - } - threads.push_back(thread.release()); - } - for (int i = 0; i < kThreadCount; ++i) { - threads[i]->task_runner()->PostTask( - FROM_HERE, base::Bind(&RunStressTest, kWatchCount, - message_loop.task_runner(), - &run_loop, &threads_active_counter)); - } - run_loop.Run(); - ASSERT_EQ(0, threads_active_counter); -} - -} // namespace test -} // namespace common -} // namespace mojo diff --git a/mojo/common/message_pump_mojo.cc b/mojo/common/message_pump_mojo.cc deleted file mode 100644 index afbf8f9..0000000 --- a/mojo/common/message_pump_mojo.cc +++ /dev/null @@ -1,295 +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/common/message_pump_mojo.h" - -#include <algorithm> -#include <vector> - -#include "base/debug/alias.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/threading/thread_local.h" -#include "base/time/time.h" -#include "mojo/common/message_pump_mojo_handler.h" -#include "mojo/common/time_helper.h" - -namespace mojo { -namespace common { -namespace { - -base::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky - g_tls_current_pump = LAZY_INSTANCE_INITIALIZER; - -MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, - base::TimeTicks now) { - // The is_null() check matches that of HandleWatcher as well as how - // |delayed_work_time| is used. - if (time_ticks.is_null()) - return MOJO_DEADLINE_INDEFINITE; - const int64_t delta = (time_ticks - now).InMicroseconds(); - return delta < 0 ? static_cast<MojoDeadline>(0) : - static_cast<MojoDeadline>(delta); -} - -} // namespace - -// State needed for one iteration of WaitMany. The first handle and flags -// corresponds to that of the control pipe. -struct MessagePumpMojo::WaitState { - std::vector<Handle> handles; - std::vector<MojoHandleSignals> wait_signals; -}; - -struct MessagePumpMojo::RunState { - RunState() : should_quit(false) { - CreateMessagePipe(NULL, &read_handle, &write_handle); - } - - base::TimeTicks delayed_work_time; - - // Used to wake up WaitForWork(). - ScopedMessagePipeHandle read_handle; - ScopedMessagePipeHandle write_handle; - - bool should_quit; -}; - -MessagePumpMojo::MessagePumpMojo() : run_state_(NULL), next_handler_id_(0) { - DCHECK(!current()) - << "There is already a MessagePumpMojo instance on this thread."; - g_tls_current_pump.Pointer()->Set(this); -} - -MessagePumpMojo::~MessagePumpMojo() { - DCHECK_EQ(this, current()); - g_tls_current_pump.Pointer()->Set(NULL); -} - -// static -scoped_ptr<base::MessagePump> MessagePumpMojo::Create() { - return scoped_ptr<MessagePump>(new MessagePumpMojo()); -} - -// static -MessagePumpMojo* MessagePumpMojo::current() { - return g_tls_current_pump.Pointer()->Get(); -} - -void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler, - const Handle& handle, - MojoHandleSignals wait_signals, - base::TimeTicks deadline) { - CHECK(handler); - DCHECK(handle.is_valid()); - // Assume it's an error if someone tries to reregister an existing handle. - CHECK_EQ(0u, handlers_.count(handle)); - Handler handler_data; - handler_data.handler = handler; - handler_data.wait_signals = wait_signals; - handler_data.deadline = deadline; - handler_data.id = next_handler_id_++; - handlers_[handle] = handler_data; -} - -void MessagePumpMojo::RemoveHandler(const Handle& handle) { - handlers_.erase(handle); -} - -void MessagePumpMojo::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void MessagePumpMojo::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -void MessagePumpMojo::Run(Delegate* delegate) { - RunState run_state; - // TODO: better deal with error handling. - CHECK(run_state.read_handle.is_valid()); - CHECK(run_state.write_handle.is_valid()); - RunState* old_state = NULL; - { - base::AutoLock auto_lock(run_state_lock_); - old_state = run_state_; - run_state_ = &run_state; - } - DoRunLoop(&run_state, delegate); - { - base::AutoLock auto_lock(run_state_lock_); - run_state_ = old_state; - } -} - -void MessagePumpMojo::Quit() { - base::AutoLock auto_lock(run_state_lock_); - if (run_state_) - run_state_->should_quit = true; -} - -void MessagePumpMojo::ScheduleWork() { - base::AutoLock auto_lock(run_state_lock_); - if (run_state_) - SignalControlPipe(*run_state_); -} - -void MessagePumpMojo::ScheduleDelayedWork( - const base::TimeTicks& delayed_work_time) { - base::AutoLock auto_lock(run_state_lock_); - if (!run_state_) - return; - run_state_->delayed_work_time = delayed_work_time; -} - -void MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { - bool more_work_is_plausible = true; - for (;;) { - const bool block = !more_work_is_plausible; - more_work_is_plausible = DoInternalWork(*run_state, block); - - if (run_state->should_quit) - break; - - more_work_is_plausible |= delegate->DoWork(); - if (run_state->should_quit) - break; - - more_work_is_plausible |= delegate->DoDelayedWork( - &run_state->delayed_work_time); - if (run_state->should_quit) - break; - - if (more_work_is_plausible) - continue; - - more_work_is_plausible = delegate->DoIdleWork(); - if (run_state->should_quit) - break; - } -} - -bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { - const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; - const WaitState wait_state = GetWaitState(run_state); - - const WaitManyResult wait_many_result = - WaitMany(wait_state.handles, wait_state.wait_signals, deadline, nullptr); - const MojoResult result = wait_many_result.result; - bool did_work = true; - if (result == MOJO_RESULT_OK) { - if (wait_many_result.index == 0) { - // Control pipe was written to. - ReadMessageRaw(run_state.read_handle.get(), NULL, NULL, NULL, NULL, - MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); - } else { - DCHECK(handlers_.find(wait_state.handles[wait_many_result.index]) != - handlers_.end()); - WillSignalHandler(); - handlers_[wait_state.handles[wait_many_result.index]] - .handler->OnHandleReady(wait_state.handles[wait_many_result.index]); - DidSignalHandler(); - } - } else { - switch (result) { - case MOJO_RESULT_CANCELLED: - case MOJO_RESULT_FAILED_PRECONDITION: - RemoveInvalidHandle(wait_state, result, wait_many_result.index); - break; - case MOJO_RESULT_DEADLINE_EXCEEDED: - did_work = false; - break; - default: - base::debug::Alias(&result); - // Unexpected result is likely fatal, crash so we can determine cause. - CHECK(false); - } - } - - // Notify and remove any handlers whose time has expired. Make a copy in case - // someone tries to add/remove new handlers from notification. - const HandleToHandler cloned_handlers(handlers_); - const base::TimeTicks now(internal::NowTicks()); - for (HandleToHandler::const_iterator i = cloned_handlers.begin(); - i != cloned_handlers.end(); ++i) { - // Since we're iterating over a clone of the handlers, verify the handler is - // still valid before notifying. - if (!i->second.deadline.is_null() && i->second.deadline < now && - handlers_.find(i->first) != handlers_.end() && - handlers_[i->first].id == i->second.id) { - WillSignalHandler(); - i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED); - DidSignalHandler(); - handlers_.erase(i->first); - did_work = true; - } - } - return did_work; -} - -void MessagePumpMojo::RemoveInvalidHandle(const WaitState& wait_state, - MojoResult result, - uint32_t index) { - // TODO(sky): deal with control pipe going bad. - CHECK(result == MOJO_RESULT_FAILED_PRECONDITION || - result == MOJO_RESULT_CANCELLED); - CHECK_NE(index, 0u); // Indicates the control pipe went bad. - - // Remove the handle first, this way if OnHandleError() tries to remove the - // handle our iterator isn't invalidated. - CHECK(handlers_.find(wait_state.handles[index]) != handlers_.end()); - MessagePumpMojoHandler* handler = - handlers_[wait_state.handles[index]].handler; - handlers_.erase(wait_state.handles[index]); - WillSignalHandler(); - handler->OnHandleError(wait_state.handles[index], result); - DidSignalHandler(); -} - -void MessagePumpMojo::SignalControlPipe(const RunState& run_state) { - const MojoResult result = - WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, - MOJO_WRITE_MESSAGE_FLAG_NONE); - // If we can't write we likely won't wake up the thread and there is a strong - // chance we'll deadlock. - CHECK_EQ(MOJO_RESULT_OK, result); -} - -MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( - const RunState& run_state) const { - WaitState wait_state; - wait_state.handles.push_back(run_state.read_handle.get()); - wait_state.wait_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); - - for (HandleToHandler::const_iterator i = handlers_.begin(); - i != handlers_.end(); ++i) { - wait_state.handles.push_back(i->first); - wait_state.wait_signals.push_back(i->second.wait_signals); - } - return wait_state; -} - -MojoDeadline MessagePumpMojo::GetDeadlineForWait( - const RunState& run_state) const { - const base::TimeTicks now(internal::NowTicks()); - MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, - now); - for (HandleToHandler::const_iterator i = handlers_.begin(); - i != handlers_.end(); ++i) { - deadline = std::min( - TimeTicksToMojoDeadline(i->second.deadline, now), deadline); - } - return deadline; -} - -void MessagePumpMojo::WillSignalHandler() { - FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler()); -} - -void MessagePumpMojo::DidSignalHandler() { - FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler()); -} - -} // namespace common -} // namespace mojo diff --git a/mojo/common/message_pump_mojo.h b/mojo/common/message_pump_mojo.h deleted file mode 100644 index 86dd8ac..0000000 --- a/mojo/common/message_pump_mojo.h +++ /dev/null @@ -1,136 +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_COMMON_MESSAGE_PUMP_MOJO_H_ -#define MOJO_COMMON_MESSAGE_PUMP_MOJO_H_ - -#include <map> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_pump.h" -#include "base/observer_list.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" -#include "mojo/common/mojo_common_export.h" -#include "third_party/mojo/src/mojo/public/cpp/system/core.h" - -namespace mojo { -namespace common { - -class MessagePumpMojoHandler; - -// Mojo implementation of MessagePump. -class MOJO_COMMON_EXPORT MessagePumpMojo : public base::MessagePump { - public: - class Observer { - public: - Observer() {} - - virtual void WillSignalHandler() = 0; - virtual void DidSignalHandler() = 0; - - protected: - virtual ~Observer() {} - }; - - MessagePumpMojo(); - ~MessagePumpMojo() override; - - // Static factory function (for using with |base::Thread::Options|, wrapped - // using |base::Bind()|). - static scoped_ptr<base::MessagePump> Create(); - - // Returns the MessagePumpMojo instance of the current thread, if it exists. - static MessagePumpMojo* current(); - - static bool IsCurrent() { return !!current(); } - - // Registers a MessagePumpMojoHandler for the specified handle. Only one - // handler can be registered for a specified handle. - // NOTE: a value of 0 for |deadline| indicates an indefinite timeout. - void AddHandler(MessagePumpMojoHandler* handler, - const Handle& handle, - MojoHandleSignals wait_signals, - base::TimeTicks deadline); - - void RemoveHandler(const Handle& handle); - - void AddObserver(Observer*); - void RemoveObserver(Observer*); - - // MessagePump: - void Run(Delegate* delegate) override; - void Quit() override; - void ScheduleWork() override; - void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override; - - private: - struct RunState; - struct WaitState; - - // Contains the data needed to track a request to AddHandler(). - struct Handler { - Handler() : handler(NULL), wait_signals(MOJO_HANDLE_SIGNAL_NONE), id(0) {} - - MessagePumpMojoHandler* handler; - MojoHandleSignals wait_signals; - base::TimeTicks deadline; - // See description of |MessagePumpMojo::next_handler_id_| for details. - int id; - }; - - typedef std::map<Handle, Handler> HandleToHandler; - - // Implementation of Run(). - void DoRunLoop(RunState* run_state, Delegate* delegate); - - // Services the set of handles ready. If |block| is true this waits for a - // handle to become ready, otherwise this does not block. Returns |true| if a - // handle has become ready, |false| otherwise. - bool DoInternalWork(const RunState& run_state, bool block); - - // Removes the given invalid handle. This is called if MojoWaitMany finds an - // invalid handle. - void RemoveInvalidHandle(const WaitState& wait_state, - MojoResult result, - uint32_t result_index); - - void SignalControlPipe(const RunState& run_state); - - WaitState GetWaitState(const RunState& run_state) const; - - // Returns the deadline for the call to MojoWaitMany(). - MojoDeadline GetDeadlineForWait(const RunState& run_state) const; - - void WillSignalHandler(); - void DidSignalHandler(); - - // If non-NULL we're running (inside Run()). Member is reference to value on - // stack. - RunState* run_state_; - - // Lock for accessing |run_state_|. In general the only method that we have to - // worry about is ScheduleWork(). All other methods are invoked on the same - // thread. - base::Lock run_state_lock_; - - HandleToHandler handlers_; - - // An ever increasing value assigned to each Handler::id. Used to detect - // uniqueness while notifying. That is, while notifying expired timers we copy - // |handlers_| and only notify handlers whose id match. If the id does not - // match it means the handler was removed then added so that we shouldn't - // notify it. - int next_handler_id_; - - base::ObserverList<Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(MessagePumpMojo); -}; - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_MESSAGE_PUMP_MOJO_H_ diff --git a/mojo/common/message_pump_mojo_handler.h b/mojo/common/message_pump_mojo_handler.h deleted file mode 100644 index dd136ed..0000000 --- a/mojo/common/message_pump_mojo_handler.h +++ /dev/null @@ -1,29 +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_COMMON_MESSAGE_PUMP_MOJO_HANDLER_H_ -#define MOJO_COMMON_MESSAGE_PUMP_MOJO_HANDLER_H_ - -#include "mojo/common/mojo_common_export.h" -#include "third_party/mojo/src/mojo/public/cpp/system/core.h" - -namespace mojo { -namespace common { - -// Used by MessagePumpMojo to notify when a handle is either ready or has become -// invalid. In case of error, the handler will be removed. -class MOJO_COMMON_EXPORT MessagePumpMojoHandler { - public: - virtual void OnHandleReady(const Handle& handle) = 0; - - virtual void OnHandleError(const Handle& handle, MojoResult result) = 0; - - protected: - virtual ~MessagePumpMojoHandler() {} -}; - -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_MESSAGE_PUMP_MOJO_HANDLER_H_ diff --git a/mojo/common/message_pump_mojo_unittest.cc b/mojo/common/message_pump_mojo_unittest.cc deleted file mode 100644 index 5d695f6..0000000 --- a/mojo/common/message_pump_mojo_unittest.cc +++ /dev/null @@ -1,124 +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/common/message_pump_mojo.h" - -#include "base/message_loop/message_loop_test.h" -#include "base/run_loop.h" -#include "mojo/common/message_pump_mojo_handler.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo/src/mojo/public/cpp/system/core.h" - -namespace mojo { -namespace common { -namespace test { - -scoped_ptr<base::MessagePump> CreateMojoMessagePump() { - return scoped_ptr<base::MessagePump>(new MessagePumpMojo()); -} - -RUN_MESSAGE_LOOP_TESTS(Mojo, &CreateMojoMessagePump); - -class CountingMojoHandler : public MessagePumpMojoHandler { - public: - CountingMojoHandler() : success_count_(0), error_count_(0) {} - - void OnHandleReady(const Handle& handle) override { - ReadMessageRaw(static_cast<const MessagePipeHandle&>(handle), - NULL, - NULL, - NULL, - NULL, - MOJO_READ_MESSAGE_FLAG_NONE); - ++success_count_; - } - void OnHandleError(const Handle& handle, MojoResult result) override { - ++error_count_; - } - - int success_count() { return success_count_; } - int error_count() { return error_count_; } - - private: - int success_count_; - int error_count_; - - DISALLOW_COPY_AND_ASSIGN(CountingMojoHandler); -}; - -class CountingObserver : public MessagePumpMojo::Observer { - public: - void WillSignalHandler() override { will_signal_handler_count++; } - void DidSignalHandler() override { did_signal_handler_count++; } - - int will_signal_handler_count = 0; - int did_signal_handler_count = 0; -}; - -TEST(MessagePumpMojo, RunUntilIdle) { - base::MessageLoop message_loop(MessagePumpMojo::Create()); - CountingMojoHandler handler; - MessagePipe handles; - MessagePumpMojo::current()->AddHandler(&handler, - handles.handle0.get(), - MOJO_HANDLE_SIGNAL_READABLE, - base::TimeTicks()); - WriteMessageRaw( - handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - WriteMessageRaw( - handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - EXPECT_EQ(2, handler.success_count()); -} - -TEST(MessagePumpMojo, Observer) { - base::MessageLoop message_loop(MessagePumpMojo::Create()); - - CountingObserver observer; - MessagePumpMojo::current()->AddObserver(&observer); - - CountingMojoHandler handler; - MessagePipe handles; - MessagePumpMojo::current()->AddHandler(&handler, - handles.handle0.get(), - MOJO_HANDLE_SIGNAL_READABLE, - base::TimeTicks()); - WriteMessageRaw( - handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - EXPECT_EQ(1, handler.success_count()); - EXPECT_EQ(1, observer.will_signal_handler_count); - EXPECT_EQ(1, observer.did_signal_handler_count); - MessagePumpMojo::current()->RemoveObserver(&observer); - - WriteMessageRaw( - handles.handle1.get(), NULL, 0, NULL, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); - base::RunLoop run_loop2; - run_loop2.RunUntilIdle(); - EXPECT_EQ(2, handler.success_count()); - EXPECT_EQ(1, observer.will_signal_handler_count); - EXPECT_EQ(1, observer.did_signal_handler_count); -} - -TEST(MessagePumpMojo, UnregisterAfterDeadline) { - base::MessageLoop message_loop(MessagePumpMojo::Create()); - CountingMojoHandler handler; - MessagePipe handles; - MessagePumpMojo::current()->AddHandler( - &handler, - handles.handle0.get(), - MOJO_HANDLE_SIGNAL_READABLE, - base::TimeTicks::Now() - base::TimeDelta::FromSeconds(1)); - for (int i = 0; i < 2; ++i) { - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - } - EXPECT_EQ(1, handler.error_count()); -} - -} // namespace test -} // namespace common -} // namespace mojo diff --git a/mojo/common/time_helper.cc b/mojo/common/time_helper.cc deleted file mode 100644 index 36fd087..0000000 --- a/mojo/common/time_helper.cc +++ /dev/null @@ -1,33 +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 "mojo/common/time_helper.h" - -#include "base/time/tick_clock.h" - -namespace mojo { -namespace common { - -namespace { - -base::TickClock* tick_clock = NULL; - -} // namespace - -namespace test { - -void SetTickClockForTest(base::TickClock* clock) { - tick_clock = clock; -} -} // namespace test - -namespace internal { - -base::TimeTicks NowTicks() { - return tick_clock ? tick_clock->NowTicks() : base::TimeTicks::Now(); -} - -} // namespace internal -} // namespace common -} // namespace mojo diff --git a/mojo/common/time_helper.h b/mojo/common/time_helper.h deleted file mode 100644 index 365ae04..0000000 --- a/mojo/common/time_helper.h +++ /dev/null @@ -1,34 +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. - -#ifndef MOJO_COMMON_TIME_HELPER_H_ -#define MOJO_COMMON_TIME_HELPER_H_ - -#include "base/time/time.h" -#include "mojo/common/mojo_common_export.h" - -namespace base { -class TickClock; -} - -namespace mojo { -namespace common { -namespace test { - -// Sets the TickClock used for getting TimeTicks::Now(). This is currently used -// by both HandleWatcher and MessagePumpMojo. -MOJO_COMMON_EXPORT void SetTickClockForTest(base::TickClock* clock); - -} // namespace test - -namespace internal { - -// Returns now. Used internally; generally not useful. -MOJO_COMMON_EXPORT base::TimeTicks NowTicks(); - -} // namespace internal -} // namespace common -} // namespace mojo - -#endif // MOJO_COMMON_TIME_HELPER_H_ |