diff --git a/mapped_file.cpp b/mapped_file.cpp index 1138298..c014b2d 100644 --- a/mapped_file.cpp +++ b/mapped_file.cpp @@ -7,13 +7,9 @@ namespace { - void throw_error(int error) { - throw std::system_error(error, std::system_category()); - } - - - void throw_error(int error, const std::string &what) { - throw std::system_error(error, std::system_category(), what); + void set_or_throw_error(std::error_code *ec, int error, const std::string &what) { + if (ec) *ec = std::error_code(error, std::system_category()); + else throw std::system_error(error, std::system_category(), what); } } @@ -23,18 +19,17 @@ namespace { namespace { - void throw_error() { - throw_error(GetLastError()); + /* + * allocating a new string could reset GetLastError() to 0. + */ + void set_or_throw_error(std::error_code *ec, const char *what) { + auto e = GetLastError(); + set_or_throw_error(ec, e, what); } - void throw_error(const char *what) { - int e = GetLastError(); - throw_error(e, what); - } - - void throw_error(const std::string &what) { - int e = GetLastError(); - throw_error(e, what); + void set_or_throw_error(std::error_code *ec, const std::string &what) { + auto e = GetLastError(); + set_or_throw_error(ec, e, what); } } @@ -49,8 +44,9 @@ void mapped_file_base::close() { } } -void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset) { +void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) { + if (ec) ec->clear(); HANDLE fh; HANDLE mh; @@ -58,9 +54,7 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si // length of 0 in CreateFileMapping / MapViewOfFile // means map the entire file. - if (is_open()) { - throw std::runtime_error("mapped_file_base::open - file already open"); - } + if (is_open()) close(); fh = CreateFile(p.c_str(), flags == readonly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, @@ -70,18 +64,20 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si flags == readonly ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL, nullptr ); - if (fh == INVALID_HANDLE_VALUE) { - throw_error("CreateFile"); - } + if (fh == INVALID_HANDLE_VALUE) + return set_or_throw_error(ec, "CreateFile"); auto fh_close = make_unique_resource(fh, CloseHandle); + if (length == -1) { LARGE_INTEGER file_size; GetFileSizeEx(fh, &file_size); length = file_size.QuadPart; } + if (length == 0) return; + DWORD protect = 0; DWORD access = 0; switch (flags) { @@ -100,9 +96,8 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si } mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0); - if (mh == INVALID_HANDLE_VALUE) { - throw_error("CreateFileMapping"); - } + if (mh == INVALID_HANDLE_VALUE) + return set_or_throw_error(ec, "CreateFileMapping"); auto mh_close = make_unique_resource(mh, CloseHandle); @@ -113,9 +108,8 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si (DWORD)offset, length, nullptr); - if (!_data) { - throw_error("MapViewOfFileEx"); - } + if (!_data) + return set_or_throw_error(ec, "MapViewOfFileEx"); _file_handle = fh_close.release(); @@ -125,7 +119,9 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si } -void mapped_file_base::create(const path_type& p, size_t length) { +void mapped_file_base::create(const path_type& p, size_t length, std::error_code *ec) { + + if (ec) ec->clear(); const size_t offset = 0; @@ -137,10 +133,7 @@ void mapped_file_base::create(const path_type& p, size_t length) { const DWORD access = FILE_MAP_WRITE; - if (is_open()) { - throw std::runtime_error("mapped_file_base::create - file already open"); - } - + if (is_open()) close(); fh = CreateFile(p.c_str(), GENERIC_READ | GENERIC_WRITE, @@ -150,21 +143,23 @@ void mapped_file_base::create(const path_type& p, size_t length) { FILE_ATTRIBUTE_NORMAL, nullptr ); - if (fh == INVALID_HANDLE_VALUE) { - throw_error("CreateFile"); - } + if (fh == INVALID_HANDLE_VALUE) + return set_or_throw_error(ec, "CreateFile"); auto fh_close = make_unique_resource(fh, CloseHandle); + if (length == 0) return; file_size.QuadPart = length; - if (!SetFilePointerEx(fh, file_size, nullptr, FILE_BEGIN)); - if (!SetEndOfFile(fh)) throw_error("SetEndOfFile"); + if (!SetFilePointerEx(fh, file_size, nullptr, FILE_BEGIN)) + return set_or_throw_error(ec, "SetFilePointerEx"); + + if (!SetEndOfFile(fh)) + return set_or_throw_error(ec, "SetEndOfFile"); mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0); - if (mh == INVALID_HANDLE_VALUE) { - throw_error("CreateFileMapping"); - } + if (mh == INVALID_HANDLE_VALUE) + return set_or_throw_error(ec, "CreateFileMapping"); auto mh_close = make_unique_resource(mh, CloseHandle); @@ -175,9 +170,8 @@ void mapped_file_base::create(const path_type& p, size_t length) { length, nullptr); - if (!_data) { - throw_error("MapViewOfFileEx"); - } + if (!_data) + return set_or_throw_error(ec, "MapViewOfFileEx"); _file_handle = fh_close.release(); _map_handle = mh_close.release(); @@ -198,14 +192,16 @@ void mapped_file_base::create(const path_type& p, size_t length) { namespace { - void throw_error() { - throw_error(errno); + + void set_or_throw_error(std::error_code *ec, const char *what) { + set_or_throw_error(ec, errno, what); } - void throw_error(const std::string &what) { - throw_error(errno, what); + void set_or_throw_error(std::error_code *ec, const std::string &what) { + set_or_throw_error(ec, errno, what); } + } void mapped_file_base::close() { @@ -217,15 +213,15 @@ void mapped_file_base::close() { } -void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset) { +void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec) { + + if (ec) ec->clear(); int fd; int oflags = 0; - if (is_open()) { - throw std::runtime_error("mapped_file_base::open - file already open"); - } + if (is_open()) close(); switch (flags) { case readonly: @@ -238,21 +234,23 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si fd = ::open(p.c_str(), oflags); if (fd < 0) { - throw_error(errno); + return set_or_throw_error(ec, "open"); } - //defer([fd](){::close(fd); }); auto close_fd = make_unique_resource(fd, ::close); if (length == -1) { - struct stat st; - if (::fstat(fd, &st) < 0) throw_error(errno); + if (::fstat(fd, &st) < 0) { + set_or_throw_error(ec, "stat"); + return; + } length = st.st_size; } - if (length == 0) return; // mmap w/ length of 0 is EINVAL. + + if (length == 0) return; _data = ::mmap(0, length, flags == readonly ? PROT_READ : PROT_READ | PROT_WRITE, @@ -261,7 +259,7 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si if (_data == MAP_FAILED) { _data = nullptr; - throw_error(errno, "mmap"); + return set_or_throw_error(ec, "mmap"); } _fd = close_fd.release(); @@ -269,29 +267,28 @@ void mapped_file_base::open(const path_type& p, mapmode flags, size_t length, si _flags = flags; } -void mapped_file_base::create(const path_type& p, size_t length) { +void mapped_file_base::create(const path_type& p, size_t length, std::error_code *ec) { + + if (ec) ec->clear(); int fd; const size_t offset = 0; - if (is_open()) { - throw std::runtime_error("mapped_file_base::create - file already open"); - } + if (is_open()) close(); - - - fd = ::open(p.c_str(), O_RDWR | O_CREAT | O_TRUNC); + fd = ::open(p.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd < 0) { - throw_error(errno, "open"); + return set_or_throw_error(ec, "open"); } - //defer([fd](){::close(fd); }); auto close_fd = make_unique_resource(fd, ::close); + if (length == 0) return; + if (::ftruncate(fd, length) < 0) { - throw_error(errno, "ftruncate"); + return set_or_throw_error(ec, "ftruncate"); } @@ -302,7 +299,7 @@ void mapped_file_base::create(const path_type& p, size_t length) { if (_data == MAP_FAILED) { _data = nullptr; - throw_error(errno, "mmap"); + return set_or_throw_error(ec, "mmap"); } _fd = close_fd.release(); diff --git a/mapped_file.h b/mapped_file.h index 563c89c..115a632 100644 --- a/mapped_file.h +++ b/mapped_file.h @@ -1,25 +1,18 @@ #ifndef __mapped_file_h__ #define __mapped_file_h__ -#ifdef HAVE_TSFS -#include -#else #include -#endif #include - +#include class mapped_file_base { public: -#ifdef HAVE_TSFS - typedef std::filesystem::path path_type ; -#else - typedef std::string path_type ; -#endif + typedef std::string path_type; enum mapmode { readonly, readwrite, priv }; + enum createmode { truncate, exclusive }; void close(); @@ -40,8 +33,8 @@ protected: void swap(mapped_file_base &rhs); - void open(const path_type& p, mapmode flags, size_t length, size_t offset); - void create(const path_type &p, size_t new_size); // always creates readwrite. + void open(const path_type& p, mapmode flags, size_t length, size_t offset, std::error_code *ec); + void create(const path_type &p, size_t new_size, std::error_code *ec); // always creates readwrite. void reset(); @@ -79,6 +72,22 @@ public: open(p, flags, length, offset); } + mapped_file(const path_type &p, std::error_code &ec) noexcept { + open(p, readonly, -1, 0, ec); + } + mapped_file(const path_type &p, mapmode flags, std::error_code &ec) noexcept { + open(p, flags, -1, 0, ec); + } + + mapped_file(const path_type &p, mapmode flags, size_t length, std::error_code &ec) noexcept { + open(p, flags, length, 0, ec); + } + + mapped_file(const path_type &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept { + open(p, flags, length, offset, ec); + } + + mapped_file(mapped_file &&); mapped_file(const mapped_file &) = delete; @@ -87,7 +96,28 @@ public: void open(const path_type& p, mapmode flags, size_t length = -1, size_t offset = 0) { - base::open(p, flags, length, offset); + base::open(p, flags, length, offset, nullptr); + } + + void open(const path_type &p, std::error_code &ec) noexcept { + base::open(p, readonly, -1, 0, &ec); + } + void open(const path_type &p, mapmode flags, std::error_code &ec) noexcept { + base::open(p, flags, -1, 0, &ec); + } + void open(const path_type &p, mapmode flags, size_t length, std::error_code &ec) noexcept { + base::open(p, flags, length, 0, &ec); + } + void open(const path_type &p, mapmode flags, size_t length, size_t offset, std::error_code &ec) noexcept { + base::open(p, flags, length, offset, &ec); + } + + void create(const path_type &p, size_t size) { + base::create(p, size, nullptr); + } + + void create(const path_type &p, size_t size, std::error_code &ec) noexcept { + base::create(p, size, &ec); } diff --git a/unique_resource.h b/unique_resource.h index 1326b46..9ec9de0 100644 --- a/unique_resource.h +++ b/unique_resource.h @@ -18,7 +18,6 @@ public: unique_resource(T t, D d): _pair(t,d), _active(true) {} - ~unique_resource() { reset(); } @@ -41,14 +40,14 @@ public: void reset(T t) { reset(); - _pair.first = t; _active = true; + _pair.first = t; } void reset(T t, D d) { reset(); - _pair = std::make_pair(t, d); _active = true; + _pair = std::make_pair(t, d); } void reset() { @@ -60,6 +59,10 @@ public: T release() { _active = false; + return _pair.first;; + } + + T get() { return _pair.first; } @@ -67,16 +70,6 @@ public: return _active; } - - T& get() { - return _pair.first; - } - - const T& get() const { - return _pair.first; - } - - D& get_deleter() { return _pair.second; }