refactor: simplify OS abstraction for mmap_block and fix move ops

This commit is contained in:
Marcus Holland-Moritz 2025-04-15 09:58:33 +02:00
parent 6cf07409dc
commit b0bc9b20c4

View File

@ -44,60 +44,73 @@ namespace dwarfs::reader {
namespace { namespace {
#ifdef _WIN32
class mmap_block { class mmap_block {
public: public:
mmap_block(size_t size) mmap_block(size_t size)
: data_{::VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, : data_{allocate(size)}
PAGE_READWRITE)} , size_{size} {}
, size_{size} {
if (!data_) { mmap_block(mmap_block&& other) noexcept
: data_{other.data_}
, size_{other.size_} {
other.data_ = nullptr;
other.size_ = 0;
}
mmap_block& operator=(mmap_block&& other) noexcept {
if (this != &other) {
mmap_block tmp{std::move(*this)};
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}
size_t size() const { return size_; }
uint8_t* data() { return static_cast<uint8_t*>(data_); }
uint8_t const* data() const { return static_cast<uint8_t const*>(data_); }
~mmap_block() {
if (data_) {
deallocate(data_, size_);
}
}
private:
static void* allocate(size_t size) {
#ifdef _WIN32
void* data =
::VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!data) {
std::error_code ec(::GetLastError(), std::system_category()); std::error_code ec(::GetLastError(), std::system_category());
throw std::runtime_error("VirtualAlloc failed: " + ec.message()); throw std::runtime_error("VirtualAlloc failed: " + ec.message());
} }
}
size_t size() const { return size_; }
uint8_t* data() { return static_cast<uint8_t*>(data_); }
uint8_t const* data() const { return static_cast<uint8_t const*>(data_); }
~mmap_block() {
auto rv [[maybe_unused]] = ::VirtualFree(data_, 0, MEM_RELEASE);
assert(rv);
}
private:
void* data_;
size_t size_;
};
#else #else
class mmap_block { void* data = ::mmap(nullptr, size, PROT_READ | PROT_WRITE,
public: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
mmap_block(size_t size) if (data == MAP_FAILED) {
: data_{::mmap(nullptr, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)}
, size_{size} {
if (data_ == MAP_FAILED) {
throw std::runtime_error("mmap failed"); throw std::runtime_error("mmap failed");
} }
#endif
return data;
} }
size_t size() const { return size_; } static void deallocate(void* data, size_t size) {
#ifdef _WIN32
uint8_t* data() { return static_cast<uint8_t*>(data_); } auto rv [[maybe_unused]] = ::VirtualFree(data, 0, MEM_RELEASE);
uint8_t const* data() const { return static_cast<uint8_t const*>(data_); } assert(rv);
#else
~mmap_block() { auto rv [[maybe_unused]] = ::munmap(data, size);
auto rv [[maybe_unused]] = ::munmap(data_, size_);
assert(rv == 0); assert(rv == 0);
#endif
} }
private:
void* data_; void* data_;
size_t size_; size_t size_;
}; };
#endif
class mmap_byte_buffer_impl : public mutable_byte_buffer_interface { class mmap_byte_buffer_impl : public mutable_byte_buffer_interface {
public: public: