From 7bb887e88c78996dba3013aeb4597b517dae839d Mon Sep 17 00:00:00 2001 From: mandreyel Date: Mon, 12 Feb 2018 13:14:07 +0100 Subject: [PATCH 1/5] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5f511d1..ed46f6d 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Please feel free to open an issue, I'll try to address any concerns as best I ca ### Why? The primary motivation for writing this library instead of using Boost.Iostreams, was the lack of support for establishing a memory mapping with an already open file handle/descriptor. This is possible with mio. +Furthermore, Boost.Iostreams' solution requires that the user pick offsets exactly at page boundaries, which is cumbersome and error prone. mio, on the other hand, manages this internally, accepting any offset and finding the nearest page boundary. + Albeit a minor nitpick, Boost.Iostreams implements memory mapped file IO with a `std::shared_ptr` to provide shared semantics, even if not needed, and the overhead of the heap allocation may be unnecessary and/or unwanted. In mio, there are two classes to cover the two use-cases: one that is move-only (basically a zero-cost abstraction over the system specific mmapping functions), and the other that acts just like its Boost.Iostreams counterpart, with shared semantics. From 742469621a50d9f6b544f322a0b655b2ed4c2023 Mon Sep 17 00:00:00 2001 From: mandreyel Date: Fri, 2 Mar 2018 12:28:23 +0100 Subject: [PATCH 2/5] Update example --- README.md | 11 +++++------ test/example.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ed46f6d..b1b848c 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ However, mio does not check whether the provided file descriptor has the same ac #include // for std::error_code #include // for std::printf #include +#include int handle_error(const std::error_code& error) { @@ -73,16 +74,14 @@ int main() std::error_code error; mio::mmap_sink rw_mmap = mio::make_mmap_sink( "file.txt", 0, mio::map_entire_file, error); - if(error) { return handle_error(error); } - assert(rw_mmap.is_open()); - assert(!rw_mmap.empty()); + if (error) { return handle_error(error); } // You can use any iterator based function. std::fill(rw_mmap.begin(), rw_mmap.end(), 0); // Or manually iterate through the mapped region just as if it were any other // container, and change each byte's value (since this is a read-write mapping). - for(auto& b : rw_mmap) { + for (auto& b : rw_mmap) { b += 10; } @@ -93,7 +92,7 @@ int main() // Don't forget to flush changes to disk, which is NOT done by the destructor for // more explicit control of this potentially expensive operation. rw_mmap.sync(error); - if(error) { handle_error(error); } + if (error) { return handle_error(error); } // We can then remove the mapping, after which rw_mmap will be in a default // constructed state, i.e. this has the same effect as if the destructor had been @@ -103,7 +102,7 @@ int main() // Now create the same mapping, but in read-only mode. mio::mmap_source ro_mmap = mio::make_mmap_source( "file.txt", 0, mio::map_entire_file, error); - if(error) { return handle_error(error); } + if (error) { return handle_error(error); } const int the_answer_to_everything = ro_mmap[answer_index]; assert(the_answer_to_everything == 42); diff --git a/test/example.cpp b/test/example.cpp index bfb294f..5385ffc 100644 --- a/test/example.cpp +++ b/test/example.cpp @@ -18,14 +18,14 @@ int main() std::error_code error; mio::mmap_sink rw_mmap = mio::make_mmap_sink( "file.txt", 0, mio::map_entire_file, error); - if(error) { return handle_error(error); } + if (error) { return handle_error(error); } // You can use any iterator based function. std::fill(rw_mmap.begin(), rw_mmap.end(), 0); // Or manually iterate through the mapped region just as if it were any other // container, and change each byte's value (since this is a read-write mapping). - for(auto& b : rw_mmap) { + for (auto& b : rw_mmap) { b += 10; } @@ -36,7 +36,7 @@ int main() // Don't forget to flush changes to disk, which is NOT done by the destructor for // more explicit control of this potentially expensive operation. rw_mmap.sync(error); - if(error) { handle_error(error); } + if (error) { return handle_error(error); } // We can then remove the mapping, after which rw_mmap will be in a default // constructed state, i.e. this has the same effect as if the destructor had been @@ -46,7 +46,7 @@ int main() // Now create the same mapping, but in read-only mode. mio::mmap_source ro_mmap = mio::make_mmap_source( "file.txt", 0, mio::map_entire_file, error); - if(error) { return handle_error(error); } + if (error) { return handle_error(error); } const int the_answer_to_everything = ro_mmap[answer_index]; assert(the_answer_to_everything == 42); From 321312f4d1d3423e2a7ec0db5925f511e9abeca4 Mon Sep 17 00:00:00 2001 From: mandreyel Date: Sat, 17 Mar 2018 11:49:10 +0100 Subject: [PATCH 3/5] Fix typos in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b1b848c..4e69075 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ int main() } ``` -`mio::basic_mmap` move-only, but if multiple copies to the same mapping is required, use `mio::basic_shared_mmap` which has `std::shared_ptr` semantics and has the same interface as `mio::basic_mmap`. +`mio::basic_mmap` is move-only, but if multiple copies to the same mapping are needed, use `mio::basic_shared_mmap` which has `std::shared_ptr` semantics and has the same interface as `mio::basic_mmap`. ```c++ #include @@ -120,7 +120,7 @@ mio::shared_mmap_source shared_mmap4; shared_mmap4.map("path", offset, size_to_map, error); ``` -It's possible to define the type of a byte (which has to be the same width as `char`), though aliases for the most commonly ones are provided by default: +It's possible to define the type of a byte (which has to be the same width as `char`), though aliases for the most common ones are provided by default: ```c++ using mmap_source = basic_mmap_source; using ummap_source = basic_mmap_source; @@ -134,7 +134,7 @@ using mmap_source = mio::basic_mmap_source; using mmap_sink = mio::basic_mmap_sink; ``` -You can query the underlying system's page allocation granularity by invoking `mio::page_size()`, which is located in `mio/page.hpp`. +Though generally not needed, since mio maps users requested offsets to page boundaries, you can query the underlying system's page allocation granularity by invoking `mio::page_size()`, which is located in `mio/page.hpp`. ### Installation mio is a header-only library, so just copy the contents in `mio/include` into your system wide include path, such as `/usr/include`, or into your project's lib folder. From ab385b9ed46693349b6a77752fef6461c74e2e56 Mon Sep 17 00:00:00 2001 From: Trent Houliston Date: Thu, 12 Apr 2018 11:13:47 +1000 Subject: [PATCH 4/5] Add missing inline for memory_map --- include/mio/detail/basic_mmap.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mio/detail/basic_mmap.ipp b/include/mio/detail/basic_mmap.ipp index bfa19d6..1fd4e70 100644 --- a/include/mio/detail/basic_mmap.ipp +++ b/include/mio/detail/basic_mmap.ipp @@ -122,7 +122,7 @@ struct mmap_context #endif }; -mmap_context memory_map(const file_handle_type file_handle, const int64_t offset, +inline mmap_context memory_map(const file_handle_type file_handle, const int64_t offset, const int64_t length, const access_mode mode, std::error_code& error) { const int64_t aligned_offset = make_offset_page_aligned(offset); From 5a6e136512af4c9e6d5616352856f3217b8622c4 Mon Sep 17 00:00:00 2001 From: lukediamond Date: Sat, 14 Apr 2018 02:00:22 -0400 Subject: [PATCH 5/5] Fixed mutable begin() for basic_mmap. --- include/mio/mmap.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mio/mmap.hpp b/include/mio/mmap.hpp index 2b8b2ed..6d71b25 100644 --- a/include/mio/mmap.hpp +++ b/include/mio/mmap.hpp @@ -151,7 +151,10 @@ public: * Returns an iterator to the first requested byte, if a valid memory mapping * exists, otherwise this function call is equivalent to invoking `end`. */ - iterator begin() noexcept { return impl_.begin(); } + template< + access_mode A = AccessMode, + typename = typename std::enable_if::type + > iterator begin() noexcept { return impl_.begin(); } const_iterator begin() const noexcept { return impl_.begin(); } const_iterator cbegin() const noexcept { return impl_.cbegin(); }