update mapped_file.
This commit is contained in:
parent
a987074a89
commit
c4bb292847
139
mapped_file.cpp
139
mapped_file.cpp
|
@ -7,13 +7,9 @@
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void throw_error(int error) {
|
void set_or_throw_error(std::error_code *ec, int error, const std::string &what) {
|
||||||
throw std::system_error(error, std::system_category());
|
if (ec) *ec = std::error_code(error, std::system_category());
|
||||||
}
|
else throw std::system_error(error, std::system_category(), what);
|
||||||
|
|
||||||
|
|
||||||
void throw_error(int error, const std::string &what) {
|
|
||||||
throw std::system_error(error, std::system_category(), what);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,18 +19,17 @@ namespace {
|
||||||
|
|
||||||
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) {
|
void set_or_throw_error(std::error_code *ec, const std::string &what) {
|
||||||
int e = GetLastError();
|
auto e = GetLastError();
|
||||||
throw_error(e, what);
|
set_or_throw_error(ec, e, what);
|
||||||
}
|
|
||||||
|
|
||||||
void throw_error(const std::string &what) {
|
|
||||||
int e = GetLastError();
|
|
||||||
throw_error(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 fh;
|
||||||
HANDLE mh;
|
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
|
// length of 0 in CreateFileMapping / MapViewOfFile
|
||||||
// means map the entire file.
|
// means map the entire file.
|
||||||
|
|
||||||
if (is_open()) {
|
if (is_open()) close();
|
||||||
throw std::runtime_error("mapped_file_base::open - file already open");
|
|
||||||
}
|
|
||||||
|
|
||||||
fh = CreateFile(p.c_str(),
|
fh = CreateFile(p.c_str(),
|
||||||
flags == readonly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
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,
|
flags == readonly ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
if (fh == INVALID_HANDLE_VALUE) {
|
if (fh == INVALID_HANDLE_VALUE)
|
||||||
throw_error("CreateFile");
|
return set_or_throw_error(ec, "CreateFile");
|
||||||
}
|
|
||||||
|
|
||||||
auto fh_close = make_unique_resource(fh, CloseHandle);
|
auto fh_close = make_unique_resource(fh, CloseHandle);
|
||||||
|
|
||||||
|
|
||||||
if (length == -1) {
|
if (length == -1) {
|
||||||
LARGE_INTEGER file_size;
|
LARGE_INTEGER file_size;
|
||||||
GetFileSizeEx(fh, &file_size);
|
GetFileSizeEx(fh, &file_size);
|
||||||
length = file_size.QuadPart;
|
length = file_size.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
DWORD protect = 0;
|
DWORD protect = 0;
|
||||||
DWORD access = 0;
|
DWORD access = 0;
|
||||||
switch (flags) {
|
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);
|
mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0);
|
||||||
if (mh == INVALID_HANDLE_VALUE) {
|
if (mh == INVALID_HANDLE_VALUE)
|
||||||
throw_error("CreateFileMapping");
|
return set_or_throw_error(ec, "CreateFileMapping");
|
||||||
}
|
|
||||||
|
|
||||||
auto mh_close = make_unique_resource(mh, CloseHandle);
|
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,
|
(DWORD)offset,
|
||||||
length,
|
length,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (!_data) {
|
if (!_data)
|
||||||
throw_error("MapViewOfFileEx");
|
return set_or_throw_error(ec, "MapViewOfFileEx");
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_file_handle = fh_close.release();
|
_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;
|
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;
|
const DWORD access = FILE_MAP_WRITE;
|
||||||
|
|
||||||
|
|
||||||
if (is_open()) {
|
if (is_open()) close();
|
||||||
throw std::runtime_error("mapped_file_base::create - file already open");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fh = CreateFile(p.c_str(),
|
fh = CreateFile(p.c_str(),
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
@ -150,21 +143,23 @@ void mapped_file_base::create(const path_type& p, size_t length) {
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
if (fh == INVALID_HANDLE_VALUE) {
|
if (fh == INVALID_HANDLE_VALUE)
|
||||||
throw_error("CreateFile");
|
return set_or_throw_error(ec, "CreateFile");
|
||||||
}
|
|
||||||
|
|
||||||
auto fh_close = make_unique_resource(fh, CloseHandle);
|
auto fh_close = make_unique_resource(fh, CloseHandle);
|
||||||
|
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
file_size.QuadPart = length;
|
file_size.QuadPart = length;
|
||||||
if (!SetFilePointerEx(fh, file_size, nullptr, FILE_BEGIN));
|
if (!SetFilePointerEx(fh, file_size, nullptr, FILE_BEGIN))
|
||||||
if (!SetEndOfFile(fh)) throw_error("SetEndOfFile");
|
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);
|
mh = CreateFileMapping(fh, nullptr, protect, 0, 0, 0);
|
||||||
if (mh == INVALID_HANDLE_VALUE) {
|
if (mh == INVALID_HANDLE_VALUE)
|
||||||
throw_error("CreateFileMapping");
|
return set_or_throw_error(ec, "CreateFileMapping");
|
||||||
}
|
|
||||||
|
|
||||||
auto mh_close = make_unique_resource(mh, CloseHandle);
|
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,
|
length,
|
||||||
nullptr);
|
nullptr);
|
||||||
|
|
||||||
if (!_data) {
|
if (!_data)
|
||||||
throw_error("MapViewOfFileEx");
|
return set_or_throw_error(ec, "MapViewOfFileEx");
|
||||||
}
|
|
||||||
|
|
||||||
_file_handle = fh_close.release();
|
_file_handle = fh_close.release();
|
||||||
_map_handle = mh_close.release();
|
_map_handle = mh_close.release();
|
||||||
|
@ -198,14 +192,16 @@ void mapped_file_base::create(const path_type& p, size_t length) {
|
||||||
|
|
||||||
namespace {
|
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) {
|
void set_or_throw_error(std::error_code *ec, const std::string &what) {
|
||||||
throw_error(errno, what);
|
set_or_throw_error(ec, errno, what);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mapped_file_base::close() {
|
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 fd;
|
||||||
|
|
||||||
int oflags = 0;
|
int oflags = 0;
|
||||||
|
|
||||||
if (is_open()) {
|
if (is_open()) close();
|
||||||
throw std::runtime_error("mapped_file_base::open - file already open");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (flags) {
|
switch (flags) {
|
||||||
case readonly:
|
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);
|
fd = ::open(p.c_str(), oflags);
|
||||||
if (fd < 0) {
|
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);
|
auto close_fd = make_unique_resource(fd, ::close);
|
||||||
|
|
||||||
|
|
||||||
if (length == -1) {
|
if (length == -1) {
|
||||||
|
|
||||||
struct stat st;
|
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;
|
length = st.st_size;
|
||||||
}
|
}
|
||||||
if (length == 0) return; // mmap w/ length of 0 is EINVAL.
|
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
_data = ::mmap(0, length,
|
_data = ::mmap(0, length,
|
||||||
flags == readonly ? PROT_READ : PROT_READ | PROT_WRITE,
|
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) {
|
if (_data == MAP_FAILED) {
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
throw_error(errno, "mmap");
|
return set_or_throw_error(ec, "mmap");
|
||||||
}
|
}
|
||||||
|
|
||||||
_fd = close_fd.release();
|
_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;
|
_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;
|
int fd;
|
||||||
const size_t offset = 0;
|
const size_t offset = 0;
|
||||||
|
|
||||||
if (is_open()) {
|
if (is_open()) close();
|
||||||
throw std::runtime_error("mapped_file_base::create - file already open");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fd = ::open(p.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||||
|
|
||||||
fd = ::open(p.c_str(), O_RDWR | O_CREAT | O_TRUNC);
|
|
||||||
if (fd < 0) {
|
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);
|
auto close_fd = make_unique_resource(fd, ::close);
|
||||||
|
|
||||||
|
|
||||||
|
if (length == 0) return;
|
||||||
|
|
||||||
if (::ftruncate(fd, length) < 0) {
|
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) {
|
if (_data == MAP_FAILED) {
|
||||||
_data = nullptr;
|
_data = nullptr;
|
||||||
throw_error(errno, "mmap");
|
return set_or_throw_error(ec, "mmap");
|
||||||
}
|
}
|
||||||
|
|
||||||
_fd = close_fd.release();
|
_fd = close_fd.release();
|
||||||
|
|
|
@ -1,25 +1,18 @@
|
||||||
#ifndef __mapped_file_h__
|
#ifndef __mapped_file_h__
|
||||||
#define __mapped_file_h__
|
#define __mapped_file_h__
|
||||||
|
|
||||||
#ifdef HAVE_TSFS
|
|
||||||
#include <filesystem>
|
|
||||||
#else
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
class mapped_file_base {
|
class mapped_file_base {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef HAVE_TSFS
|
typedef std::string path_type;
|
||||||
typedef std::filesystem::path path_type ;
|
|
||||||
#else
|
|
||||||
typedef std::string path_type ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum mapmode { readonly, readwrite, priv };
|
enum mapmode { readonly, readwrite, priv };
|
||||||
|
enum createmode { truncate, exclusive };
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
|
@ -40,8 +33,8 @@ protected:
|
||||||
|
|
||||||
void swap(mapped_file_base &rhs);
|
void swap(mapped_file_base &rhs);
|
||||||
|
|
||||||
void open(const path_type& p, mapmode flags, size_t length, size_t offset);
|
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); // always creates readwrite.
|
void create(const path_type &p, size_t new_size, std::error_code *ec); // always creates readwrite.
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,6 +72,22 @@ public:
|
||||||
open(p, flags, length, offset);
|
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(mapped_file &&);
|
||||||
mapped_file(const mapped_file &) = delete;
|
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) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ public:
|
||||||
unique_resource(T t, D d): _pair(t,d), _active(true)
|
unique_resource(T t, D d): _pair(t,d), _active(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
~unique_resource() {
|
~unique_resource() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -41,14 +40,14 @@ public:
|
||||||
|
|
||||||
void reset(T t) {
|
void reset(T t) {
|
||||||
reset();
|
reset();
|
||||||
_pair.first = t;
|
|
||||||
_active = true;
|
_active = true;
|
||||||
|
_pair.first = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(T t, D d) {
|
void reset(T t, D d) {
|
||||||
reset();
|
reset();
|
||||||
_pair = std::make_pair(t, d);
|
|
||||||
_active = true;
|
_active = true;
|
||||||
|
_pair = std::make_pair(t, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
|
@ -60,6 +59,10 @@ public:
|
||||||
|
|
||||||
T release() {
|
T release() {
|
||||||
_active = false;
|
_active = false;
|
||||||
|
return _pair.first;;
|
||||||
|
}
|
||||||
|
|
||||||
|
T get() {
|
||||||
return _pair.first;
|
return _pair.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,16 +70,6 @@ public:
|
||||||
return _active;
|
return _active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
T& get() {
|
|
||||||
return _pair.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& get() const {
|
|
||||||
return _pair.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
D& get_deleter() {
|
D& get_deleter() {
|
||||||
return _pair.second;
|
return _pair.second;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue