blob: ee702a88919ca04c26527ec1bf743c9ff34546bb [file] [log] [blame]
// Copyright 2015 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_MASTER_CONNECTION_MANAGER_H_
#define MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_
#include <stdint.h>
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/connection_manager.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/system_impl_export.h"
#include "mojo/public/cpp/system/macros.h"
namespace base {
class TaskRunner;
class WaitableEvent;
}
namespace mojo {
namespace embedder {
class MasterProcessDelegate;
using SlaveInfo = void*;
}
namespace system {
// The |ConnectionManager| implementation for the master process.
//
// This class is thread-safe (except that no public methods may be called from
// its internal, private thread), with condition that |Init()| be called before
// anything else and |Shutdown()| be called before destruction (and no other
// public methods may be called during/after |Shutdown()|).
class MOJO_SYSTEM_IMPL_EXPORT MasterConnectionManager final
: public ConnectionManager {
public:
// Note: None of the public methods may be called from |private_thread_|.
// |platform_support| must be valid and remain alive until after |Shutdown()|
// has completed.
explicit MasterConnectionManager(embedder::PlatformSupport* platform_support);
~MasterConnectionManager() override;
// No other methods may be called until after this has been called.
// |delegate_thread_task_runner| should be the task runner for the "delegate
// thread", on which |master_process_delegate|'s methods will be called. Both
// must stay alive at least until after |Shutdown()| has been called.
void Init(scoped_refptr<base::TaskRunner> delegate_thread_task_runner,
embedder::MasterProcessDelegate* master_process_delegate)
MOJO_NOT_THREAD_SAFE;
// Adds a slave process and sets up/tracks a connection to that slave (using
// |platform_handle|). |slave_info| is used by the caller/implementation of
// |embedder::MasterProcessDelegate| to track this process. It must remain
// alive until the delegate's |OnSlaveDisconnect()| is called with it as the
// argument. |OnSlaveDisconnect()| will always be called for each slave,
// assuming proper shutdown. Returns the process identifier for the
// newly-added slave.
ProcessIdentifier AddSlave(embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle);
// Like |AddSlave()|, but allows a connection to be bootstrapped: both the
// master and slave may call |Connect()| with |connection_id| immediately (as
// if both had already called |AllowConnect()|). |connection_id| must be
// unique (i.e., not previously used).
// TODO(vtl): Is |AddSlave()| really needed? (It's probably mostly useful for
// tests.)
ProcessIdentifier AddSlaveAndBootstrap(
embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
const ConnectionIdentifier& connection_id);
// |ConnectionManager| methods:
void Shutdown() override MOJO_NOT_THREAD_SAFE;
bool AllowConnect(const ConnectionIdentifier& connection_id) override;
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
Result Connect(const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle) override;
private:
class Helper;
// These should be thread-safe and may be called on any thread, including
// |private_thread_|:
bool AllowConnectImpl(ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id);
bool CancelConnectImpl(ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id);
Result ConnectImpl(ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
bool* is_first,
embedder::ScopedPlatformHandle* platform_handle);
// Helper for |ConnectImpl()|. This is called when the two process identifiers
// are known (and known to be valid), and all that remains is to determine the
// |Result| and provide a platform handle if appropriate. (This will never
// return |Result::FAILURE|.)
Result ConnectImplHelperNoLock(
ProcessIdentifier process_identifier,
ProcessIdentifier peer_process_identifier,
embedder::ScopedPlatformHandle* platform_handle)
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// These should only be called on |private_thread_|:
void ShutdownOnPrivateThread() MOJO_NOT_THREAD_SAFE;
// Signals |*event| on completion.
void AddSlaveOnPrivateThread(embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
ProcessIdentifier slave_process_identifier,
base::WaitableEvent* event);
// Called by |Helper::OnError()|.
void OnError(ProcessIdentifier process_identifier);
// Posts a call to |master_process_delegate_->OnSlaveDisconnect()|.
void CallOnSlaveDisconnect(embedder::SlaveInfo slave_info);
// Asserts that the current thread is *not* |private_thread_| (no-op if
// DCHECKs are not enabled). This should only be called while
// |private_thread_| is alive (i.e., after |Init()| but before |Shutdown()|).
void AssertNotOnPrivateThread() const;
// Asserts that the current thread is |private_thread_| (no-op if DCHECKs are
// not enabled). This should only be called while |private_thread_| is alive
// (i.e., after |Init()| but before |Shutdown()|).
void AssertOnPrivateThread() const;
// These are set in |Init()| before |private_thread_| exists and only cleared
// in |Shutdown()| after |private_thread_| is dead. Thus it's safe to "use" on
// |private_thread_|. (Note that |master_process_delegate_| may only be called
// from the delegate thread.)
scoped_refptr<base::TaskRunner> delegate_thread_task_runner_;
embedder::MasterProcessDelegate* master_process_delegate_;
// This is a private I/O thread on which this class does the bulk of its work.
// It is started in |Init()| and terminated in |Shutdown()|.
base::Thread private_thread_;
// The following members are only accessed on |private_thread_|:
base::hash_map<ProcessIdentifier, Helper*> helpers_; // Owns its values.
// Note: |mutex_| is not needed in the constructor, |Init()|,
// |Shutdown()|/|ShutdownOnPrivateThread()|, or the destructor
Mutex mutex_;
ProcessIdentifier next_process_identifier_ MOJO_GUARDED_BY(mutex_);
// Stores information on pending calls to |AllowConnect()|/|Connect()| (or
// |CancelConnect()|, namely those for which at least one party has called
// |AllowConnect()| but both have not yet called |Connect()| (or
// |CancelConnect()|).
struct PendingConnectInfo;
base::hash_map<ConnectionIdentifier, PendingConnectInfo*> pending_connects_
MOJO_GUARDED_BY(mutex_); // Owns its values.
// A |ProcessConnections| stores information about connections "from" a given
// (fixed, implied) process "to" other processes. A connection may be not
// present, running (meaning that both sides have connected and been given
// platform handles to a connected "pipe"), or pending (meaning that the
// "from" side must still be given a platform handle).
class ProcessConnections;
// This is a map from "from" processes to its |ProcessConnections| (above).
base::hash_map<ProcessIdentifier, ProcessConnections*> connections_
MOJO_GUARDED_BY(mutex_); // Owns its values.
MOJO_DISALLOW_COPY_AND_ASSIGN(MasterConnectionManager);
};
} // namespace system
} // namespace mojo
#endif // MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_