// 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 #include // #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) { // 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& 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::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 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) { 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* 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& 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& 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* 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 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(std::move(dispatcher)) {} HandleTable::Entry::Entry(const Entry& other) = default; HandleTable::Entry::~Entry() {} } // namespace core } // namespace mojo