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 =
25 handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher))));
26 DCHECK(result.second);
27
28 return handle;
29 }
30
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)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
GetDispatcher(MojoHandle handle) const54 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
GetAndRemoveDispatcher(MojoHandle handle,scoped_refptr<Dispatcher> * dispatcher)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
BeginTransit(const MojoHandle * handles,uint32_t num_handles,std::vector<Dispatcher::DispatcherInTransit> * dispatchers)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
CompleteTransitAndClose(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)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
CancelTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)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
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)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
Entry()125 HandleTable::Entry::Entry() {}
126
Entry(scoped_refptr<Dispatcher> dispatcher)127 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
128 : dispatcher(std::move(dispatcher)) {}
129
130 HandleTable::Entry::Entry(const Entry& other) = default;
131
~Entry()132 HandleTable::Entry::~Entry() {}
133
134 } // namespace edk
135 } // namespace mojo
136