• 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 = 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