From 1a88259c026ff65f154774c0fbb3aeea72b75bf7 Mon Sep 17 00:00:00 2001 From: mandreyel Date: Wed, 4 Oct 2017 21:41:18 +0200 Subject: [PATCH] converted mio to templatize the char type --- include/mio/detail/mmap_impl.hpp | 44 +++++++++------- include/mio/detail/mmap_impl.ipp | 76 +++++++++++++++++---------- include/mio/mmap.hpp | 90 +++++++++++++++++--------------- 3 files changed, 121 insertions(+), 89 deletions(-) diff --git a/include/mio/detail/mmap_impl.hpp b/include/mio/detail/mmap_impl.hpp index 88bbbbd..2f7107f 100644 --- a/include/mio/detail/mmap_impl.hpp +++ b/include/mio/detail/mmap_impl.hpp @@ -37,11 +37,18 @@ namespace mio { namespace detail { +template struct basic_mmap; + +template +bool operator==(const basic_mmap& a, const basic_mmap& b); +template +bool operator!=(const basic_mmap& a, const basic_mmap& b); + size_t page_size(); -struct mmap +template struct basic_mmap { - using value_type = char; + using value_type = CharT; using size_type = int64_t; using reference = value_type&; using const_reference = const value_type&; @@ -93,12 +100,12 @@ private: public: - mmap() = default; - mmap(const mmap&) = delete; - mmap& operator=(const mmap&) = delete; - mmap(mmap&&); - mmap& operator=(mmap&&); - ~mmap(); + basic_mmap() = default; + basic_mmap(const basic_mmap&) = delete; + basic_mmap& operator=(const basic_mmap&) = delete; + basic_mmap(basic_mmap&&); + basic_mmap& operator=(basic_mmap&&); + ~basic_mmap(); handle_type file_handle() const noexcept { return file_handle_; } handle_type mapping_handle() const noexcept; @@ -107,9 +114,10 @@ public: bool is_mapped() const noexcept; bool empty() const noexcept { return length() == 0; } - size_type size() const noexcept { return length_; } - size_type length() const noexcept { return length_; } - size_type mapped_length() const noexcept { return mapped_length_; } + // TODO return the number of BYTES or the number of times sizeof(CharT) fits into length_? + size_type size() const noexcept { return length_ >> sizeof(CharT); } + size_type length() const noexcept { return length_ >> sizeof(CharT); } + size_type mapped_length() const noexcept { return mapped_length_ >> sizeof(CharT); } pointer data() noexcept { return data_; } const_pointer data() const noexcept { return data_; } @@ -134,19 +142,19 @@ public: const_reference operator[](const size_type i) const noexcept { return data_[i]; } template - void map(const String& path, const size_type offset, const size_type length, - const access_mode mode, std::error_code& error); - void map(const handle_type handle, const size_type offset, const size_type length, - const access_mode mode, std::error_code& error); + void map(String& path, size_type offset, size_type length, + access_mode mode, std::error_code& error); + void map(handle_type handle, size_type offset, size_type length, + access_mode mode, std::error_code& error); void unmap(); void close(); void sync(std::error_code& error); - void swap(mmap& other); + void swap(basic_mmap& other); - friend bool operator==(const mmap& a, const mmap& b); - friend bool operator!=(const mmap& a, const mmap& b); + friend bool operator==(const basic_mmap& a, const basic_mmap& b); + friend bool operator!=(const basic_mmap& a, const basic_mmap& b); private: diff --git a/include/mio/detail/mmap_impl.ipp b/include/mio/detail/mmap_impl.ipp index 5fe022a..c254507 100644 --- a/include/mio/detail/mmap_impl.ipp +++ b/include/mio/detail/mmap_impl.ipp @@ -37,6 +37,8 @@ namespace mio { namespace detail { +using handle_type = basic_mmap::handle_type; + #if defined(_WIN32) inline DWORD int64_high(int64_t n) noexcept { @@ -64,11 +66,11 @@ inline size_t page_size() return page_size; } -inline size_t make_page_aligned(size_t offset) noexcept +inline size_t make_page_aligned(size_t t) noexcept { const static size_t page_size_ = page_size(); // Use integer division to round down to the nearest page alignment. - return offset / page_size_ * page_size_; + return t / page_size_ * page_size_; } inline std::error_code last_error() noexcept @@ -83,8 +85,8 @@ inline std::error_code last_error() noexcept } template -mmap::handle_type open_file(const Path& path, - const mmap::access_mode mode, std::error_code& error) +handle_type open_file(const Path& path, + const basic_mmap::access_mode mode, std::error_code& error) { error.clear(); if(detail::empty(path)) @@ -94,7 +96,7 @@ mmap::handle_type open_file(const Path& path, } #if defined(_WIN32) const auto handle = ::CreateFile(c_str(path), - mode == mmap::access_mode::read_only + mode == basic_mmap::access_mode::read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, @@ -103,7 +105,7 @@ mmap::handle_type open_file(const Path& path, 0); #else const auto handle = ::open(c_str(path), - mode == mmap::access_mode::read_only ? O_RDONLY : O_RDWR); + mode == basic_mmap::access_mode::read_only ? O_RDONLY : O_RDWR); #endif if(handle == INVALID_HANDLE_VALUE) { @@ -112,7 +114,7 @@ mmap::handle_type open_file(const Path& path, return handle; } -inline mmap::size_type query_file_size(mmap::handle_type handle, std::error_code& error) +int64_t query_file_size(handle_type handle, std::error_code& error) { error.clear(); #ifdef _WIN32 @@ -122,7 +124,7 @@ inline mmap::size_type query_file_size(mmap::handle_type handle, std::error_code error = last_error(); return 0; } - return static_cast(file_size.QuadPart); + return static_cast(file_size.QuadPart); #else struct stat sbuf; if(::fstat(handle, &sbuf) == -1) @@ -134,14 +136,16 @@ inline mmap::size_type query_file_size(mmap::handle_type handle, std::error_code #endif } -// -- mmap -- +// -- basic_mmap -- -inline mmap::~mmap() +template +basic_mmap::~basic_mmap() { unmap(); } -inline mmap::mmap(mmap&& other) +template +basic_mmap::basic_mmap(basic_mmap&& other) : data_(std::move(other.data_)) , length_(std::move(other.length_)) , mapped_length_(std::move(other.mapped_length_)) @@ -159,7 +163,8 @@ inline mmap::mmap(mmap&& other) #endif } -inline mmap& mmap::operator=(mmap&& other) +template +basic_mmap& basic_mmap::operator=(basic_mmap&& other) { if(this != &other) { @@ -174,7 +179,7 @@ inline mmap& mmap::operator=(mmap&& other) #endif is_handle_internal_ = std::move(other.is_handle_internal_); - // The moved from 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. other.data_ = nullptr; other.length_ = other.mapped_length_ = 0; @@ -187,7 +192,9 @@ inline mmap& mmap::operator=(mmap&& other) return *this; } -inline mmap::handle_type mmap::mapping_handle() const noexcept +template +typename basic_mmap::handle_type +basic_mmap::mapping_handle() const noexcept { #ifdef _WIN32 return file_mapping_handle_; @@ -196,9 +203,10 @@ inline mmap::handle_type mmap::mapping_handle() const noexcept #endif } +template template -void mmap::map(const String& path, const size_type offset, const size_type length, - const access_mode mode, std::error_code& error) +void basic_mmap::map(String& path, size_type offset, + size_type length, access_mode mode, std::error_code& error) { error.clear(); if(detail::empty(path)) @@ -216,8 +224,9 @@ void mmap::map(const String& path, const size_type offset, const size_type lengt } } -inline void mmap::map(const handle_type handle, const size_type offset, - size_type length, const access_mode mode, std::error_code& error) +template +void basic_mmap::map(handle_type handle, size_type offset, + size_type length, access_mode mode, std::error_code& error) { error.clear(); if(handle == INVALID_HANDLE_VALUE) @@ -244,7 +253,8 @@ inline void mmap::map(const handle_type handle, const size_type offset, map(offset, length, mode, error); } -inline void mmap::map(const size_type offset, const size_type length, +template +void basic_mmap::map(const size_type offset, const size_type length, const access_mode mode, std::error_code& error) { const size_type aligned_offset = make_page_aligned(offset); @@ -279,7 +289,7 @@ inline void mmap::map(const size_type offset, const size_type length, const pointer mapping_start = static_cast(::mmap( 0, // Don't give hint as to where to map. length_to_map, - mode == mmap::access_mode::read_only ? PROT_READ : PROT_WRITE, + mode == basic_mmap::access_mode::read_only ? PROT_READ : PROT_WRITE, MAP_SHARED, // TODO do we want to share it? file_handle_, aligned_offset)); @@ -294,7 +304,8 @@ inline void mmap::map(const size_type offset, const size_type length, mapped_length_ = length_to_map; } -inline void mmap::sync(std::error_code& error) +template +void basic_mmap::sync(std::error_code& error) { error.clear(); if(!is_open()) @@ -324,7 +335,8 @@ inline void mmap::sync(std::error_code& error) #endif } -inline void mmap::unmap() +template +void basic_mmap::unmap() { if(!is_open()) { return; } // TODO do we care about errors here? @@ -341,7 +353,7 @@ inline void mmap::unmap() // If file handle was obtained by our opening it (when map is called with a path, // rather than an existing file handle), we need to close it, otherwise it must not - // be closed as it may still be used outside of this mmap instance. + // be closed as it may still be used outside of this basic_mmap instance. if(is_handle_internal_) { #ifdef _WIN32 @@ -360,19 +372,22 @@ inline void mmap::unmap() #endif } -inline mmap::pointer mmap::get_mapping_start() noexcept +template +typename basic_mmap::pointer basic_mmap::get_mapping_start() noexcept { if(!data_) { return nullptr; } const auto offset = mapped_length_ - length_; return data_ - offset; } -inline bool mmap::is_open() const noexcept +template +bool basic_mmap::is_open() const noexcept { return file_handle_ != INVALID_HANDLE_VALUE; } -inline bool mmap::is_mapped() const noexcept +template +bool basic_mmap::is_mapped() const noexcept { #ifdef _WIN32 return file_mapping_handle_ != INVALID_HANDLE_VALUE; @@ -381,7 +396,8 @@ inline bool mmap::is_mapped() const noexcept #endif } -inline void mmap::swap(mmap& other) +template +void basic_mmap::swap(basic_mmap& other) { if(this != &other) { @@ -397,7 +413,8 @@ inline void mmap::swap(mmap& other) } } -inline bool operator==(const mmap& a, const mmap& b) +template +bool operator==(const basic_mmap& a, const basic_mmap& b) { if(a.is_mapped() && b.is_mapped()) { @@ -406,7 +423,8 @@ inline bool operator==(const mmap& a, const mmap& b) return !a.is_mapped() && !b.is_mapped(); } -inline bool operator!=(const mmap& a, const mmap& b) +template +bool operator!=(const basic_mmap& a, const basic_mmap& b) { return !(a == b); } diff --git a/include/mio/mmap.hpp b/include/mio/mmap.hpp index 9af5619..ea1cc23 100644 --- a/include/mio/mmap.hpp +++ b/include/mio/mmap.hpp @@ -28,26 +28,26 @@ namespace mio { /** A read-only file memory mapping. */ -class mmap_source +template class basic_mmap_source { - using impl_type = detail::mmap; + using impl_type = detail::basic_mmap; impl_type impl_; public: - using value_type = impl_type::value_type; - using size_type = impl_type::size_type; - using reference = impl_type::reference; - using const_reference = impl_type::const_reference; - using pointer = impl_type::pointer; - using const_pointer = impl_type::const_pointer; - using difference_type = impl_type::difference_type; - using iterator = impl_type::iterator; - using const_iterator = impl_type::const_iterator; + using value_type = typename impl_type::value_type; + using size_type = typename impl_type::size_type; + using reference = typename impl_type::reference; + using const_reference = typename impl_type::const_reference; + using pointer = typename impl_type::pointer; + using const_pointer = typename impl_type::const_pointer; + using difference_type = typename impl_type::difference_type; + using iterator = typename impl_type::iterator; + using const_iterator = typename impl_type::const_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - using iterator_category = impl_type::iterator_category; - using handle_type = impl_type::handle_type; + using iterator_category = typename impl_type::iterator_category; + using handle_type = typename impl_type::handle_type; /** * This value may be provided as the `length` parameter to the constructor or @@ -60,7 +60,7 @@ public: * operations that attempt to access nonexistent underlying date will result in * undefined behaviour/segmentation faults. */ - mmap_source() = default; + basic_mmap_source() = default; /** * `handle` must be a valid file handle, which is then used to memory map the @@ -73,7 +73,7 @@ public: * returned by `data` or `begin`), so long as `offset` is valid, will be at `offset` * from the start of the file. */ - mmap_source(const handle_type handle, const size_type offset, const size_type length) + basic_mmap_source(const handle_type handle, const size_type offset, const size_type length) { std::error_code error; map(handle, offset, length, error); @@ -84,11 +84,11 @@ public: * This class has single-ownership semantics, so transferring ownership may only be * accomplished by moving the object. */ - mmap_source(mmap_source&&) = default; - mmap_source& operator=(mmap_source&&) = default; + basic_mmap_source(basic_mmap_source&&) = default; + basic_mmap_source& operator=(basic_mmap_source&&) = default; /** The destructor invokes unmap. */ - ~mmap_source() = default; + ~basic_mmap_source() = default; /** * On UNIX systems 'file_handle' and 'mapping_handle' are the same. On Windows, @@ -206,40 +206,40 @@ public: */ void unmap() { impl_.unmap(); } - void swap(mmap_source& other) { impl_.swap(other.impl_); } + void swap(basic_mmap_source& other) { impl_.swap(other.impl_); } - friend bool operator==(const mmap_source& a, const mmap_source& b) + friend bool operator==(const basic_mmap_source& a, const basic_mmap_source& b) { return a.impl_ == b.impl_; } - friend bool operator!=(const mmap_source& a, const mmap_source& b) + friend bool operator!=(const basic_mmap_source& a, const basic_mmap_source& b) { return !(a == b); } }; /** A read-write file memory mapping. */ -class mmap_sink +template class basic_mmap_sink { - using impl_type = detail::mmap; + using impl_type = detail::basic_mmap; impl_type impl_; public: - using value_type = impl_type::value_type; - using size_type = impl_type::size_type; - using reference = impl_type::reference; - using const_reference = impl_type::const_reference; - using pointer = impl_type::pointer; - using const_pointer = impl_type::const_pointer; - using difference_type = impl_type::difference_type; - using iterator = impl_type::iterator; - using const_iterator = impl_type::const_iterator; + using value_type = typename impl_type::value_type; + using size_type = typename impl_type::size_type; + using reference = typename impl_type::reference; + using const_reference = typename impl_type::const_reference; + using pointer = typename impl_type::pointer; + using const_pointer = typename impl_type::const_pointer; + using difference_type = typename impl_type::difference_type; + using iterator = typename impl_type::iterator; + using const_iterator = typename impl_type::const_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - using iterator_category = impl_type::iterator_category; - using handle_type = impl_type::handle_type; + using iterator_category = typename impl_type::iterator_category; + using handle_type = typename impl_type::handle_type; /** * This value may be provided as the `length` parameter to the constructor or @@ -252,7 +252,7 @@ public: * operations that attempt to access nonexistent underlying date will result in * undefined behaviour/segmentation faults. */ - mmap_sink() = default; + basic_mmap_sink() = default; /** * `handle` must be a valid file handle, which is then used to memory map the @@ -265,7 +265,7 @@ public: * returned by `data` or `begin`), so long as `offset` is valid, will be at `offset` * from the start of the file. */ - mmap_sink(const handle_type handle, const size_type offset, const size_type length) + basic_mmap_sink(const handle_type handle, const size_type offset, const size_type length) { std::error_code error; map(handle, offset, length, error); @@ -276,15 +276,15 @@ public: * This class has single-ownership semantics, so transferring ownership may only be * accomplished by moving the object. */ - mmap_sink(mmap_sink&&) = default; - mmap_sink& operator=(mmap_sink&&) = default; + basic_mmap_sink(basic_mmap_sink&&) = default; + basic_mmap_sink& operator=(basic_mmap_sink&&) = default; /** * The destructor invokes unmap, but does NOT invoke `sync`. Thus, if the mapped * region has been written to, `sync` needs to be called in order to persist the * changes to disk. */ - ~mmap_sink() = default; + ~basic_mmap_sink() = default; /** * On UNIX systems 'file_handle' and 'mapping_handle' are the same. On Windows, @@ -411,19 +411,25 @@ public: /** Flushes the memory mapped page to disk. */ void sync(std::error_code& error) { impl_.sync(error); } - void swap(mmap_sink& other) { impl_.swap(other.impl_); } + void swap(basic_mmap_sink& other) { impl_.swap(other.impl_); } - friend bool operator==(const mmap_sink& a, const mmap_sink& b) + friend bool operator==(const basic_mmap_sink& a, const basic_mmap_sink& b) { return a.impl_ == b.impl_; } - friend bool operator!=(const mmap_sink& a, const mmap_sink& b) + friend bool operator!=(const basic_mmap_sink& a, const basic_mmap_sink& b) { return !(a == b); } }; +using mmap_source = basic_mmap_source; +using ummap_source = basic_mmap_source; + +using mmap_sink = basic_mmap_sink; +using ummap_sink = basic_mmap_sink; + /** * Convenience factory method. *