1#ifndef OSMIUM_UTIL_MEMORY_MAPPING_HPP
2#define OSMIUM_UTIL_MEMORY_MAPPING_HPP
42#include <system_error>
46# include <sys/statvfs.h>
51# include <sys/types.h>
56 inline namespace util {
148 HANDLE get_handle() const noexcept;
149 HANDLE create_file_mapping() const noexcept;
150 void* map_view_of_file() const noexcept;
159 struct statvfs stat{};
160 const int result = ::fstatvfs(
fd, &stat);
164 return stat.f_bsize * stat.f_bavail;
178 if (available > 0 && current_file_size + available <=
m_size) {
179 throw std::system_error{ENOSPC, std::system_category(),
"Could not resize file: Not enough space on filesystem"};
231 }
catch (
const std::system_error&) {
255 void resize(std::size_t new_size);
261 explicit operator bool() const noexcept {
270 std::size_t
size() const noexcept {
279 int fd() const noexcept {
295 template <
typename T =
void>
297 return reinterpret_cast<T*
>(
m_addr);
325 void resize(std::size_t) =
delete;
339 template <
typename T>
421 explicit operator bool() const noexcept {
430 std::size_t
size() const noexcept {
440 int fd() const noexcept {
483 const T*
cend() const noexcept {
501 const T*
end() const noexcept {
507 template <
typename T>
521 void resize(std::size_t) =
delete;
535#pragma GCC diagnostic push
536#pragma GCC diagnostic ignored "-Wold-style-cast"
539 return m_addr != MAP_FAILED;
546#pragma GCC diagnostic pop
550# define MAP_ANONYMOUS MAP_ANON
554 if (m_mapping_mode == mapping_mode::readonly) {
557 return PROT_READ | PROT_WRITE;
564 if (m_mapping_mode == mapping_mode::write_shared) {
571 m_size(check_size(size)),
574 m_mapping_mode(mode),
575 m_addr(::mmap(nullptr, m_size, get_protection(), get_flags(), m_fd, m_offset)) {
578 throw std::system_error{errno, std::system_category(),
"mmap failed"};
583 m_size(other.m_size),
584 m_offset(other.m_offset),
586 m_mapping_mode(other.m_mapping_mode),
587 m_addr(other.m_addr) {
588 other.make_invalid();
594 }
catch (
const std::system_error&) {
598 m_size = other.m_size;
599 m_offset = other.m_offset;
601 m_mapping_mode = other.m_mapping_mode;
602 m_addr = other.m_addr;
603 other.make_invalid();
609 if (::munmap(m_addr, m_size) != 0) {
610 throw std::system_error{errno, std::system_category(),
"munmap failed"};
617 assert(new_size > 0 &&
"can not resize to zero size");
620 m_addr = ::mremap(m_addr, m_size, new_size, MREMAP_MAYMOVE);
622 throw std::system_error{errno, std::system_category(),
"mremap failed"};
626 assert(
false &&
"can't resize anonymous mappings on non-linux systems");
632 m_addr = ::mmap(
nullptr, new_size, get_protection(), get_flags(), m_fd, m_offset);
634 throw std::system_error{errno, std::system_category(),
"mmap (remap) failed"};
652 inline namespace util {
654 inline DWORD dword_hi(uint64_t x) {
655 return static_cast<DWORD
>(x >> 32);
658 inline DWORD dword_lo(uint64_t x) {
659 return static_cast<DWORD
>(x & 0xffffffff);
667 switch (m_mapping_mode) {
668 case mapping_mode::readonly:
669 return PAGE_READONLY;
670 case mapping_mode::write_private:
671 return PAGE_WRITECOPY;
675 return PAGE_READWRITE;
679 switch (m_mapping_mode) {
680 case mapping_mode::readonly:
681 return FILE_MAP_READ;
682 case mapping_mode::write_private:
683 return FILE_MAP_COPY;
687 return FILE_MAP_WRITE;
690inline HANDLE osmium::util::MemoryMapping::get_handle() const noexcept {
692 return INVALID_HANDLE_VALUE;
694 return reinterpret_cast<HANDLE
>(_get_osfhandle(m_fd));
697inline HANDLE osmium::util::MemoryMapping::create_file_mapping() const noexcept {
699 _setmode(m_fd, _O_BINARY);
701 return CreateFileMapping(get_handle(),
704 osmium::dword_hi(
static_cast<uint64_t
>(m_size) + m_offset),
705 osmium::dword_lo(
static_cast<uint64_t
>(m_size) + m_offset),
709inline void* osmium::util::MemoryMapping::map_view_of_file() const noexcept {
710 return MapViewOfFile(m_handle,
712 osmium::dword_hi(m_offset),
713 osmium::dword_lo(m_offset),
718 return m_addr !=
nullptr;
728inline int last_error() noexcept {
729 return static_cast<int>(GetLastError());
733 m_size(check_size(size)),
736 m_mapping_mode(mode),
737 m_handle(create_file_mapping()),
741 throw std::system_error{last_error(), std::system_category(),
"CreateFileMapping failed"};
744 m_addr = map_view_of_file();
746 throw std::system_error{last_error(), std::system_category(),
"MapViewOfFile failed"};
751 m_size(other.m_size),
752 m_offset(other.m_offset),
754 m_mapping_mode(other.m_mapping_mode),
755 m_handle(std::move(other.m_handle)),
756 m_addr(other.m_addr) {
757 other.make_invalid();
758 other.m_handle =
nullptr;
764 }
catch (
const std::system_error&) {
768 m_size = other.m_size;
769 m_offset = other.m_offset;
771 m_mapping_mode = other.m_mapping_mode;
772 m_handle = std::move(other.m_handle);
773 m_addr = other.m_addr;
774 other.make_invalid();
775 other.m_handle =
nullptr;
781 if (!UnmapViewOfFile(m_addr)) {
782 throw std::system_error{last_error(), std::system_category(),
"UnmapViewOfFile failed"};
788 if (!CloseHandle(m_handle)) {
789 throw std::system_error{last_error(), std::system_category(),
"CloseHandle failed"};
801 m_handle = create_file_mapping();
803 throw std::system_error{last_error(), std::system_category(),
"CreateFileMapping failed"};
806 m_addr = map_view_of_file();
808 throw std::system_error{last_error(), std::system_category(),
"MapViewOfFile failed"};
Definition: memory_mapping.hpp:312
AnonymousMemoryMapping(std::size_t size)
Definition: memory_mapping.hpp:316
Definition: memory_mapping.hpp:508
AnonymousTypedMemoryMapping(std::size_t size)
Definition: memory_mapping.hpp:512
Definition: memory_mapping.hpp:95
int resize_fd(int fd) const
Definition: memory_mapping.hpp:168
void unmap()
Definition: memory_mapping.hpp:607
bool is_valid() const noexcept
Definition: memory_mapping.hpp:538
MemoryMapping & operator=(const MemoryMapping &)=delete
You can not copy a MemoryMapping.
mapping_mode
Definition: memory_mapping.hpp:99
std::size_t size() const noexcept
Definition: memory_mapping.hpp:270
MemoryMapping(const MemoryMapping &)=delete
You can not copy construct a MemoryMapping.
flag_type get_protection() const noexcept
Definition: memory_mapping.hpp:553
off_t m_offset
Offset into the file.
Definition: memory_mapping.hpp:111
~MemoryMapping() noexcept
Definition: memory_mapping.hpp:228
std::size_t m_size
The size of the mapping.
Definition: memory_mapping.hpp:108
static std::size_t available_space(int fd)
Definition: memory_mapping.hpp:155
int m_fd
File handle we got the mapping from.
Definition: memory_mapping.hpp:114
int flag_type
Definition: memory_mapping.hpp:133
void resize(std::size_t new_size)
Definition: memory_mapping.hpp:616
bool writable() const noexcept
Definition: memory_mapping.hpp:286
T * get_addr() const noexcept
Definition: memory_mapping.hpp:296
flag_type get_flags() const noexcept
Definition: memory_mapping.hpp:560
mapping_mode m_mapping_mode
Mapping mode.
Definition: memory_mapping.hpp:117
static std::size_t check_size(std::size_t size)
Definition: memory_mapping.hpp:140
void make_invalid() noexcept
Definition: memory_mapping.hpp:542
void * m_addr
The address where the memory is mapped.
Definition: memory_mapping.hpp:124
int fd() const noexcept
Definition: memory_mapping.hpp:279
MemoryMapping(std::size_t size, mapping_mode mode, int fd=-1, off_t offset=0)
Definition: memory_mapping.hpp:570
Definition: memory_mapping.hpp:340
~TypedMemoryMapping() noexcept=default
int fd() const noexcept
Definition: memory_mapping.hpp:440
void resize(std::size_t new_size)
Definition: memory_mapping.hpp:413
TypedMemoryMapping & operator=(TypedMemoryMapping &&other) noexcept=default
const T * end() const noexcept
Definition: memory_mapping.hpp:501
const T * begin() const noexcept
Definition: memory_mapping.hpp:492
void unmap()
Definition: memory_mapping.hpp:399
TypedMemoryMapping(std::size_t size)
Definition: memory_mapping.hpp:352
bool writable() const noexcept
Definition: memory_mapping.hpp:447
TypedMemoryMapping(const TypedMemoryMapping &)=delete
You can not copy construct a TypedMemoryMapping.
const T * cend() const noexcept
Definition: memory_mapping.hpp:483
std::size_t size() const noexcept
Definition: memory_mapping.hpp:430
TypedMemoryMapping(std::size_t size, MemoryMapping::mapping_mode mode, int fd, off_t offset=0)
Definition: memory_mapping.hpp:366
MemoryMapping m_mapping
Definition: memory_mapping.hpp:342
const T * cbegin() const noexcept
Definition: memory_mapping.hpp:474
TypedMemoryMapping(TypedMemoryMapping &&other) noexcept=default
T * end() noexcept
Definition: memory_mapping.hpp:465
TypedMemoryMapping & operator=(const TypedMemoryMapping &)=delete
You can not copy a TypedMemoryMapping.
T * begin() noexcept
Definition: memory_mapping.hpp:456
#define MAP_ANONYMOUS
Definition: memory_mapping.hpp:550
void resize_file(int fd, std::size_t new_size)
Definition: file.hpp:177
std::size_t file_size(int fd)
Definition: file.hpp:109
std::size_t get_pagesize() noexcept
Definition: file.hpp:193
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: location.hpp:555