blob: 25f1037b9fb9761cf80389d260d88ab3cca25c61 [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/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/connection_manager.h"
namespace base {
class TaskRunner;
class WaitableEvent;
}
namespace mojo {
namespace embedder {
class MasterProcessDelegate;
class SlaveInfo;
}
namespace system {
// The |ConnectionManager| implementation for the master process.
//
// Objects of this class must be created, initialized (via |Init()|), shut down
// (via |Shutdown()|), and destroyed on the same thread (the "creation thread").
// Otherwise, its public methods are thread-safe (except that they may not be
// called from its internal, private thread).
class MasterConnectionManager : public ConnectionManager {
public:
// Note: None of the public methods may be called from |private_thread_|.
MasterConnectionManager();
~MasterConnectionManager() override;
// No other methods may be called until after this has been called.
// |master_process_delegate| must stay alive at least until after |Shutdown()|
// has been called; its methods will be called on this object's creation
// thread.
void Init(embedder::MasterProcessDelegate* master_process_delegate);
// No other methods may be called after this is (or while it is being) called.
void Shutdown();
// 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; ownership of
// |slave_info| will be returned to the delegate via |OnSlaveDisconnect()|,
// which will always be called for each slave, assuming proper shutdown.)
void AddSlave(scoped_ptr<embedder::SlaveInfo> slave_info,
embedder::ScopedPlatformHandle platform_handle);
// |ConnectionManager| methods:
bool AllowConnect(const ConnectionIdentifier& connection_id) override;
bool CancelConnect(const ConnectionIdentifier& connection_id) override;
bool Connect(const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
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);
bool ConnectImpl(ProcessIdentifier process_identifier,
const ConnectionIdentifier& connection_id,
ProcessIdentifier* peer_process_identifier,
embedder::ScopedPlatformHandle* platform_handle);
// These should only be called on |private_thread_|:
void ShutdownOnPrivateThread();
// Signals |*event| on completion.
void AddSlaveOnPrivateThread(scoped_ptr<embedder::SlaveInfo> slave_info,
embedder::ScopedPlatformHandle platform_handle,
base::WaitableEvent* event);
// Called by |Helper::OnError()|.
void OnError(ProcessIdentifier process_identifier);
// Posts a call to |master_process_delegate_->OnSlaveDisconnect()|.
void CallOnSlaveDisconnect(scoped_ptr<embedder::SlaveInfo> slave_info);
// Asserts that the current thread is the creation thread. (This actually
// checks the current message loop, which is what we depend on, not the thread
// per se.)
void AssertOnCreationThread() const;
// 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;
const scoped_refptr<base::TaskRunner> creation_thread_task_runner_;
// This is 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 creation thread.)
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_|:
ProcessIdentifier next_process_identifier_;
base::hash_map<ProcessIdentifier, Helper*> helpers_; // Owns its values.
// Protects the members below (except in the constructor, |Init()|,
// |Shutdown()|/|ShutdownOnPrivateThread()|, and the destructor).
base::Lock lock_;
struct PendingConnectionInfo;
base::hash_map<ConnectionIdentifier, PendingConnectionInfo*>
pending_connections_; // Owns its values.
DISALLOW_COPY_AND_ASSIGN(MasterConnectionManager);
};
} // namespace system
} // namespace mojo
#endif // MOJO_EDK_SYSTEM_MASTER_CONNECTION_MANAGER_H_