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
A simple header-only cross-platform C++14 memory mapping library.
A simple header-only cross-platform C++11 memory mapping library.
## Example
```c++
@ -42,10 +42,14 @@ int main()
// Or just change one value with the subscript operator.
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
// std::error_code upon failure.
const auto page_size = mio::page_size();
try {
const auto page_size = mio::page_size();
mio::mmap_sink mmap3("another/path/to/file",
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).
using wmmap_source = mio::basic_mmap_source<wchar_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
// Length, in bytes, requested by user, which may not be the length of the full
// mapping.
size_type length_ = 0;
size_type mapped_length_ = 0;
// mapping, and the entire length of the full mapping.
size_type num_bytes_ = 0;
size_type num_mapped_bytes_ = 0;
// 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,
@ -105,9 +105,9 @@ public:
bool is_mapped() const noexcept;
bool empty() const noexcept { return length() == 0; }
size_type offset() const noexcept { return mapped_length_ - length_; }
size_type length() const noexcept { return length_; }
size_type mapped_length() const noexcept { return mapped_length_; }
size_type offset() const noexcept { return to_char_size(num_mapped_bytes_ - num_bytes_); }
size_type length() const noexcept { return to_char_size(num_bytes_); }
size_type mapped_length() const noexcept { return to_char_size(num_mapped_bytes_); }
pointer data() noexcept { return data_; }
const_pointer data() const noexcept { return data_; }
@ -135,9 +135,9 @@ public:
void set_offset(const size_type offset) noexcept;
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);
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);
void unmap();
void close();
@ -150,8 +150,18 @@ private:
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);
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>

View File

@ -49,7 +49,7 @@ inline DWORD int64_high(int64_t n) noexcept
inline DWORD int64_low(int64_t n) noexcept
{
return n & 0xff'ff'ff'ff;
return n & 0xffffffff;
}
#endif
@ -125,8 +125,8 @@ basic_mmap<CharT>::~basic_mmap()
template<typename CharT>
basic_mmap<CharT>::basic_mmap(basic_mmap<CharT>&& other)
: data_(std::move(other.data_))
, length_(std::move(other.length_))
, mapped_length_(std::move(other.mapped_length_))
, num_bytes_(std::move(other.num_bytes_))
, num_mapped_bytes_(std::move(other.num_mapped_bytes_))
, file_handle_(std::move(other.file_handle_))
#ifdef _WIN32
, 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_))
{
other.data_ = nullptr;
other.length_ = other.mapped_length_ = 0;
other.num_bytes_ = other.num_mapped_bytes_ = 0;
other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
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.
unmap();
data_ = std::move(other.data_);
length_ = std::move(other.length_);
mapped_length_ = std::move(other.mapped_length_);
num_bytes_ = std::move(other.num_bytes_);
num_mapped_bytes_ = std::move(other.num_mapped_bytes_);
file_handle_ = std::move(other.file_handle_);
#ifdef _WIN32
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
// destructor will unmap the same mapping that was just moved into this.
other.data_ = nullptr;
other.length_ = other.mapped_length_ = 0;
other.num_bytes_ = other.num_mapped_bytes_ = 0;
other.file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
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 String>
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();
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);
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.
is_handle_internal_ = true;
}
@ -203,7 +203,7 @@ void basic_mmap<CharT>::map(String& path, size_type offset,
template<typename CharT>
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();
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);
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);
return;
@ -227,17 +227,17 @@ void basic_mmap<CharT>::map(handle_type handle, size_type offset,
file_handle_ = handle;
is_handle_internal_ = false;
map(offset, length, mode, error);
map(offset, num_bytes, mode, error);
}
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 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
const size_type max_file_size = offset + length;
const size_type max_file_size = offset + num_bytes;
file_mapping_handle_ = ::CreateFileMapping(
file_handle_,
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,
int64_high(aligned_offset),
int64_low(aligned_offset),
length_to_map));
num_bytes_to_map));
if(mapping_start == nullptr)
{
error = last_error();
@ -265,7 +265,7 @@ void basic_mmap<CharT>::map(const size_type offset, const size_type length,
#else
const pointer mapping_start = static_cast<pointer>(::mmap(
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,
MAP_SHARED,
file_handle_,
@ -277,8 +277,8 @@ void basic_mmap<CharT>::map(const size_type offset, const size_type length,
}
#endif
data_ = mapping_start + offset - aligned_offset;
length_ = length;
mapped_length_ = length_to_map;
num_bytes_ = num_bytes;
num_mapped_bytes_ = num_bytes_to_map;
}
template<typename CharT>
@ -294,10 +294,10 @@ void basic_mmap<CharT>::sync(std::error_code& error)
if(data() != nullptr)
{
#ifdef _WIN32
if(::FlushViewOfFile(get_mapping_start(), mapped_length_) == 0
if(::FlushViewOfFile(get_mapping_start(), num_mapped_bytes_) == 0
|| ::FlushFileBuffers(file_handle_) == 0)
#else
if(::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0)
if(::msync(get_mapping_start(), num_mapped_bytes_, MS_SYNC) != 0)
#endif
{
error = last_error();
@ -325,7 +325,7 @@ void basic_mmap<CharT>::unmap()
file_mapping_handle_ = INVALID_HANDLE_VALUE;
}
#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
// 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.
data_ = nullptr;
length_ = mapped_length_ = 0;
num_bytes_ = num_mapped_bytes_ = 0;
file_handle_ = INVALID_HANDLE_VALUE;
#ifdef _WIN32
file_mapping_handle_ = INVALID_HANDLE_VALUE;
@ -377,7 +377,7 @@ template<typename CharT>
void basic_mmap<CharT>::set_length(const size_type length) noexcept
{
if(length > this->length() - offset()) { throw std::invalid_argument(""); }
length_ = length;
num_bytes_ = to_byte_size(length);
}
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(""); }
const auto diff = offset - this->offset();
data_ += diff;
length_ += -1 * diff;
num_bytes_ += -1 * to_byte_size(diff);
}
template<typename CharT>
@ -400,8 +400,8 @@ void basic_mmap<CharT>::swap(basic_mmap<CharT>& other)
#ifdef _WIN32
swap(file_mapping_handle_, other.file_mapping_handle_);
#endif
swap(length_, other.length_);
swap(mapped_length_, other.mapped_length_);
swap(num_bytes_, other.num_bytes_);
swap(num_mapped_bytes_, other.num_mapped_bytes_);
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
* is a multiple of the underlying operating system's page allocation granularity.
*/
size_type size() const noexcept { return char_size(impl_.length()); }
size_type length() const noexcept { return char_size(impl_.length()); }
size_type mapped_length() const noexcept { return char_size(impl_.mapped_length()); }
size_type size() const noexcept { return impl_.length(); }
size_type length() const noexcept { return impl_.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
* requested to be created, expressed in multiples of `sizeof(CharT)` rather than
* 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
@ -215,8 +215,8 @@ public:
* If `offset` is larger than the number of bytes mapped, an std::invalid_argument
* exception is thrown.
*/
void set_length(const size_type length) noexcept { impl_.set_length(byte_size(length)); }
void set_offset(const size_type offset) noexcept { impl_.set_offset(byte_size(offset)); }
void set_length(const size_type length) noexcept { impl_.set_length(length); }
void set_offset(const size_type offset) noexcept { impl_.set_offset(offset); }
/**
* Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the
@ -327,18 +327,6 @@ public:
{
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);
}
};
/**