forked from mirrors/gecko-dev
This class implements a shared memory key-value store that fits into a single memory mapped segment. All of the runtime data for its instances are stored in the shared memory region, which means that memory overhead for each instance in each process is only a few bytes. Importantly, the key and value strings returned by this class are also pointers into the shared memory region, which means that once an instance is created, its memory cannot be unmapped until process shutdown. For the uses I intend to put it to, this is a reasonable constraint. If we need to use it for shorter-lived maps in the future, we can add an option to return non-literal dependent strings that will be copied if they need to be kept alive long term. MozReview-Commit-ID: 5BwAaDsb7HS --HG-- extra : rebase_source : b472fe628018f88a2c4d6b3de4b7143aeca55e14 extra : absorb_source : 5cdeb568cfd2b4a5a767191402e699e61e653b3b
104 lines
3 KiB
C++
104 lines
3 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4; -*- */
|
|
/* 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 loader_AutoMemMap_h
|
|
#define loader_AutoMemMap_h
|
|
|
|
#include "mozilla/FileUtils.h"
|
|
#include "mozilla/MemoryReporting.h"
|
|
#include "mozilla/RangedPtr.h"
|
|
#include "mozilla/Result.h"
|
|
#include "mozilla/ipc/FileDescriptor.h"
|
|
#include "nsIMemoryReporter.h"
|
|
|
|
#include <prio.h>
|
|
|
|
class nsIFile;
|
|
|
|
namespace mozilla {
|
|
namespace loader {
|
|
|
|
using mozilla::ipc::FileDescriptor;
|
|
|
|
class AutoMemMap
|
|
{
|
|
public:
|
|
AutoMemMap() = default;
|
|
|
|
~AutoMemMap();
|
|
|
|
Result<Ok, nsresult>
|
|
init(nsIFile* file, int flags = PR_RDONLY, int mode = 0,
|
|
PRFileMapProtect prot = PR_PROT_READONLY);
|
|
|
|
Result<Ok, nsresult>
|
|
init(const ipc::FileDescriptor& file,
|
|
PRFileMapProtect prot = PR_PROT_READONLY,
|
|
size_t expectedSize = 0);
|
|
|
|
// Initializes the mapped memory with a shared memory handle. On
|
|
// Unix-like systems, this is identical to the above init() method. On
|
|
// Windows, the FileDescriptor must be a handle for a file mapping,
|
|
// rather than a file descriptor.
|
|
Result<Ok, nsresult>
|
|
initWithHandle(const ipc::FileDescriptor& file, size_t size,
|
|
PRFileMapProtect prot = PR_PROT_READONLY);
|
|
|
|
void reset();
|
|
|
|
bool initialized() { return addr; }
|
|
|
|
uint32_t size() const { return size_; }
|
|
|
|
template<typename T = void>
|
|
RangedPtr<T> get()
|
|
{
|
|
MOZ_ASSERT(addr);
|
|
return { static_cast<T*>(addr), size_ };
|
|
}
|
|
|
|
template<typename T = void>
|
|
const RangedPtr<T> get() const
|
|
{
|
|
MOZ_ASSERT(addr);
|
|
return { static_cast<T*>(addr), size_ };
|
|
}
|
|
|
|
size_t nonHeapSizeOfExcludingThis() { return size_; }
|
|
|
|
FileDescriptor cloneFileDescriptor() const;
|
|
FileDescriptor cloneHandle() const;
|
|
|
|
// Makes this mapping persistent. After calling this, the mapped memory
|
|
// will remained mapped, even after this instance is destroyed.
|
|
void setPersistent() { persistent_ = true; }
|
|
|
|
private:
|
|
Result<Ok, nsresult> initInternal(PRFileMapProtect prot = PR_PROT_READONLY,
|
|
size_t expectedSize = 0);
|
|
|
|
AutoFDClose fd;
|
|
PRFileMap* fileMap = nullptr;
|
|
|
|
#ifdef XP_WIN
|
|
// We can't include windows.h in this header, since it gets included
|
|
// by some binding headers (which are explicitly incompatible with
|
|
// windows.h). So we can't use the HANDLE type here.
|
|
void* handle_ = nullptr;
|
|
#endif
|
|
|
|
uint32_t size_ = 0;
|
|
void* addr = nullptr;
|
|
|
|
bool persistent_ = 0;
|
|
|
|
AutoMemMap(const AutoMemMap&) = delete;
|
|
void operator=(const AutoMemMap&) = delete;
|
|
};
|
|
|
|
} // namespace loader
|
|
} // namespace mozilla
|
|
|
|
#endif // loader_AutoMemMap_h
|