1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/edk/system/handle_table.h" 6 7 #include <stdint.h> 8 9 #include <limits> 10 11 namespace mojo { 12 namespace edk { 13 14 HandleTable::HandleTable() {} 15 16 HandleTable::~HandleTable() {} 17 18 MojoHandle HandleTable::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) { 19 // Oops, we're out of handles. 20 if (next_available_handle_ == MOJO_HANDLE_INVALID) 21 return MOJO_HANDLE_INVALID; 22 23 MojoHandle handle = next_available_handle_++; 24 auto result = 25 handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher)))); 26 DCHECK(result.second); 27 28 return handle; 29 } 30 31 bool HandleTable::AddDispatchersFromTransit( 32 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers, 33 MojoHandle* handles) { 34 // Oops, we're out of handles. 35 if (next_available_handle_ == MOJO_HANDLE_INVALID) 36 return false; 37 38 DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max()); 39 // If this insertion would cause handle overflow, we're out of handles. 40 if (next_available_handle_ + dispatchers.size() < next_available_handle_) 41 return false; 42 43 for (size_t i = 0; i < dispatchers.size(); ++i) { 44 MojoHandle handle = next_available_handle_++; 45 auto result = handles_.insert( 46 std::make_pair(handle, Entry(dispatchers[i].dispatcher))); 47 DCHECK(result.second); 48 handles[i] = handle; 49 } 50 51 return true; 52 } 53 54 scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const { 55 auto it = handles_.find(handle); 56 if (it == handles_.end()) 57 return nullptr; 58 return it->second.dispatcher; 59 } 60 61 MojoResult HandleTable::GetAndRemoveDispatcher( 62 MojoHandle handle, 63 scoped_refptr<Dispatcher>* dispatcher) { 64 auto it = handles_.find(handle); 65 if (it == handles_.end()) 66 return MOJO_RESULT_INVALID_ARGUMENT; 67 if (it->second.busy) 68 return MOJO_RESULT_BUSY; 69 70 *dispatcher = std::move(it->second.dispatcher); 71 handles_.erase(it); 72 return MOJO_RESULT_OK; 73 } 74 75 MojoResult HandleTable::BeginTransit( 76 const MojoHandle* handles, 77 uint32_t num_handles, 78 std::vector<Dispatcher::DispatcherInTransit>* dispatchers) { 79 dispatchers->clear(); 80 dispatchers->reserve(num_handles); 81 for (size_t i = 0; i < num_handles; ++i) { 82 auto it = handles_.find(handles[i]); 83 if (it == handles_.end()) 84 return MOJO_RESULT_INVALID_ARGUMENT; 85 if (it->second.busy) 86 return MOJO_RESULT_BUSY; 87 88 Dispatcher::DispatcherInTransit d; 89 d.local_handle = handles[i]; 90 d.dispatcher = it->second.dispatcher; 91 if (!d.dispatcher->BeginTransit()) 92 return MOJO_RESULT_BUSY; 93 it->second.busy = true; 94 dispatchers->push_back(d); 95 } 96 return MOJO_RESULT_OK; 97 } 98 99 void HandleTable::CompleteTransitAndClose( 100 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) { 101 for (const auto& dispatcher : dispatchers) { 102 auto it = handles_.find(dispatcher.local_handle); 103 DCHECK(it != handles_.end() && it->second.busy); 104 handles_.erase(it); 105 dispatcher.dispatcher->CompleteTransitAndClose(); 106 } 107 } 108 109 void HandleTable::CancelTransit( 110 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) { 111 for (const auto& dispatcher : dispatchers) { 112 auto it = handles_.find(dispatcher.local_handle); 113 DCHECK(it != handles_.end() && it->second.busy); 114 it->second.busy = false; 115 dispatcher.dispatcher->CancelTransit(); 116 } 117 } 118 119 void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) { 120 handles->clear(); 121 for (const auto& entry : handles_) 122 handles->push_back(entry.first); 123 } 124 125 HandleTable::Entry::Entry() {} 126 127 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher) 128 : dispatcher(std::move(dispatcher)) {} 129 130 HandleTable::Entry::Entry(const Entry& other) = default; 131 132 HandleTable::Entry::~Entry() {} 133 134 } // namespace edk 135 } // namespace mojo 136