1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_CORE_HANDLE_TABLE_H_
#define MOJO_CORE_HANDLE_TABLE_H_
#include <stdint.h>
#include <unordered_map>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_provider.h"
#include "mojo/core/dispatcher.h"
#include "mojo/core/system_impl_export.h"
#include "mojo/public/c/system/types.h"
namespace mojo {
namespace core {
class MOJO_SYSTEM_IMPL_EXPORT HandleTable
: public base::trace_event::MemoryDumpProvider {
public:
HandleTable();
HandleTable(const HandleTable&) = delete;
HandleTable& operator=(const HandleTable&) = delete;
~HandleTable() override;
// HandleTable is thread-hostile. All access should be gated by GetLock().
base::Lock& GetLock();
MojoHandle AddDispatcher(scoped_refptr<Dispatcher> dispatcher);
// Inserts multiple dispatchers received from message transit, populating
// |handles| with their newly allocated handles. Returns |true| on success.
bool AddDispatchersFromTransit(
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
MojoHandle* handles);
scoped_refptr<Dispatcher> GetDispatcher(MojoHandle handle);
MojoResult GetAndRemoveDispatcher(MojoHandle,
scoped_refptr<Dispatcher>* dispatcher);
// Marks handles as busy and populates |dispatchers|. Returns MOJO_RESULT_BUSY
// if any of the handles are already in transit; MOJO_RESULT_INVALID_ARGUMENT
// if any of the handles are invalid; or MOJO_RESULT_OK if successful.
MojoResult BeginTransit(
const MojoHandle* handles,
size_t num_handles,
std::vector<Dispatcher::DispatcherInTransit>* dispatchers);
void CompleteTransitAndClose(
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers);
void CancelTransit(
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers);
void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);
private:
FRIEND_TEST_ALL_PREFIXES(HandleTableTest, OnMemoryDump);
// MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
struct Entry {
explicit Entry(scoped_refptr<Dispatcher> dispatcher);
~Entry();
Entry(const Entry& entry);
Entry& operator=(const Entry&) = delete;
const scoped_refptr<Dispatcher> dispatcher;
bool busy = false;
};
// A helper class for storing dispatchers that caches the last fetched
// dispatcher. This is an optimization for the common case that the same
// dispatcher is fetched repeatedly. Please see https://crbug.com/1295449 for
// more details.
class EntriesAccessor {
public:
EntriesAccessor();
~EntriesAccessor();
// Returns whether an Entry was inserted.
bool Add(MojoHandle handle, Entry entry);
// Returns nullptr if a dispatcher is not found.
const scoped_refptr<Dispatcher>* GetDispatcher(MojoHandle handle);
// Returns nullptr if an entry is not found.
Entry* GetMutable(MojoHandle handle);
// See `Remove` below.
enum RemovalCondition { kRemoveOnlyIfBusy, kRemoveOnlyIfNotBusy };
// Returns whether an entry was found, and if found, `MOJO_RESULT_BUSY` if
// `Entry.busy` is true and `MOJO_RESULT_OK` if `Entry.busy` is false. If an
// entry is not found, `MOJO_RESULT_NOT_FOUND` is returned.
//
// If an entry is found, and if `removal_condition` matches `Entry.busy`, it
// is removed from storage and -- if `dispatcher` is not nullptr -- the
// corresponding dispatcher is returned in `dispatcher`. Otherwise,
// `dispatcher` is left unchanged.
MojoResult Remove(MojoHandle handle,
RemovalCondition removal_condition,
scoped_refptr<Dispatcher>* dispatcher);
const std::unordered_map<MojoHandle, Entry>& GetUnderlyingMap() const;
private:
std::unordered_map<MojoHandle, Entry> handles_;
scoped_refptr<Dispatcher> last_read_dispatcher_;
MojoHandle last_read_handle_ = MOJO_HANDLE_INVALID;
};
EntriesAccessor entries_;
base::Lock lock_;
uintptr_t next_available_handle_ = 1;
};
} // namespace core
} // namespace mojo
#endif // MOJO_CORE_HANDLE_TABLE_H_
|