205 lines
6.1 KiB
C++
205 lines
6.1 KiB
C++
// 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/core/handle_table.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <limits>
|
|
|
|
// #include "base/trace_event/memory_dump_manager.h"
|
|
|
|
namespace mojo {
|
|
namespace core {
|
|
|
|
namespace {
|
|
|
|
// const char* GetNameForDispatcherType(Dispatcher::Type type) {
|
|
// switch (type) {
|
|
// case Dispatcher::Type::UNKNOWN:
|
|
// return "unknown";
|
|
// case Dispatcher::Type::MESSAGE_PIPE:
|
|
// return "message_pipe";
|
|
// case Dispatcher::Type::DATA_PIPE_PRODUCER:
|
|
// return "data_pipe_producer";
|
|
// case Dispatcher::Type::DATA_PIPE_CONSUMER:
|
|
// return "data_pipe_consumer";
|
|
// case Dispatcher::Type::SHARED_BUFFER:
|
|
// return "shared_buffer";
|
|
// case Dispatcher::Type::WATCHER:
|
|
// return "watcher";
|
|
// case Dispatcher::Type::PLATFORM_HANDLE:
|
|
// return "platform_handle";
|
|
// case Dispatcher::Type::INVITATION:
|
|
// return "invitation";
|
|
// }
|
|
// NOTREACHED();
|
|
// return "unknown";
|
|
// }
|
|
|
|
} // namespace
|
|
|
|
HandleTable::HandleTable() {}
|
|
|
|
HandleTable::~HandleTable() {}
|
|
|
|
base::Lock& HandleTable::GetLock() {
|
|
return lock_;
|
|
}
|
|
|
|
MojoHandle HandleTable::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
|
|
// Oops, we're out of handles.
|
|
if (next_available_handle_ == MOJO_HANDLE_INVALID)
|
|
return MOJO_HANDLE_INVALID;
|
|
|
|
MojoHandle handle = next_available_handle_++;
|
|
auto result =
|
|
handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher))));
|
|
DCHECK(result.second);
|
|
|
|
return handle;
|
|
}
|
|
|
|
bool HandleTable::AddDispatchersFromTransit(
|
|
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
|
MojoHandle* handles) {
|
|
// Oops, we're out of handles.
|
|
if (next_available_handle_ == MOJO_HANDLE_INVALID)
|
|
return false;
|
|
|
|
DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
|
|
// If this insertion would cause handle overflow, we're out of handles.
|
|
if (next_available_handle_ + dispatchers.size() < next_available_handle_)
|
|
return false;
|
|
|
|
for (size_t i = 0; i < dispatchers.size(); ++i) {
|
|
MojoHandle handle = MOJO_HANDLE_INVALID;
|
|
if (dispatchers[i].dispatcher) {
|
|
handle = next_available_handle_++;
|
|
auto result = handles_.insert(
|
|
std::make_pair(handle, Entry(dispatchers[i].dispatcher)));
|
|
DCHECK(result.second);
|
|
}
|
|
handles[i] = handle;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
|
|
auto it = handles_.find(handle);
|
|
if (it == handles_.end())
|
|
return nullptr;
|
|
return it->second.dispatcher;
|
|
}
|
|
|
|
MojoResult HandleTable::GetAndRemoveDispatcher(
|
|
MojoHandle handle,
|
|
scoped_refptr<Dispatcher>* dispatcher) {
|
|
auto it = handles_.find(handle);
|
|
if (it == handles_.end())
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
if (it->second.busy)
|
|
return MOJO_RESULT_BUSY;
|
|
|
|
*dispatcher = std::move(it->second.dispatcher);
|
|
handles_.erase(it);
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
MojoResult HandleTable::BeginTransit(
|
|
const MojoHandle* handles,
|
|
size_t num_handles,
|
|
std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
|
|
dispatchers->reserve(dispatchers->size() + num_handles);
|
|
for (size_t i = 0; i < num_handles; ++i) {
|
|
auto it = handles_.find(handles[i]);
|
|
if (it == handles_.end())
|
|
return MOJO_RESULT_INVALID_ARGUMENT;
|
|
if (it->second.busy)
|
|
return MOJO_RESULT_BUSY;
|
|
|
|
Dispatcher::DispatcherInTransit d;
|
|
d.local_handle = handles[i];
|
|
d.dispatcher = it->second.dispatcher;
|
|
if (!d.dispatcher->BeginTransit())
|
|
return MOJO_RESULT_BUSY;
|
|
it->second.busy = true;
|
|
dispatchers->push_back(d);
|
|
}
|
|
return MOJO_RESULT_OK;
|
|
}
|
|
|
|
void HandleTable::CompleteTransitAndClose(
|
|
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
|
|
for (const auto& dispatcher : dispatchers) {
|
|
auto it = handles_.find(dispatcher.local_handle);
|
|
DCHECK(it != handles_.end() && it->second.busy);
|
|
handles_.erase(it);
|
|
dispatcher.dispatcher->CompleteTransitAndClose();
|
|
}
|
|
}
|
|
|
|
void HandleTable::CancelTransit(
|
|
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
|
|
for (const auto& dispatcher : dispatchers) {
|
|
auto it = handles_.find(dispatcher.local_handle);
|
|
DCHECK(it != handles_.end() && it->second.busy);
|
|
it->second.busy = false;
|
|
dispatcher.dispatcher->CancelTransit();
|
|
}
|
|
}
|
|
|
|
void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
|
|
handles->clear();
|
|
for (const auto& entry : handles_)
|
|
handles->push_back(entry.first);
|
|
}
|
|
|
|
// MemoryDumpProvider implementation.
|
|
// bool HandleTable::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
|
|
// base::trace_event::ProcessMemoryDump* pmd) {
|
|
// // Create entries for all relevant dispatcher types to ensure they are present
|
|
// // in the final dump.
|
|
// std::map<Dispatcher::Type, int> handle_count;
|
|
// handle_count[Dispatcher::Type::MESSAGE_PIPE];
|
|
// handle_count[Dispatcher::Type::DATA_PIPE_PRODUCER];
|
|
// handle_count[Dispatcher::Type::DATA_PIPE_CONSUMER];
|
|
// handle_count[Dispatcher::Type::SHARED_BUFFER];
|
|
// handle_count[Dispatcher::Type::WATCHER];
|
|
// handle_count[Dispatcher::Type::PLATFORM_HANDLE];
|
|
// handle_count[Dispatcher::Type::INVITATION];
|
|
|
|
// // Count the number of each dispatcher type.
|
|
// {
|
|
// base::AutoLock lock(GetLock());
|
|
// for (const auto& entry : handles_) {
|
|
// ++handle_count[entry.second.dispatcher->GetType()];
|
|
// }
|
|
// }
|
|
|
|
// for (const auto& entry : handle_count) {
|
|
// base::trace_event::MemoryAllocatorDump* inner_dump =
|
|
// pmd->CreateAllocatorDump(std::string("mojo/") +
|
|
// GetNameForDispatcherType(entry.first));
|
|
// inner_dump->AddScalar(
|
|
// base::trace_event::MemoryAllocatorDump::kNameObjectCount,
|
|
// base::trace_event::MemoryAllocatorDump::kUnitsObjects, entry.second);
|
|
// }
|
|
|
|
// return true;
|
|
// }
|
|
|
|
HandleTable::Entry::Entry() {}
|
|
|
|
HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
|
|
: dispatcher(std::move(dispatcher)) {}
|
|
|
|
HandleTable::Entry::Entry(const Entry& other) = default;
|
|
|
|
HandleTable::Entry::~Entry() {}
|
|
|
|
} // namespace core
|
|
} // namespace mojo
|