15 #include <system_error>
20 #include <boost/filesystem.hpp>
25 namespace fsys = boost::filesystem;
26 using namespace std::literals;
32 virtual void* allocate(
size_t sz) = 0;
33 virtual void deallocate(
void* t,
size_t n) = 0;
34 virtual void* reallocate(
void* t,
size_t n) = 0;
35 virtual void* initialize() = 0;
36 virtual size_t size()
const = 0;
37 inline virtual void msync(
bool async)
const {
38 throw std::range_error(
"msync not defined for allocator type");
46 inline void* allocate(
size_t n) {
49 throw std::system_error(std::error_code(errno, std::system_category()),
"malloc");
53 inline void deallocate(
void* address,
size_t n) {
57 inline void* reallocate(
void* old_address,
size_t n) {
58 if (old_address != t) {
59 throw std::out_of_range(
"memallocator can't reallocate at an offset");
61 void* new_t = realloc(old_address, n);
62 if (new_t ==
nullptr) {
63 throw std::system_error(std::error_code(errno, std::system_category()),
"realloc");
68 inline void* initialize() {
69 throw std::out_of_range(
"memallocator has nothing to initialize from");
71 inline size_t size()
const {
72 throw std::out_of_range(
"memallocator does not provide size");
81 flexallocator() : offset(0), t(
nullptr), n(0), pagesz(sysconf(_SC_PAGESIZE)) { }
83 inline void* allocate(
size_t n_p) {
84 size_t pages = n_p / pagesz;
89 t = mmap(NULL, n, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
90 if (t == (
void *)-1) {
91 throw std::system_error(std::error_code(errno, std::system_category()),
"mmap (PRIVATE|ANON)");
96 inline virtual void deallocate(
void* t_p,
size_t n_p) {
97 if (munmap(t_p, n_p) == -1) {
98 throw std::system_error(std::error_code(errno, std::system_category()),
"munmap");
102 inline virtual void* reallocate(
void* t_p,
size_t n_p) {
105 throw std::out_of_range(
"can't reallocate with an address before start of mapping");
107 else if (t_p == (
char*)t + offset) {
108 size_t pages = (n_p + offset) / pagesz;
109 if ((n_p + offset) % pagesz) {
112 n_p = pages * pagesz;
114 t = mremap(t, n, n_p, MREMAP_MAYMOVE);
115 if (t == (
void *)-1) {
116 throw std::system_error(std::error_code(errno, std::system_category()),
"mremap");
120 return (
char*)t + offset;
123 if (t_p > (
char*)t + n) {
124 throw std::out_of_range(
"can't reallocate with an address beyond end of mapping");
127 size_t sz = (
char*)t_p - ((
char*)t + offset);
128 size_t pages = sz / pagesz;
129 offset = sz % pagesz;
132 if (munmap(t, pages * pagesz) == -1) {
133 throw std::system_error(std::error_code(errno, std::system_category()),
"munmap");
136 t = (
char*)t + pages * pagesz;
140 return reallocate((
char*)t + offset, n_p + offset);
145 inline void* initialize() {
146 throw std::out_of_range(
"flexallocator has nothing to initialize from");
148 inline size_t size()
const {
149 throw std::out_of_range(
"flexallocator does not provide size");
163 mmapallocator(
const fsys::path& filename_p) : t(
nullptr), n(0), fd(-1), filename(filename_p) { }
165 inline void* initialize() {
166 int fd = open(filename.c_str(), O_RDWR);
168 throw std::system_error(std::error_code(errno, std::system_category()),
169 "cannot open "s + filename.c_str());
172 off_t sz = lseek(fd, 0L, SEEK_END);
175 throw std::system_error(std::error_code(errno, std::system_category()),
"lseek");
177 t =
static_cast<void*
>(mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
178 if (t == MAP_FAILED) {
180 throw std::system_error(std::error_code(errno, std::system_category()),
"mmap");
186 inline size_t size()
const {
return n; }
188 inline void* allocate(
size_t sz) {
189 fd = open(filename.c_str(), O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
191 throw std::system_error(std::error_code(errno, std::system_category()),
"open");
193 if (posix_fallocate(fd, 0, sz) == -1) {
195 throw std::system_error(std::error_code(errno, std::system_category()),
"posix_fallocate");
197 t =
static_cast<void*
>(mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
198 if (t == MAP_FAILED) {
200 throw std::system_error(std::error_code(errno, std::system_category()),
"mmap");
207 inline void deallocate(
void* address,
size_t n) {
210 if (munmap(address, n) == -1) {
211 throw std::system_error(std::error_code(errno, std::system_category()),
"munmap");
215 if (remove(filename.c_str()) != 0) {
216 throw std::system_error(std::error_code(errno, std::system_category()),
217 "can't remove "s + filename.c_str());
222 inline void* reallocate(
void* old_address,
size_t new_size) {
223 if (old_address != t) {
224 throw std::out_of_range(
"mmapallocator can't reallocate at an offset");
226 if (lseek(fd, new_size, SEEK_SET) == -1) {
227 throw std::system_error(std::error_code(errno, std::system_category()),
"lseek");
229 if (write(fd,
"", 1) != 1) {
231 throw std::system_error(std::error_code(errno, std::system_category()),
"write");
233 void *new_t = mremap(t, n, new_size, MREMAP_MAYMOVE);
234 if (new_t == MAP_FAILED) {
235 throw std::system_error(std::error_code(errno, std::system_category()),
"mremap");
242 inline virtual void msync(
bool async)
const {
244 if (::msync(t, n, MS_SYNC) == -1) {
245 throw std::system_error(std::error_code(errno, std::system_category()),
"msync");
249 if (::msync(t, n, MS_ASYNC) == -1) {
250 throw std::system_error(std::error_code(errno, std::system_category()),
"msync");
261 if (::msync(t, n, MS_SYNC) == -1) {
263 throw std::system_error(std::error_code(errno, std::system_category()),
"msync");
266 if (munmap(t, n) == -1) {
267 throw std::system_error(std::error_code(errno, std::system_category()),
"munmap");
276 const fsys::path filename;