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
HandleTable()14 HandleTable::HandleTable() {}
15
~HandleTable()16 HandleTable::~HandleTable() {}
17
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)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 = handles_.insert(std::make_pair(handle, Entry(dispatcher)));
25 DCHECK(result.second);
26
27 return handle;
28 }
29
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)30 bool HandleTable::AddDispatchersFromTransit(
31 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
32 MojoHandle* handles) {
33 // Oops, we're out of handles.
34 if (next_available_handle_ == MOJO_HANDLE_INVALID)
35 return false;
36
37 DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
38 // If this insertion would cause handle overflow, we're out of handles.
39 if (next_available_handle_ + dispatchers.size() < next_available_handle_)
40 return false;
41
42 for (size_t i = 0; i < dispatchers.size(); ++i) {
43 MojoHandle handle = next_available_handle_++;
44 auto result = handles_.insert(
45 std::make_pair(handle, Entry(dispatchers[i].dispatcher)));
46 DCHECK(result.second);
47 handles[i] = handle;
48 }
49
50 return true;
51 }
52
GetDispatcher(MojoHandle handle) const53 scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
54 auto it = handles_.find(handle);
55 if (it == handles_.end())
56 return nullptr;
57 return it->second.dispatcher;
58 }
59
GetAndRemoveDispatcher(MojoHandle handle,scoped_refptr<Dispatcher> * dispatcher)60 MojoResult HandleTable::GetAndRemoveDispatcher(
61 MojoHandle handle,
62 scoped_refptr<Dispatcher>* dispatcher) {
63 auto it = handles_.find(handle);
64 if (it == handles_.end())
65 return MOJO_RESULT_INVALID_ARGUMENT;
66 if (it->second.busy)
67 return MOJO_RESULT_BUSY;
68
69 *dispatcher = it->second.dispatcher;
70 handles_.erase(it);
71 return MOJO_RESULT_OK;
72 }
73
BeginTransit(const MojoHandle * handles,uint32_t num_handles,std::vector<Dispatcher::DispatcherInTransit> * dispatchers)74 MojoResult HandleTable::BeginTransit(
75 const MojoHandle* handles,
76 uint32_t num_handles,
77 std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
78 dispatchers->clear();
79 dispatchers->reserve(num_handles);
80 for (size_t i = 0; i < num_handles; ++i) {
81 auto it = handles_.find(handles[i]);
82 if (it == handles_.end())
83 return MOJO_RESULT_INVALID_ARGUMENT;
84 if (it->second.busy)
85 return MOJO_RESULT_BUSY;
86
87 Dispatcher::DispatcherInTransit d;
88 d.local_handle = handles[i];
89 d.dispatcher = it->second.dispatcher;
90 if (!d.dispatcher->BeginTransit())
91 return MOJO_RESULT_BUSY;
92 it->second.busy = true;
93 dispatchers->push_back(d);
94 }
95 return MOJO_RESULT_OK;
96 }
97
CompleteTransitAndClose(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)98 void HandleTable::CompleteTransitAndClose(
99 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
100 for (const auto& dispatcher : dispatchers) {
101 auto it = handles_.find(dispatcher.local_handle);
102 DCHECK(it != handles_.end() && it->second.busy);
103 handles_.erase(it);
104 dispatcher.dispatcher->CompleteTransitAndClose();
105 }
106 }
107
CancelTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)108 void HandleTable::CancelTransit(
109 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
110 for (const auto& dispatcher : dispatchers) {
111 auto it = handles_.find(dispatcher.local_handle);
112 DCHECK(it != handles_.end() && it->second.busy);
113 it->second.busy = false;
114 dispatcher.dispatcher->CancelTransit();
115 }
116 }
117
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)118 void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
119 handles->clear();
120 for (const auto& entry : handles_)
121 handles->push_back(entry.first);
122 }
123
Entry()124 HandleTable::Entry::Entry() {}
125
Entry(scoped_refptr<Dispatcher> dispatcher)126 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
127 : dispatcher(dispatcher) {}
128
129 HandleTable::Entry::Entry(const Entry& other) = default;
130
~Entry()131 HandleTable::Entry::~Entry() {}
132
133 } // namespace edk
134 } // namespace mojo
135