Backed out changeset 8d9053f1c203 (bug 1942129) Backed out changeset 393e3c507c27 (bug 1942129) Backed out changeset 8240d353d224 (bug 1942129) Backed out changeset 8c4cd026b720 (bug 1942129) Backed out changeset 742634b0d6e9 (bug 1942129) Backed out changeset d16857f9812f (bug 1942129) Backed out changeset 7ff7af041ee7 (bug 1942129) Backed out changeset ef41d9e4c7de (bug 1942129)
225 lines
7.2 KiB
C++
225 lines
7.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef dom_ipc_SharedStringMap_h
|
|
#define dom_ipc_SharedStringMap_h
|
|
|
|
#include "mozilla/Result.h"
|
|
#include "mozilla/dom/ipc/StringTable.h"
|
|
#include "mozilla/ipc/SharedMemory.h"
|
|
#include "nsTHashMap.h"
|
|
|
|
namespace mozilla::dom::ipc {
|
|
|
|
class SharedStringMapBuilder;
|
|
|
|
/**
|
|
* This class provides a simple, read-only key-value string store, with all
|
|
* data packed into a single segment of memory, which can be shared between
|
|
* processes.
|
|
*
|
|
* Look-ups are performed by binary search of a static table in the mapped
|
|
* memory region, and all returned strings are literals which reference the
|
|
* mapped data. No copies are performed on instantiation or look-up.
|
|
*
|
|
* Important: The mapped memory created by this class is persistent. Once an
|
|
* instance has been initialized, the memory that it allocates can never be
|
|
* freed before process shutdown. Do not use it for short-lived mappings.
|
|
*/
|
|
class SharedStringMap {
|
|
public:
|
|
/**
|
|
* The header at the beginning of the shared memory region describing its
|
|
* layout. The layout of the shared memory is as follows:
|
|
*
|
|
* - Header:
|
|
* A Header struct describing the contents of the rest of the memory region.
|
|
*
|
|
* - Optional alignment padding for Header[].
|
|
*
|
|
* - Entry[header.mEntryCount]:
|
|
* An array of Entry structs, one for each entry in the map. Entries are
|
|
* lexocographically sorted by key.
|
|
*
|
|
* - StringTable<nsCString>:
|
|
* A region of flat, null-terminated C strings. Entry key strings are
|
|
* encoded as character offsets into this region.
|
|
*
|
|
* - Optional alignment padding for char16_t[]
|
|
*
|
|
* - StringTable<nsString>:
|
|
* A region of flat, null-terminated UTF-16 strings. Entry value strings are
|
|
* encoded as character (*not* byte) offsets into this region.
|
|
*/
|
|
struct Header {
|
|
uint32_t mMagic;
|
|
// The number of entries in this map.
|
|
uint32_t mEntryCount;
|
|
|
|
// The raw byte offset of the beginning of the key string table, from the
|
|
// start of the shared memory region, and its size in bytes.
|
|
size_t mKeyStringsOffset;
|
|
size_t mKeyStringsSize;
|
|
|
|
// The raw byte offset of the beginning of the value string table, from the
|
|
// start of the shared memory region, and its size in bytes (*not*
|
|
// characters).
|
|
size_t mValueStringsOffset;
|
|
size_t mValueStringsSize;
|
|
};
|
|
|
|
/**
|
|
* Describes a value in the string map, as offsets into the key and value
|
|
* string tables.
|
|
*/
|
|
struct Entry {
|
|
// The offset and size of the entry's UTF-8 key in the key string table.
|
|
StringTableEntry mKey;
|
|
// The offset and size of the entry's UTF-16 value in the value string
|
|
// table.
|
|
StringTableEntry mValue;
|
|
};
|
|
|
|
NS_INLINE_DECL_REFCOUNTING(SharedStringMap)
|
|
|
|
// Note: These constructors are infallible on the premise that this class
|
|
// is used primarily in cases where it is critical to platform
|
|
// functionality.
|
|
explicit SharedStringMap(const mozilla::ipc::SharedMemoryHandle&, size_t);
|
|
explicit SharedStringMap(SharedStringMapBuilder&&);
|
|
|
|
/**
|
|
* Searches for the given value in the map, and returns true if it exists.
|
|
*/
|
|
bool Has(const nsCString& aKey);
|
|
|
|
/**
|
|
* Searches for the given value in the map, and, if it exists, returns true
|
|
* and places its value in aValue.
|
|
*
|
|
* The returned value is a literal string which references the mapped memory
|
|
* region.
|
|
*/
|
|
bool Get(const nsCString& aKey, nsAString& aValue);
|
|
|
|
private:
|
|
/**
|
|
* Searches for an entry for the given key. If found, returns true, and
|
|
* places its index in the entry array in aIndex.
|
|
*/
|
|
bool Find(const nsCString& aKey, size_t* aIndex);
|
|
|
|
public:
|
|
/**
|
|
* Returns the number of entries in the map.
|
|
*/
|
|
uint32_t Count() const { return EntryCount(); }
|
|
|
|
/**
|
|
* Returns the string entry at the given index. Keys are guaranteed to be
|
|
* sorted lexographically.
|
|
*
|
|
* The given index *must* be less than the value returned by Count().
|
|
*
|
|
* The returned value is a literal string which references the mapped memory
|
|
* region.
|
|
*/
|
|
nsCString GetKeyAt(uint32_t aIndex) const {
|
|
MOZ_ASSERT(aIndex < Count());
|
|
return KeyTable().Get(Entries()[aIndex].mKey);
|
|
}
|
|
|
|
/**
|
|
* Returns the string value for the entry at the given index.
|
|
*
|
|
* The given index *must* be less than the value returned by Count().
|
|
*
|
|
* The returned value is a literal string which references the mapped memory
|
|
* region.
|
|
*/
|
|
nsString GetValueAt(uint32_t aIndex) const {
|
|
MOZ_ASSERT(aIndex < Count());
|
|
return ValueTable().Get(Entries()[aIndex].mValue);
|
|
}
|
|
|
|
/**
|
|
* Returns a copy of the read-only shared memory handle which backs the shared
|
|
* memory region for this map. The handle may be passed between processes, and
|
|
* used to construct new instances of SharedStringMap with the same data as
|
|
* this instance.
|
|
*/
|
|
mozilla::ipc::SharedMemoryHandle CloneHandle() const;
|
|
|
|
size_t MapSize() const { return mMappedMemory.size(); }
|
|
|
|
protected:
|
|
~SharedStringMap() = default;
|
|
|
|
private:
|
|
// Type-safe getters for values in the shared memory region:
|
|
const Header& GetHeader() const {
|
|
return *reinterpret_cast<const Header*>(mMappedMemory.data());
|
|
}
|
|
|
|
RangedPtr<const Entry> Entries() const {
|
|
return {reinterpret_cast<const Entry*>(&GetHeader() + 1), EntryCount()};
|
|
}
|
|
|
|
uint32_t EntryCount() const { return GetHeader().mEntryCount; }
|
|
|
|
StringTable<nsCString> KeyTable() const {
|
|
const auto& header = GetHeader();
|
|
return {{&mMappedMemory.data()[header.mKeyStringsOffset],
|
|
header.mKeyStringsSize}};
|
|
}
|
|
|
|
StringTable<nsString> ValueTable() const {
|
|
const auto& header = GetHeader();
|
|
return {{&mMappedMemory.data()[header.mValueStringsOffset],
|
|
header.mValueStringsSize}};
|
|
}
|
|
|
|
mozilla::ipc::SharedMemoryHandle mHandle;
|
|
// This is a leaked shared memory mapping (see the constructor definition for
|
|
// an explanation). It replaces AutoMemMap::setPersistent behavior as part of
|
|
// bug 1454816.
|
|
Span<uint8_t> mMappedMemory;
|
|
};
|
|
|
|
/**
|
|
* A helper class which builds the contiguous look-up table used by
|
|
* SharedStringMap. Each key-value pair in the final map is added to the
|
|
* builder, before it is finalized and transformed into a snapshot.
|
|
*/
|
|
class MOZ_RAII SharedStringMapBuilder {
|
|
public:
|
|
SharedStringMapBuilder() = default;
|
|
|
|
/**
|
|
* Adds a key-value pair to the map.
|
|
*/
|
|
void Add(const nsCString& aKey, const nsString& aValue);
|
|
|
|
/**
|
|
* Finalizes the binary representation of the map, writes it to a shared
|
|
* memory region, and then initializes the given SharedMemory with a reference
|
|
* to the read-only copy of it.
|
|
*/
|
|
Result<Ok, nsresult> Finalize(RefPtr<mozilla::ipc::SharedMemory>& aMap);
|
|
|
|
private:
|
|
using Entry = SharedStringMap::Entry;
|
|
|
|
StringTableBuilder<nsCStringHashKey, nsCString> mKeyTable;
|
|
StringTableBuilder<nsStringHashKey, nsString> mValueTable;
|
|
|
|
nsTHashMap<nsCStringHashKey, Entry> mEntries;
|
|
};
|
|
|
|
} // namespace mozilla::dom::ipc
|
|
|
|
#endif // dom_ipc_SharedStringMap_h
|