mirror of
https://github.com/vimpunk/mio.git
synced 2025-12-06 16:57:01 +08:00
bugfix, updated README
This commit is contained in:
parent
0d94b74491
commit
2024c807f0
17
README.md
17
README.md
@ -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.
|
||||
try {
|
||||
const auto page_size = mio::page_size();
|
||||
try {
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user