• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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