| // 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_CHANNEL_MANAGER_H_ |
| #define MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_ |
| |
| #include <stdint.h> |
| |
| #include <unordered_map> |
| |
| #include "base/callback_forward.h" |
| #include "mojo/edk/embedder/platform_task_runner.h" |
| #include "mojo/edk/embedder/scoped_platform_handle.h" |
| #include "mojo/edk/system/channel_id.h" |
| #include "mojo/edk/util/mutex.h" |
| #include "mojo/edk/util/ref_ptr.h" |
| #include "mojo/edk/util/thread_annotations.h" |
| #include "mojo/public/cpp/system/macros.h" |
| |
| namespace base { |
| class TaskRunner; |
| } |
| |
| namespace mojo { |
| |
| namespace embedder { |
| class PlatformSupport; |
| } |
| |
| namespace system { |
| |
| class Channel; |
| class ChannelEndpoint; |
| class ConnectionManager; |
| class MessagePipeDispatcher; |
| |
| // This class manages and "owns" |Channel|s (which typically connect to other |
| // processes) for a given process. This class is thread-safe, except as |
| // specifically noted. |
| class ChannelManager { |
| public: |
| // |io_thread_task_runner| should be the |TaskRunner| for the I/O thread, on |
| // which this channel manager will create all channels. Connection manager is |
| // optional and may be null. All arguments (if non-null) must remain alive at |
| // least until after shutdown completion. |
| ChannelManager(embedder::PlatformSupport* platform_support, |
| embedder::PlatformTaskRunnerRefPtr io_thread_task_runner, |
| ConnectionManager* connection_manager); |
| ~ChannelManager(); |
| |
| // Shuts down the channel manager, including shutting down all channels (as if |
| // |ShutdownChannelOnIOThread()| were called for each channel). This must be |
| // called from the I/O thread (given to the constructor) and completes |
| // synchronously. This, or |Shutdown()|, must be called before destroying this |
| // object. |
| void ShutdownOnIOThread(); |
| |
| // Like |ShutdownOnIOThread()|, but may be called from any thread. On |
| // completion, will call |callback| ("on" |io_thread_task_runner| if |
| // |callback_thread_task_runner| is null else by posted using |
| // |callback_thread_task_runner|). Note: This will always post a task to the |
| // I/O thread, even it is the current thread. |
| // TODO(vtl): Consider if this is really necessary, since it only has one use |
| // (in tests). |
| void Shutdown(const base::Closure& callback, |
| embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner); |
| |
| // Creates a |Channel| and adds it to the set of channels managed by this |
| // |ChannelManager|. This must be called from the I/O thread (given to the |
| // constructor). |channel_id| should be a valid |ChannelId| (i.e., nonzero) |
| // not "assigned" to any other |Channel| being managed by this |
| // |ChannelManager|. |
| util::RefPtr<MessagePipeDispatcher> CreateChannelOnIOThread( |
| ChannelId channel_id, |
| embedder::ScopedPlatformHandle platform_handle); |
| |
| // Like |CreateChannelOnIOThread()|, but doesn't create a bootstrap message |
| // pipe. Returns the newly-created |Channel|. |
| // TODO(vtl): Maybe get rid of the others (and bootstrap message pipes in |
| // general). |
| util::RefPtr<Channel> CreateChannelWithoutBootstrapOnIOThread( |
| ChannelId channel_id, |
| embedder::ScopedPlatformHandle platform_handle); |
| |
| // Like |CreateChannelOnIOThread()|, but may be called from any thread. On |
| // completion, will call |callback| (using |callback_thread_task_runner| if it |
| // is non-null, else on the I/O thread). Note: This will always post a task to |
| // the I/O thread, even if called from that thread. |
| util::RefPtr<MessagePipeDispatcher> CreateChannel( |
| ChannelId channel_id, |
| embedder::ScopedPlatformHandle platform_handle, |
| const base::Closure& callback, |
| embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner); |
| |
| // Gets the |Channel| with the given ID (which must exist). |
| util::RefPtr<Channel> GetChannel(ChannelId channel_id) const; |
| |
| // Informs the channel manager (and thus channel) that it will be shutdown |
| // soon (by calling |ShutdownChannel()|). Calling this is optional (and may in |
| // fact be called multiple times) but it will suppress certain warnings (e.g., |
| // for the channel being broken) and enable others (if messages are written to |
| // the channel). |
| void WillShutdownChannel(ChannelId channel_id); |
| |
| // Shuts down the channel specified by the given ID. This, or |
| // |ShutdownChannel()|, should be called once per channel (created using |
| // |CreateChannelOnIOThread()| or |CreateChannel()|). This must be called from |
| // the I/O thread. |
| void ShutdownChannelOnIOThread(ChannelId channel_id); |
| |
| // Like |ShutdownChannelOnIOThread()|, but may be called from any thread. It |
| // will always post a task to the I/O thread, and post |callback| to |
| // |callback_thread_task_runner| (or execute it directly on the I/O thread if |
| // |callback_thread_task_runner| is null) on completion. |
| void ShutdownChannel( |
| ChannelId channel_id, |
| const base::Closure& callback, |
| embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner); |
| |
| ConnectionManager* connection_manager() const { return connection_manager_; } |
| |
| private: |
| // Used by |Shutdown()|. Called on the I/O thread. |
| void ShutdownHelper( |
| const base::Closure& callback, |
| embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner); |
| |
| // Used by |CreateChannelOnIOThread()| and |CreateChannelHelper()|. Called on |
| // the I/O thread. |bootstrap_channel_endpoint| is optional and may be null. |
| // Returns the newly-created |Channel|. |
| util::RefPtr<Channel> CreateChannelOnIOThreadHelper( |
| ChannelId channel_id, |
| embedder::ScopedPlatformHandle platform_handle, |
| util::RefPtr<ChannelEndpoint>&& bootstrap_channel_endpoint); |
| |
| // Used by |CreateChannel()|. Called on the I/O thread. |
| // TODO(vtl): |bootstrap_channel_endpoint| should be an rvalue reference, but |
| // that doesn't currently work correctly with base::Bind. |
| void CreateChannelHelper( |
| ChannelId channel_id, |
| embedder::ScopedPlatformHandle platform_handle, |
| util::RefPtr<ChannelEndpoint> bootstrap_channel_endpoint, |
| const base::Closure& callback, |
| embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner); |
| |
| // Note: These must not be used after shutdown. |
| embedder::PlatformSupport* const platform_support_; |
| const embedder::PlatformTaskRunnerRefPtr io_thread_task_runner_; |
| ConnectionManager* const connection_manager_; |
| |
| // Note: |Channel| methods should not be called under |mutex_|. |
| // TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|, |
| // once clang actually checks such annotations. |
| // https://github.com/domokit/mojo/issues/313 |
| mutable util::Mutex mutex_; |
| |
| using ChannelIdToChannelMap = |
| std::unordered_map<ChannelId, util::RefPtr<Channel>>; |
| ChannelIdToChannelMap channels_ MOJO_GUARDED_BY(mutex_); |
| |
| MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManager); |
| }; |
| |
| } // namespace system |
| } // namespace mojo |
| |
| #endif // MOJO_EDK_SYSTEM_CHANNEL_MANAGER_H_ |