Home | History | Annotate | Download | only in system
      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 
     14 HandleTable::HandleTable() {}
     15 
     16 HandleTable::~HandleTable() {}
     17 
     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 
     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 
     54 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 
     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 
     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 
     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 
    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 
    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 
    125 HandleTable::Entry::Entry() {}
    126 
    127 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
    128     : dispatcher(std::move(dispatcher)) {}
    129 
    130 HandleTable::Entry::Entry(const Entry& other) = default;
    131 
    132 HandleTable::Entry::~Entry() {}
    133 
    134 }  // namespace edk
    135 }  // namespace mojo
    136