bugfix, updated README

This commit is contained in:
mandreyel 2017-10-06 13:18:12 +02:00
parent 0d94b74491
commit 2024c807f0
4 changed files with 69 additions and 58 deletions

View File

@ -1,5 +1,5 @@
# mio # mio
A simple header-only cross-platform C++14 memory mapping library. A simple header-only cross-platform C++11 memory mapping library.
## Example ## Example
```c++ ```c++
@ -42,10 +42,14 @@ int main()
// Or just change one value with the subscript operator. // Or just change one value with the subscript operator.
mmap2[mmap2.size() / 2] = 42; mmap2[mmap2.size() / 2] = 42;
// Don't forget to flush changes to disk, which is NOT done by the constructor for
// more explicit control of this potentially expensive operation.
mmap2.sync();
// You can also create a mapping using the constructor, which throws a // You can also create a mapping using the constructor, which throws a
// std::error_code upon failure. // std::error_code upon failure.
try {
const auto page_size = mio::page_size(); const auto page_size = mio::page_size();
try {
mio::mmap_sink mmap3("another/path/to/file", mio::mmap_sink mmap3("another/path/to/file",
offset_type(page_size), length_type(page_size)); offset_type(page_size), length_type(page_size));
// ... // ...
@ -58,6 +62,15 @@ int main()
// accounted for by mio, so appropriate conversions need be done by the user). // accounted for by mio, so appropriate conversions need be done by the user).
using wmmap_source = mio::basic_mmap_source<wchar_t>; using wmmap_source = mio::basic_mmap_source<wchar_t>;
using i32mmap_source = mio::basic_mmap_source<int32_t>; using i32mmap_source = mio::basic_mmap_source<int32_t>;
// mio::basic_mmap<> has std::unique_ptr semantics, but if multiple copies to the
// same mapping is required, use mio::basic_shared_mmap<> for std::shared_ptr
// semantics, which has the same interface as mio::basic_mmap<>.
mio::shared_mmap_source shared_mmap1("path", offset_type(0), length_type(page_size));
mio::shared_mmap_source shared_mmap2(std::move(mmap1)); // or use operator=
mio::shared_mmap_source shared_mmap3(std::make_shared<mio::mmap_source>(mmap1)); // or use operator=
mio::shared_mmap_source shared_mmap4;
shared_mmap4.map("path", offset_type(0), length_type(page_size), error);
} }
``` ```

View File

@ -79,9 +79,9 @@ private:
#endif #endif
// Length, in bytes, requested by user, which may not be the length of the full // Length, in bytes, requested by user, which may not be the length of the full
// mapping. // mapping, and the entire length of the full mapping.
size_type length_ = 0; size_type num_bytes_ = 0;
size_type mapped_length_ = 0; size_type num_mapped_bytes_ = 0;
// Letting user map a file using both an existing file handle and a path introcudes // Letting user map a file using both an existing file handle and a path introcudes
// some complexity in that we must not close the file handle if user provided it, // some complexity in that we must not close the file handle if user provided it,
@ -105,9 +105,9 @@ public:
bool is_mapped() const noexcept; bool is_mapped() const noexcept;
bool empty() const noexcept { return length() == 0; } bool empty() const noexcept { return length() == 0; }
size_type offset() const noexcept { return mapped_length_ - length_; } size_type offset() const noexcept { return to_char_size(num_mapped_bytes_ - num_bytes_); }
size_type length() const noexcept { return length_; } size_type length() const noexcept { return to_char_size(num_bytes_); }
size_type mapped_length() const noexcept { return mapped_length_; } size_type mapped_length() const noexcept { return to_char_size(num_mapped_bytes_); }
pointer data() noexcept { return data_; } pointer data() noexcept { return data_; }
const_pointer data() const noexcept { return data_; } const_pointer data() const noexcept { return data_; }
@ -135,9 +135,9 @@ public:
void set_offset(const size_type offset) noexcept; void set_offset(const size_type offset) noexcept;
template<typename String> template<typename String>
void map(String& path, size_type offset, size_type length, void map(String& path, size_type offset, size_type num_bytes,
access_mode mode, std::error_code& error); access_mode mode, std::error_code& error);
void map(handle_type handle, size_type offset, size_type length, void map(handle_type handle, size_type offset, size_type num_bytes,
access_mode mode, std::error_code& error); access_mode mode, std::error_code& error);
void unmap(); void unmap();
void close(); void close();
@ -150,8 +150,18 @@ private:
pointer get_mapping_start() noexcept; pointer get_mapping_start() noexcept;
void map(const size_type offset, size_type length, void map(const size_type offset, size_type num_bytes,
const access_mode mode, std::error_code& error); const access_mode mode, std::error_code& error);
static size_type to_char_size(const size_type num_bytes) noexcept
{
return num_bytes >> (sizeof(CharT) - 1);
}
static size_type to_byte_size(const size_type num_chars) noexcept
{
return num_chars << (sizeof(CharT) - 1);
}
}; };
template<typename CharT> template<typename CharT>

View File

@ -49,7 +49,7 @@ inline DWORD int64_high(int64_t n) noexcept
inline DWORD int64_low(int64_t n) noexcept inline DWORD int64_low(int64_t n) noexcept
{ {
return n & 0xff'ff'ff'ff; return n & 0xffffffff;
} }
#endif #endif
@ -125,8 +125,8 @@ basic_mmap<CharT>::~basic_mmap()
template<typename CharT> template<typename CharT>
basic_mmap<CharT>::basic_mmap(basic_mmap<CharT>&& other) basic_mmap<CharT>::basic_mmap(basic_mmap<CharT>&& other)
: data_(std::move(other.data_)) : data_(std::move(other.data_))
, length_(std::move(other.length_)) , num_bytes_(std::move(other.num_bytes_))
, mapped_length_(std::move(other.mapped_length_)) , num_mapped_bytes_(std::move(other.num_mapped_bytes_))
, file_handle_(std::move(other.file_handle_)) , file_handle_(std::move(other.file_handle_))
#ifdef _WIN32 #ifdef _WIN32
, file_mapping_handle_(std::move(other.file_mapping_handle_)) , file_mapping_handle_(std::move(other.file_mapping_handle_))
@ -134,7 +134,7 @@ basic_mmap<CharT>::basic_mmap(basic_mmap<CharT>&& other)
, is_handle_internal_(std::move(other.is_handle_internal_)) , is_handle_internal_(std::move(other.is_handle_internal_))
{ {
other.data_ = nullptr; other.data_ = nullptr;
other.length_ = other.mapped_length_ = 0; other.num_bytes_ = other.num_mapped_bytes_ = 0;
other.file_handle_ = INVALID_HANDLE_VALUE; other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32 #ifdef _WIN32
other.file_mapping_handle_ = INVALID_HANDLE_VALUE; other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
@ -149,8 +149,8 @@ basic_mmap<CharT>& basic_mmap<CharT>::operator=(basic_mmap<CharT>&& other)
// First the existing mapping needs to be removed. // First the existing mapping needs to be removed.
unmap(); unmap();
data_ = std::move(other.data_); data_ = std::move(other.data_);
length_ = std::move(other.length_); num_bytes_ = std::move(other.num_bytes_);
mapped_length_ = std::move(other.mapped_length_); num_mapped_bytes_ = std::move(other.num_mapped_bytes_);
file_handle_ = std::move(other.file_handle_); file_handle_ = std::move(other.file_handle_);
#ifdef _WIN32 #ifdef _WIN32
file_mapping_handle_ = std::move(other.file_mapping_handle_); file_mapping_handle_ = std::move(other.file_mapping_handle_);
@ -160,7 +160,7 @@ basic_mmap<CharT>& basic_mmap<CharT>::operator=(basic_mmap<CharT>&& other)
// The moved from basic_mmap's fields need to be reset, because otherwise other's // The moved from basic_mmap's fields need to be reset, because otherwise other's
// destructor will unmap the same mapping that was just moved into this. // destructor will unmap the same mapping that was just moved into this.
other.data_ = nullptr; other.data_ = nullptr;
other.length_ = other.mapped_length_ = 0; other.num_bytes_ = other.num_mapped_bytes_ = 0;
other.file_handle_ = INVALID_HANDLE_VALUE; other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32 #ifdef _WIN32
other.file_mapping_handle_ = INVALID_HANDLE_VALUE; other.file_mapping_handle_ = INVALID_HANDLE_VALUE;
@ -183,7 +183,7 @@ typename basic_mmap<CharT>::handle_type basic_mmap<CharT>::mapping_handle() cons
template<typename CharT> template<typename CharT>
template<typename String> template<typename String>
void basic_mmap<CharT>::map(String& path, size_type offset, void basic_mmap<CharT>::map(String& path, size_type offset,
size_type length, access_mode mode, std::error_code& error) size_type num_bytes, access_mode mode, std::error_code& error)
{ {
error.clear(); error.clear();
if(detail::empty(path)) if(detail::empty(path))
@ -195,7 +195,7 @@ void basic_mmap<CharT>::map(String& path, size_type offset,
{ {
const auto handle = open_file(path, mode, error); const auto handle = open_file(path, mode, error);
if(error) { return; } if(error) { return; }
map(handle, offset, length, mode, error); map(handle, offset, num_bytes, mode, error);
// MUST be after the call to map, as that sets this to true. // MUST be after the call to map, as that sets this to true.
is_handle_internal_ = true; is_handle_internal_ = true;
} }
@ -203,7 +203,7 @@ void basic_mmap<CharT>::map(String& path, size_type offset,
template<typename CharT> template<typename CharT>
void basic_mmap<CharT>::map(handle_type handle, size_type offset, void basic_mmap<CharT>::map(handle_type handle, size_type offset,
size_type length, access_mode mode, std::error_code& error) size_type num_bytes, access_mode mode, std::error_code& error)
{ {
error.clear(); error.clear();
if(handle == INVALID_HANDLE_VALUE) if(handle == INVALID_HANDLE_VALUE)
@ -215,11 +215,11 @@ void basic_mmap<CharT>::map(handle_type handle, size_type offset,
const auto file_size = query_file_size(handle, error); const auto file_size = query_file_size(handle, error);
if(error) { return; } if(error) { return; }
if(length <= map_entire_file) if(num_bytes <= map_entire_file)
{ {
length = file_size; num_bytes = file_size;
} }
else if(offset + length > file_size) else if(offset + num_bytes > file_size)
{ {
error = std::make_error_code(std::errc::invalid_argument); error = std::make_error_code(std::errc::invalid_argument);
return; return;
@ -227,17 +227,17 @@ void basic_mmap<CharT>::map(handle_type handle, size_type offset,
file_handle_ = handle; file_handle_ = handle;
is_handle_internal_ = false; is_handle_internal_ = false;
map(offset, length, mode, error); map(offset, num_bytes, mode, error);
} }
template<typename CharT> template<typename CharT>
void basic_mmap<CharT>::map(const size_type offset, const size_type length, void basic_mmap<CharT>::map(const size_type offset, const size_type num_bytes,
const access_mode mode, std::error_code& error) const access_mode mode, std::error_code& error)
{ {
const size_type aligned_offset = make_offset_page_aligned(offset); const size_type aligned_offset = make_offset_page_aligned(offset);
const size_type length_to_map = offset - aligned_offset + length; const size_type num_bytes_to_map = offset - aligned_offset + num_bytes;
#ifdef _WIN32 #ifdef _WIN32
const size_type max_file_size = offset + length; const size_type max_file_size = offset + num_bytes;
file_mapping_handle_ = ::CreateFileMapping( file_mapping_handle_ = ::CreateFileMapping(
file_handle_, file_handle_,
0, 0,
@ -256,7 +256,7 @@ void basic_mmap<CharT>::map(const size_type offset, const size_type length,
mode == access_mode::read ? FILE_MAP_READ : FILE_MAP_WRITE, mode == access_mode::read ? FILE_MAP_READ : FILE_MAP_WRITE,
int64_high(aligned_offset), int64_high(aligned_offset),
int64_low(aligned_offset), int64_low(aligned_offset),
length_to_map)); num_bytes_to_map));
if(mapping_start == nullptr) if(mapping_start == nullptr)
{ {
error = last_error(); error = last_error();
@ -265,7 +265,7 @@ void basic_mmap<CharT>::map(const size_type offset, const size_type length,
#else #else
const pointer mapping_start = static_cast<pointer>(::mmap( const pointer mapping_start = static_cast<pointer>(::mmap(
0, // Don't give hint as to where to map. 0, // Don't give hint as to where to map.
length_to_map, num_bytes_to_map,
mode == access_mode::read ? PROT_READ : PROT_WRITE, mode == access_mode::read ? PROT_READ : PROT_WRITE,
MAP_SHARED, MAP_SHARED,
file_handle_, file_handle_,
@ -277,8 +277,8 @@ void basic_mmap<CharT>::map(const size_type offset, const size_type length,
} }
#endif #endif
data_ = mapping_start + offset - aligned_offset; data_ = mapping_start + offset - aligned_offset;
length_ = length; num_bytes_ = num_bytes;
mapped_length_ = length_to_map; num_mapped_bytes_ = num_bytes_to_map;
} }
template<typename CharT> template<typename CharT>
@ -294,10 +294,10 @@ void basic_mmap<CharT>::sync(std::error_code& error)
if(data() != nullptr) if(data() != nullptr)
{ {
#ifdef _WIN32 #ifdef _WIN32
if(::FlushViewOfFile(get_mapping_start(), mapped_length_) == 0 if(::FlushViewOfFile(get_mapping_start(), num_mapped_bytes_) == 0
|| ::FlushFileBuffers(file_handle_) == 0) || ::FlushFileBuffers(file_handle_) == 0)
#else #else
if(::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0) if(::msync(get_mapping_start(), num_mapped_bytes_, MS_SYNC) != 0)
#endif #endif
{ {
error = last_error(); error = last_error();
@ -325,7 +325,7 @@ void basic_mmap<CharT>::unmap()
file_mapping_handle_ = INVALID_HANDLE_VALUE; file_mapping_handle_ = INVALID_HANDLE_VALUE;
} }
#else #else
if(data_) { ::munmap(const_cast<pointer>(get_mapping_start()), mapped_length_); } if(data_) { ::munmap(const_cast<pointer>(get_mapping_start()), num_mapped_bytes_); }
#endif #endif
// If file handle was obtained by our opening it (when map is called with a path, // If file handle was obtained by our opening it (when map is called with a path,
@ -342,7 +342,7 @@ void basic_mmap<CharT>::unmap()
// Reset fields to their default values. // Reset fields to their default values.
data_ = nullptr; data_ = nullptr;
length_ = mapped_length_ = 0; num_bytes_ = num_mapped_bytes_ = 0;
file_handle_ = INVALID_HANDLE_VALUE; file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32 #ifdef _WIN32
file_mapping_handle_ = INVALID_HANDLE_VALUE; file_mapping_handle_ = INVALID_HANDLE_VALUE;
@ -377,7 +377,7 @@ template<typename CharT>
void basic_mmap<CharT>::set_length(const size_type length) noexcept void basic_mmap<CharT>::set_length(const size_type length) noexcept
{ {
if(length > this->length() - offset()) { throw std::invalid_argument(""); } if(length > this->length() - offset()) { throw std::invalid_argument(""); }
length_ = length; num_bytes_ = to_byte_size(length);
} }
template<typename CharT> template<typename CharT>
@ -386,7 +386,7 @@ void basic_mmap<CharT>::set_offset(const size_type offset) noexcept
if(offset >= mapped_length()) { throw std::invalid_argument(""); } if(offset >= mapped_length()) { throw std::invalid_argument(""); }
const auto diff = offset - this->offset(); const auto diff = offset - this->offset();
data_ += diff; data_ += diff;
length_ += -1 * diff; num_bytes_ += -1 * to_byte_size(diff);
} }
template<typename CharT> template<typename CharT>
@ -400,8 +400,8 @@ void basic_mmap<CharT>::swap(basic_mmap<CharT>& other)
#ifdef _WIN32 #ifdef _WIN32
swap(file_mapping_handle_, other.file_mapping_handle_); swap(file_mapping_handle_, other.file_mapping_handle_);
#endif #endif
swap(length_, other.length_); swap(num_bytes_, other.num_bytes_);
swap(mapped_length_, other.mapped_length_); swap(num_mapped_bytes_, other.num_mapped_bytes_);
swap(is_handle_internal_, other.is_handle_internal_); swap(is_handle_internal_, other.is_handle_internal_);
} }
} }

View File

@ -141,16 +141,16 @@ public:
* actual number of bytes that were mapped, also divided by `sizeof(CharT)`, which * actual number of bytes that were mapped, also divided by `sizeof(CharT)`, which
* is a multiple of the underlying operating system's page allocation granularity. * is a multiple of the underlying operating system's page allocation granularity.
*/ */
size_type size() const noexcept { return char_size(impl_.length()); } size_type size() const noexcept { return impl_.length(); }
size_type length() const noexcept { return char_size(impl_.length()); } size_type length() const noexcept { return impl_.length(); }
size_type mapped_length() const noexcept { return char_size(impl_.mapped_length()); } size_type mapped_length() const noexcept { return impl_.mapped_length(); }
/** /**
* Returns the offset, relative to the file's start, at which the mapping was * Returns the offset, relative to the file's start, at which the mapping was
* requested to be created, expressed in multiples of `sizeof(CharT)` rather than * requested to be created, expressed in multiples of `sizeof(CharT)` rather than
* in bytes. * in bytes.
*/ */
size_type offset() const noexcept { return char_size(impl_.offset()); } size_type offset() const noexcept { return impl_.offset(); }
/** /**
* Returns a pointer to the first requested byte, or `nullptr` if no memory mapping * Returns a pointer to the first requested byte, or `nullptr` if no memory mapping
@ -215,8 +215,8 @@ public:
* If `offset` is larger than the number of bytes mapped, an std::invalid_argument * If `offset` is larger than the number of bytes mapped, an std::invalid_argument
* exception is thrown. * exception is thrown.
*/ */
void set_length(const size_type length) noexcept { impl_.set_length(byte_size(length)); } void set_length(const size_type length) noexcept { impl_.set_length(length); }
void set_offset(const size_type offset) noexcept { impl_.set_offset(byte_size(offset)); } void set_offset(const size_type offset) noexcept { impl_.set_offset(offset); }
/** /**
* Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the * Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the
@ -327,18 +327,6 @@ public:
{ {
return a.impl_ >= b.impl_; return a.impl_ >= b.impl_;
} }
private:
static size_type char_size(const size_type num_bytes) noexcept
{
return num_bytes >> (sizeof(CharT) - 1);
}
static size_type byte_size(const size_type num_bytes) noexcept
{
return num_bytes << (sizeof(CharT) - 1);
}
}; };
/** /**