Create destructor sync policy

This commit is contained in:
mandreyel 2018-10-22 15:22:02 +02:00
parent 865d7f35ce
commit 50bfe8087a
3 changed files with 101 additions and 76 deletions

View File

@ -185,15 +185,15 @@ inline mmap_context memory_map(const file_handle_type file_handle, const int64_t
// -- basic_mmap --
template<access_mode AccessMode, typename ByteT>
basic_mmap<AccessMode, ByteT>::~basic_mmap()
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
basic_mmap<AccessMode, ByteT, DtorPolicy>::~basic_mmap()
{
conditional_sync();
unmap();
}
template<access_mode AccessMode, typename ByteT>
basic_mmap<AccessMode, ByteT>::basic_mmap(basic_mmap&& other)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
basic_mmap<AccessMode, ByteT, DtorPolicy>::basic_mmap(basic_mmap&& other)
: data_(std::move(other.data_))
, length_(std::move(other.length_))
, mapped_length_(std::move(other.mapped_length_))
@ -211,9 +211,9 @@ basic_mmap<AccessMode, ByteT>::basic_mmap(basic_mmap&& other)
#endif
}
template<access_mode AccessMode, typename ByteT>
basic_mmap<AccessMode, ByteT>&
basic_mmap<AccessMode, ByteT>::operator=(basic_mmap&& other)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
basic_mmap<AccessMode, ByteT, DtorPolicy>&
basic_mmap<AccessMode, ByteT, DtorPolicy>::operator=(basic_mmap&& other)
{
if(this != &other)
{
@ -242,9 +242,9 @@ basic_mmap<AccessMode, ByteT>::operator=(basic_mmap&& other)
return *this;
}
template<access_mode AccessMode, typename ByteT>
typename basic_mmap<AccessMode, ByteT>::handle_type
basic_mmap<AccessMode, ByteT>::mapping_handle() const noexcept
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
typename basic_mmap<AccessMode, ByteT, DtorPolicy>::handle_type
basic_mmap<AccessMode, ByteT, DtorPolicy>::mapping_handle() const noexcept
{
#ifdef _WIN32
return file_mapping_handle_;
@ -253,9 +253,9 @@ basic_mmap<AccessMode, ByteT>::mapping_handle() const noexcept
#endif
}
template<access_mode AccessMode, typename ByteT>
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
template<typename String>
void basic_mmap<AccessMode, ByteT>::map(const String& path, const size_type offset,
void basic_mmap<AccessMode, ByteT, DtorPolicy>::map(const String& path, const size_type offset,
const size_type length, std::error_code& error)
{
error.clear();
@ -278,8 +278,8 @@ void basic_mmap<AccessMode, ByteT>::map(const String& path, const size_type offs
}
}
template<access_mode AccessMode, typename ByteT>
void basic_mmap<AccessMode, ByteT>::map(const handle_type handle,
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
void basic_mmap<AccessMode, ByteT, DtorPolicy>::map(const handle_type handle,
const size_type offset, const size_type length, std::error_code& error)
{
error.clear();
@ -323,9 +323,9 @@ void basic_mmap<AccessMode, ByteT>::map(const handle_type handle,
}
}
template<access_mode AccessMode, typename ByteT>
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
template<access_mode, typename /*SFINAE*/>
void basic_mmap<AccessMode, ByteT>::sync(std::error_code& error)
void basic_mmap<AccessMode, ByteT, DtorPolicy>::sync(std::error_code& error)
{
error.clear();
if(!is_open())
@ -355,8 +355,8 @@ void basic_mmap<AccessMode, ByteT>::sync(std::error_code& error)
#endif
}
template<access_mode AccessMode, typename ByteT>
void basic_mmap<AccessMode, ByteT>::unmap()
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
void basic_mmap<AccessMode, ByteT, DtorPolicy>::unmap()
{
if(!is_open()) { return; }
// TODO do we care about errors here?
@ -391,8 +391,8 @@ void basic_mmap<AccessMode, ByteT>::unmap()
#endif
}
template<access_mode AccessMode, typename ByteT>
bool basic_mmap<AccessMode, ByteT>::is_mapped() const noexcept
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool basic_mmap<AccessMode, ByteT, DtorPolicy>::is_mapped() const noexcept
{
#ifdef _WIN32
return file_mapping_handle_ != invalid_handle;
@ -401,8 +401,8 @@ bool basic_mmap<AccessMode, ByteT>::is_mapped() const noexcept
#endif
}
template<access_mode AccessMode, typename ByteT>
void basic_mmap<AccessMode, ByteT>::swap(basic_mmap& other)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
void basic_mmap<AccessMode, ByteT, DtorPolicy>::swap(basic_mmap& other)
{
if(this != &other)
{
@ -418,47 +418,47 @@ void basic_mmap<AccessMode, ByteT>::swap(basic_mmap& other)
}
}
template<access_mode AccessMode, typename ByteT>
bool operator==(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator==(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
return a.data() == b.data()
&& a.size() == b.size();
}
template<access_mode AccessMode, typename ByteT>
bool operator!=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator!=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
return !(a == b);
}
template<access_mode AccessMode, typename ByteT>
bool operator<(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator<(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
if(a.data() == b.data()) { return a.size() < b.size(); }
return a.data() < b.data();
}
template<access_mode AccessMode, typename ByteT>
bool operator<=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator<=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
return !(a > b);
}
template<access_mode AccessMode, typename ByteT>
bool operator>(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator>(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
if(a.data() == b.data()) { return a.size() > b.size(); }
return a.data() > b.data();
}
template<access_mode AccessMode, typename ByteT>
bool operator>=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b)
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator>=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b)
{
return !(a < b);
}

View File

@ -53,8 +53,17 @@ using file_handle_type = int;
// determine whether `basic_mmap::file_handle` is valid, for example.
constexpr static file_handle_type invalid_handle = INVALID_HANDLE_VALUE;
template<access_mode AccessMode, typename ByteT>
struct basic_mmap
// `basic_mmap`'s constructor syncs changes to disk if it's in write mode, but
// some user's may prefer the absence of this feature and instead syncing
// manually. This optional template parameter may be used to change this
// beharior.
enum class dtor_policy { sync, no_sync, };
template<
access_mode AccessMode,
typename ByteT,
dtor_policy DtorPolicy = dtor_policy::sync
> struct basic_mmap
{
using value_type = ByteT;
using size_type = int64_t;
@ -70,7 +79,8 @@ struct basic_mmap
using iterator_category = std::random_access_iterator_tag;
using handle_type = file_handle_type;
static_assert(sizeof(ByteT) == sizeof(char), "ByteT must be the same size as char.");
static_assert(sizeof(ByteT) == sizeof(char),
"ByteT must be the same size as char.");
private:
// Points to the first requested byte, and not to the actual start of the mapping.
@ -331,50 +341,64 @@ private:
* 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.
*/
template<access_mode A = AccessMode,
typename = typename std::enable_if<A == access_mode::write>::type>
void conditional_sync() { sync(); }
template<access_mode A = AccessMode>
typename std::enable_if<A == access_mode::read, void>::type conditional_sync() {}
template<
access_mode A = AccessMode,
dtor_policy D = DtorPolicy,
typename = typename std::enable_if<
A == access_mode::write and D == dtor_policy::sync
>::type
> void conditional_sync()
{
// Not much we can do about errors in the destructor.
std::error_code ec;
sync(ec);
}
template<
access_mode A = AccessMode,
dtor_policy D = DtorPolicy
> typename std::enable_if<
A == access_mode::read or D == dtor_policy::no_sync, void
>::type conditional_sync() {}
};
template<access_mode AccessMode, typename ByteT>
bool operator==(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator==(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
template<access_mode AccessMode, typename ByteT>
bool operator!=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator!=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
template<access_mode AccessMode, typename ByteT>
bool operator<(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator<(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
template<access_mode AccessMode, typename ByteT>
bool operator<=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator<=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
template<access_mode AccessMode, typename ByteT>
bool operator>(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator>(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
template<access_mode AccessMode, typename ByteT>
bool operator>=(const basic_mmap<AccessMode, ByteT>& a,
const basic_mmap<AccessMode, ByteT>& b);
template<access_mode AccessMode, typename ByteT, dtor_policy DtorPolicy>
bool operator>=(const basic_mmap<AccessMode, ByteT, DtorPolicy>& a,
const basic_mmap<AccessMode, ByteT, DtorPolicy>& b);
/**
* This is the basis for all read-only mmap objects and should be preferred over
* directly using `basic_mmap`.
*/
template<typename ByteT>
using basic_mmap_source = basic_mmap<access_mode::read, ByteT>;
template<typename ByteT, dtor_policy DtorPolicy = dtor_policy::sync>
using basic_mmap_source = basic_mmap<access_mode::read, ByteT, DtorPolicy>;
/**
* This is the basis for all read-write mmap objects and should be preferred over
* directly using `basic_mmap`.
*/
template<typename ByteT>
using basic_mmap_sink = basic_mmap<access_mode::write, ByteT>;
template<typename ByteT, dtor_policy DtorPolicy = dtor_policy::sync>
using basic_mmap_sink = basic_mmap<access_mode::write, ByteT, DtorPolicy>;
/**
* These aliases cover the most common use cases, both representing a raw byte stream

View File

@ -37,10 +37,11 @@ namespace mio {
*/
template<
access_mode AccessMode,
typename ByteT
typename ByteT,
dtor_policy DtorPolicy = dtor_policy::sync
> class basic_shared_mmap
{
using impl_type = basic_mmap<AccessMode, ByteT>;
using impl_type = basic_mmap<AccessMode, ByteT, DtorPolicy>;
std::shared_ptr<impl_type> pimpl_;
public:
@ -344,15 +345,15 @@ private:
* This is the basis for all read-only mmap objects and should be preferred over
* directly using basic_shared_mmap.
*/
template<typename ByteT>
using basic_shared_mmap_source = basic_shared_mmap<access_mode::read, ByteT>;
template<typename ByteT, dtor_policy DtorPolicy = dtor_policy::sync>
using basic_shared_mmap_source = basic_shared_mmap<access_mode::read, ByteT, DtorPolicy>;
/**
* This is the basis for all read-write mmap objects and should be preferred over
* directly using basic_shared_mmap.
*/
template<typename ByteT>
using basic_shared_mmap_sink = basic_shared_mmap<access_mode::write, ByteT>;
template<typename ByteT, dtor_policy DtorPolicy = dtor_policy::sync>
using basic_shared_mmap_sink = basic_shared_mmap<access_mode::write, ByteT, DtorPolicy>;
/**
* These aliases cover the most common use cases, both representing a raw byte stream