• 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/core/handle_table.h"
6 
7 #include <stdint.h>
8 
9 #include <limits>
10 
11 // #include "base/trace_event/memory_dump_manager.h"
12 
13 namespace mojo {
14 namespace core {
15 
16 namespace {
17 
18 // const char* GetNameForDispatcherType(Dispatcher::Type type) {
19 //   switch (type) {
20 //     case Dispatcher::Type::UNKNOWN:
21 //       return "unknown";
22 //     case Dispatcher::Type::MESSAGE_PIPE:
23 //       return "message_pipe";
24 //     case Dispatcher::Type::DATA_PIPE_PRODUCER:
25 //       return "data_pipe_producer";
26 //     case Dispatcher::Type::DATA_PIPE_CONSUMER:
27 //       return "data_pipe_consumer";
28 //     case Dispatcher::Type::SHARED_BUFFER:
29 //       return "shared_buffer";
30 //     case Dispatcher::Type::WATCHER:
31 //       return "watcher";
32 //     case Dispatcher::Type::PLATFORM_HANDLE:
33 //       return "platform_handle";
34 //     case Dispatcher::Type::INVITATION:
35 //       return "invitation";
36 //   }
37 //   NOTREACHED();
38 //   return "unknown";
39 // }
40 
41 }  // namespace
42 
HandleTable()43 HandleTable::HandleTable() {}
44 
~HandleTable()45 HandleTable::~HandleTable() {}
46 
GetLock()47 base::Lock& HandleTable::GetLock() {
48   return lock_;
49 }
50 
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)51 MojoHandle HandleTable::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
52   // Oops, we're out of handles.
53   if (next_available_handle_ == MOJO_HANDLE_INVALID)
54     return MOJO_HANDLE_INVALID;
55 
56   MojoHandle handle = next_available_handle_++;
57   auto result =
58       handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher))));
59   DCHECK(result.second);
60 
61   return handle;
62 }
63 
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)64 bool HandleTable::AddDispatchersFromTransit(
65     const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
66     MojoHandle* handles) {
67   // Oops, we're out of handles.
68   if (next_available_handle_ == MOJO_HANDLE_INVALID)
69     return false;
70 
71   DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
72   // If this insertion would cause handle overflow, we're out of handles.
73   if (next_available_handle_ + dispatchers.size() < next_available_handle_)
74     return false;
75 
76   for (size_t i = 0; i < dispatchers.size(); ++i) {
77     MojoHandle handle = MOJO_HANDLE_INVALID;
78     if (dispatchers[i].dispatcher) {
79       handle = next_available_handle_++;
80       auto result = handles_.insert(
81           std::make_pair(handle, Entry(dispatchers[i].dispatcher)));
82       DCHECK(result.second);
83     }
84     handles[i] = handle;
85   }
86 
87   return true;
88 }
89 
GetDispatcher(MojoHandle handle) const90 scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
91   auto it = handles_.find(handle);
92   if (it == handles_.end())
93     return nullptr;
94   return it->second.dispatcher;
95 }
96 
GetAndRemoveDispatcher(MojoHandle handle,scoped_refptr<Dispatcher> * dispatcher)97 MojoResult HandleTable::GetAndRemoveDispatcher(
98     MojoHandle handle,
99     scoped_refptr<Dispatcher>* dispatcher) {
100   auto it = handles_.find(handle);
101   if (it == handles_.end())
102     return MOJO_RESULT_INVALID_ARGUMENT;
103   if (it->second.busy)
104     return MOJO_RESULT_BUSY;
105 
106   *dispatcher = std::move(it->second.dispatcher);
107   handles_.erase(it);
108   return MOJO_RESULT_OK;
109 }
110 
BeginTransit(const MojoHandle * handles,size_t num_handles,std::vector<Dispatcher::DispatcherInTransit> * dispatchers)111 MojoResult HandleTable::BeginTransit(
112     const MojoHandle* handles,
113     size_t num_handles,
114     std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
115   dispatchers->reserve(dispatchers->size() + num_handles);
116   for (size_t i = 0; i < num_handles; ++i) {
117     auto it = handles_.find(handles[i]);
118     if (it == handles_.end())
119       return MOJO_RESULT_INVALID_ARGUMENT;
120     if (it->second.busy)
121       return MOJO_RESULT_BUSY;
122 
123     Dispatcher::DispatcherInTransit d;
124     d.local_handle = handles[i];
125     d.dispatcher = it->second.dispatcher;
126     if (!d.dispatcher->BeginTransit())
127       return MOJO_RESULT_BUSY;
128     it->second.busy = true;
129     dispatchers->push_back(d);
130   }
131   return MOJO_RESULT_OK;
132 }
133 
CompleteTransitAndClose(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)134 void HandleTable::CompleteTransitAndClose(
135     const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
136   for (const auto& dispatcher : dispatchers) {
137     auto it = handles_.find(dispatcher.local_handle);
138     DCHECK(it != handles_.end() && it->second.busy);
139     handles_.erase(it);
140     dispatcher.dispatcher->CompleteTransitAndClose();
141   }
142 }
143 
CancelTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)144 void HandleTable::CancelTransit(
145     const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
146   for (const auto& dispatcher : dispatchers) {
147     auto it = handles_.find(dispatcher.local_handle);
148     DCHECK(it != handles_.end() && it->second.busy);
149     it->second.busy = false;
150     dispatcher.dispatcher->CancelTransit();
151   }
152 }
153 
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)154 void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
155   handles->clear();
156   for (const auto& entry : handles_)
157     handles->push_back(entry.first);
158 }
159 
160 // MemoryDumpProvider implementation.
161 // bool HandleTable::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
162 //                                base::trace_event::ProcessMemoryDump* pmd) {
163 //   // Create entries for all relevant dispatcher types to ensure they are present
164 //   // in the final dump.
165 //   std::map<Dispatcher::Type, int> handle_count;
166 //   handle_count[Dispatcher::Type::MESSAGE_PIPE];
167 //   handle_count[Dispatcher::Type::DATA_PIPE_PRODUCER];
168 //   handle_count[Dispatcher::Type::DATA_PIPE_CONSUMER];
169 //   handle_count[Dispatcher::Type::SHARED_BUFFER];
170 //   handle_count[Dispatcher::Type::WATCHER];
171 //   handle_count[Dispatcher::Type::PLATFORM_HANDLE];
172 //   handle_count[Dispatcher::Type::INVITATION];
173 
174 //   // Count the number of each dispatcher type.
175 //   {
176 //     base::AutoLock lock(GetLock());
177 //     for (const auto& entry : handles_) {
178 //       ++handle_count[entry.second.dispatcher->GetType()];
179 //     }
180 //   }
181 
182 //   for (const auto& entry : handle_count) {
183 //     base::trace_event::MemoryAllocatorDump* inner_dump =
184 //         pmd->CreateAllocatorDump(std::string("mojo/") +
185 //                                  GetNameForDispatcherType(entry.first));
186 //     inner_dump->AddScalar(
187 //         base::trace_event::MemoryAllocatorDump::kNameObjectCount,
188 //         base::trace_event::MemoryAllocatorDump::kUnitsObjects, entry.second);
189 //   }
190 
191 //   return true;
192 // }
193 
Entry()194 HandleTable::Entry::Entry() {}
195 
Entry(scoped_refptr<Dispatcher> dispatcher)196 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
197     : dispatcher(std::move(dispatcher)) {}
198 
199 HandleTable::Entry::Entry(const Entry& other) = default;
200 
~Entry()201 HandleTable::Entry::~Entry() {}
202 
203 }  // namespace core
204 }  // namespace mojo
205