Merge 22394fdd799756648f5769488e0ed55562e4312e into 8b6b7d878c89e81614d05edca7936de41ccdd2da

This commit is contained in:
Ivan Roberto de Oliveira 2023-03-03 10:40:40 +01:00 committed by GitHub
commit 85bfbccf0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1213 additions and 49 deletions

View File

@ -27,6 +27,10 @@
#include <algorithm>
#ifdef _WIN32
# include <vector>
#endif
#ifndef _WIN32
# include <unistd.h>
# include <fcntl.h>
@ -73,7 +77,7 @@ template<
> file_handle_type open_file_helper(const String& path, const access_mode mode)
{
return ::CreateFileW(s_2_ws(path).c_str(),
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
mode == access_mode::write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
@ -88,7 +92,7 @@ typename std::enable_if<
>::type open_file_helper(const String& path, const access_mode mode)
{
return ::CreateFileW(c_str(path),
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
mode == access_mode::write ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
@ -128,7 +132,7 @@ file_handle_type open_file(const String& path, const access_mode mode,
const auto handle = win::open_file_helper(path, mode);
#else // POSIX
const auto handle = ::open(c_str(path),
mode == access_mode::read ? O_RDONLY : O_RDWR);
mode == access_mode::write ? O_RDWR : O_RDONLY);
#endif
if(handle == invalid_handle)
{
@ -179,7 +183,8 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
const auto file_mapping_handle = ::CreateFileMapping(
file_handle,
0,
mode == access_mode::read ? PAGE_READONLY : PAGE_READWRITE,
mode == access_mode::read ? PAGE_READONLY :
mode == access_mode::write ? PAGE_READWRITE : PAGE_WRITECOPY,
win::int64_high(max_file_size),
win::int64_low(max_file_size),
0);
@ -190,7 +195,8 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
}
char* mapping_start = static_cast<char*>(::MapViewOfFile(
file_mapping_handle,
mode == access_mode::read ? FILE_MAP_READ : FILE_MAP_WRITE,
mode == access_mode::read ? FILE_MAP_READ :
mode == access_mode::write ? FILE_MAP_WRITE : FILE_MAP_COPY,
win::int64_high(aligned_offset),
win::int64_low(aligned_offset),
length_to_map));
@ -206,7 +212,7 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
0, // Don't give hint as to where to map.
length_to_map,
mode == access_mode::read ? PROT_READ : PROT_WRITE,
MAP_SHARED,
mode == access_mode::copy_on_write ? MAP_PRIVATE : MAP_SHARED,
file_handle,
aligned_offset));
if(mapping_start == MAP_FAILED)
@ -477,7 +483,7 @@ basic_mmap<AccessMode, ByteT>::conditional_sync()
template<access_mode AccessMode, typename ByteT>
template<access_mode A>
typename std::enable_if<A == access_mode::read, void>::type
typename std::enable_if<A != access_mode::write, void>::type
basic_mmap<AccessMode, ByteT>::conditional_sync()
{
// noop

View File

@ -192,7 +192,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> pointer data() noexcept { return data_; }
const_pointer data() const noexcept { return data_; }
@ -202,7 +202,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> iterator begin() noexcept { return data(); }
const_iterator begin() const noexcept { return data(); }
const_iterator cbegin() const noexcept { return data(); }
@ -213,7 +213,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> iterator end() noexcept { return data() + length(); }
const_iterator end() const noexcept { return data() + length(); }
const_iterator cend() const noexcept { return data() + length(); }
@ -225,7 +225,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const noexcept
{ return const_reverse_iterator(end()); }
@ -238,7 +238,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
const_reverse_iterator rend() const noexcept
{ return const_reverse_iterator(begin()); }
@ -359,7 +359,7 @@ public:
private:
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> pointer get_mapping_start() noexcept
{
return !data() ? nullptr : data() - mapping_offset();
@ -372,14 +372,15 @@ private:
/**
* The destructor syncs changes to disk if `AccessMode` is `write`, but not
* if it's `read`, but since the destructor cannot be templated, we need to
* do SFINAE in a dedicated function, where one syncs and the other is a noop.
* if it's `read` or `copy_on_write`, but since the destructor cannot be
* templated, we need to do SFINAE in a dedicated function, where one syncs
* and the other is a noop.
*/
template<access_mode A = AccessMode>
typename std::enable_if<A == access_mode::write, void>::type
conditional_sync();
template<access_mode A = AccessMode>
typename std::enable_if<A == access_mode::read, void>::type conditional_sync();
typename std::enable_if<A != access_mode::write, void>::type conditional_sync();
};
template<access_mode AccessMode, typename ByteT>
@ -420,6 +421,13 @@ using basic_mmap_source = basic_mmap<access_mode::read, ByteT>;
template<typename ByteT>
using basic_mmap_sink = basic_mmap<access_mode::write, ByteT>;
/**
* This is the basis for all copy-on-write mmap objects and should be preferred over
* directly using `basic_mmap`.
*/
template<typename ByteT>
using basic_mmap_cow_sink = basic_mmap<access_mode::copy_on_write, ByteT>;
/**
* These aliases cover the most common use cases, both representing a raw byte stream
* (either with a char or an unsigned char/uint8_t).
@ -430,6 +438,9 @@ using ummap_source = basic_mmap_source<unsigned char>;
using mmap_sink = basic_mmap_sink<char>;
using ummap_sink = basic_mmap_sink<unsigned char>;
using mmap_cow_sink = basic_mmap_cow_sink<char>;
using ummap_cow_sink = basic_mmap_cow_sink<unsigned char>;
/**
* Convenience factory method that constructs a mapping for any `basic_mmap` or
* `basic_mmap` type.
@ -485,6 +496,27 @@ mmap_sink make_mmap_sink(const MappingToken& token, std::error_code& error)
return make_mmap_sink(token, 0, map_entire_file, error);
}
/**
* Convenience factory method.
*
* MappingToken may be a String (`std::string`, `std::string_view`, `const char*`,
* `std::filesystem::path`, `std::vector<char>`, or similar), or a
* `mmap_sink::handle_type`.
*/
template<typename MappingToken>
mmap_cow_sink make_mmap_cow_sink(const MappingToken& token,
mmap_cow_sink::size_type offset, mmap_cow_sink::size_type length,
std::error_code& error)
{
return make_mmap<mmap_cow_sink>(token, offset, length, error);
}
template<typename MappingToken>
mmap_cow_sink make_mmap_cow_sink(const MappingToken& token, std::error_code& error)
{
return make_mmap_cow_sink(token, 0, map_entire_file, error);
}
} // namespace mio
#include "detail/mmap.ipp"

View File

@ -30,13 +30,14 @@
namespace mio {
/**
* This is used by `basic_mmap` to determine whether to create a read-only or
* a read-write memory mapping.
* This is used by `basic_mmap` to determine whether to create a read-only,
* a read-write or a copy-on-write memory mapping.
*/
enum class access_mode
{
read,
write
write,
copy_on_write
};
/**

View File

@ -168,7 +168,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> pointer data() noexcept { return pimpl_->data(); }
const_pointer data() const noexcept { return pimpl_ ? pimpl_->data() : nullptr; }
@ -186,7 +186,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> iterator end() noexcept { return pimpl_->end(); }
const_iterator end() const noexcept { return pimpl_->end(); }
const_iterator cend() const noexcept { return pimpl_->cend(); }
@ -198,7 +198,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> reverse_iterator rbegin() noexcept { return pimpl_->rbegin(); }
const_reverse_iterator rbegin() const noexcept { return pimpl_->rbegin(); }
const_reverse_iterator crbegin() const noexcept { return pimpl_->crbegin(); }
@ -209,7 +209,7 @@ public:
*/
template<
access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type
typename = typename std::enable_if<A != access_mode::read>::type
> reverse_iterator rend() noexcept { return pimpl_->rend(); }
const_reverse_iterator rend() const noexcept { return pimpl_->rend(); }
const_reverse_iterator crend() const noexcept { return pimpl_->crend(); }
@ -391,6 +391,13 @@ using basic_shared_mmap_source = basic_shared_mmap<access_mode::read, ByteT>;
template<typename ByteT>
using basic_shared_mmap_sink = basic_shared_mmap<access_mode::write, ByteT>;
/**
* This is the basis for all copy-on-write mmap objects and should be preferred over
* directly using basic_shared_mmap.
*/
template<typename ByteT>
using basic_shared_mmap_cow_sink = basic_shared_mmap<access_mode::copy_on_write, ByteT>;
/**
* These aliases cover the most common use cases, both representing a raw byte stream
* (either with a char or an unsigned char/uint8_t).
@ -401,6 +408,9 @@ using shared_ummap_source = basic_shared_mmap_source<unsigned char>;
using shared_mmap_sink = basic_shared_mmap_sink<char>;
using shared_ummap_sink = basic_shared_mmap_sink<unsigned char>;
using shared_mmap_cow_sink = basic_shared_mmap_cow_sink<char>;
using shared_ummap_cow_sink = basic_shared_mmap_cow_sink<unsigned char>;
} // namespace mio
#endif // MIO_SHARED_MMAP_HEADER

File diff suppressed because it is too large Load Diff