123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #ifndef MMF_H
- #define MMF_H
- #include <cstddef>
- #include <string>
- #include <iterator>
- #include "mmap_wrapper.hxx"
- #ifdef _WIN32
- #define IF_WIN(exp) exp
- #define IF_UNIX(exp)
- #else
- #define IF_WIN(exp)
- #define IF_UNIX(exp) exp
- #include <sys/mman.h>
- #include <unistd.h>
- #endif
- namespace pmmf {
- class MappedFile {
- public:
- template<typename T>
- class MappedData {
- friend class MappedFile;
- FileDescriptor file_descriptor = INVALID_FILE_DESCRIPTOR;
- size_t offset = -1;
- size_t byte_offset = -1;
- size_t element_count = -1;
- void* page_start = nullptr;
- MappedData(FileDescriptor file_descriptor, size_t offset, size_t byte_offset, size_t element_count, void* page_start)
- : file_descriptor(file_descriptor), offset(offset), byte_offset(byte_offset), element_count(element_count), page_start(page_start) {}
- T* getDataStart() const { return reinterpret_cast<T*>(reinterpret_cast<char*>(page_start) + byte_offset); }
- public:
- MappedData() = default;
- MappedData(const MappedData<T>&) = delete;
- MappedData(MappedData<T>&& other)
- : file_descriptor(other.file_descriptor), offset(other.offset), byte_offset(other.byte_offset), element_count(other.element_count), page_start(other.page_start) {
- other.file_descriptor = INVALID_FILE_DESCRIPTOR;
- other.offset = -1;
- other.byte_offset = -1;
- other.element_count = -1;
- other.page_start = nullptr;
- }
- ~MappedData() {
- if(page_start) {
- flush();
- munmap(page_start, byte_offset + element_count * sizeof(T));
- }
- }
- inline bool isMapped() const { return !!page_start; }
- inline size_t getDataOffset() const { return offset + byte_offset; }
- inline size_t getPageOffset() const { return offset; }
- inline size_t getElementCount() const { return element_count; }
- inline size_t getDataSize() const { return element_count * sizeof(T); }
- inline size_t getPageSize() const { return byte_offset + element_count * sizeof(T); }
- inline T& operator[](size_t index) { return *(getDataStart() + index); }
- inline const T& operator[](size_t index) const { return *(getDataStart() + index); }
- inline T& operator*() { return *getDataStart(); }
- inline const T& operator*() const { return *getDataStart(); }
- inline T* operator->() { return getDataStart(); }
- inline const T* operator->() const { return getDataStart(); }
- inline T* begin() { return getDataStart(); }
- inline T* end() { return getDataStart() + element_count; }
- inline const T* begin() const { return getDataStart(); }
- inline const T* end() const { return getDataStart() + element_count; }
- inline const T* cbegin() const { return getDataStart(); }
- inline const T* cend() const { return getDataStart() + element_count; }
- inline std::reverse_iterator<T*> rbegin() { return getDataStart() + element_count - 1; }
- inline std::reverse_iterator<T*> rend() { return getDataStart() - 1; }
- inline std::reverse_iterator<const T*> rbegin() const { return getDataStart() + element_count - 1; }
- inline std::reverse_iterator<const T*> rend() const { return getDataStart() - 1; }
- inline std::reverse_iterator<const T*> crbegin() const { return getDataStart() + element_count - 1; }
- inline std::reverse_iterator<const T*> crend() const { return getDataStart() - 1; }
- bool flush() {
- #ifdef _WIN32
- constexpr int MS_SYNC = 0;
- #endif
- if(isMapped()) return msync(file_descriptor, page_start, byte_offset + element_count * sizeof(T), MS_SYNC) == 0;
- return false;
- }
- MappedData<T>& operator=(MappedData<T>&& other) {
- ~MappedData<T>();
- return new(this) MappedData<T>(std::move(other));
- }
- };
- template<typename T>
- friend class MappedData;
- private:
- static size_t getSystemPageSize();
- static inline const size_t OS_PAGE_SIZE = getSystemPageSize();
- FileDescriptor file_descriptor = INVALID_FILE_DESCRIPTOR;
- ProtectionMode proterction_mode = ProtectionMode(0x00);
- MapFlag map_flag = MapFlag(0x00);
- FileDescriptor openFile(std::string file_path, ProtectionMode protection_mode);
- public:
- MappedFile(std::string file_path, ProtectionMode protection_mode = ProtectionMode::rw, MapFlag map_flag = MapFlag::shared);
- MappedFile(const MappedFile&) = delete;
- MappedFile(MappedFile&& other)
- : file_descriptor(other.file_descriptor),
- proterction_mode(other.proterction_mode),
- map_flag(other.map_flag) {
- other.file_descriptor = INVALID_FILE_DESCRIPTOR;
- other.proterction_mode = ProtectionMode(0);
- other.map_flag = MapFlag(0);
- }
- ~MappedFile();
- static inline size_t getOSPageSize() { return OS_PAGE_SIZE; }
- inline bool isFileOpen() const { return file_descriptor != INVALID_FILE_DESCRIPTOR; }
- size_t getFileSize() const;
- template<typename T>
- MappedData<T> getMappedData(size_t byte_offset, size_t element_count = 1) {
- if(!isFileOpen())
- return MappedData<T>(INVALID_FILE_DESCRIPTOR, -1, -1, -1, nullptr);
- #ifndef _WIN32
- if(getFileSize() < byte_offset + element_count * sizeof(T))
- if(ftruncate64(file_descriptor, byte_offset + element_count * sizeof(T)) != 0)
- return MappedData<T>(INVALID_FILE_DESCRIPTOR, -1, -1, -1, nullptr);
- #endif
- const size_t page_aligned_offset = (byte_offset / OS_PAGE_SIZE) * OS_PAGE_SIZE;
- byte_offset = byte_offset - page_aligned_offset;
- void* page_start = mmap(nullptr, byte_offset + element_count * sizeof(T), proterction_mode, map_flag, file_descriptor, page_aligned_offset);
- if(page_start == (void*)-1)
- return MappedData<T>(INVALID_FILE_DESCRIPTOR, -1, -1, -1, nullptr);
- return MappedData<T>(file_descriptor, page_aligned_offset, byte_offset, element_count, page_start);
- }
- };
- template <typename T>
- using MappedData = MappedFile::MappedData<T>;
- }
- #undef OS_DEP
- #endif //MMF_H
|