1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#ifndef qEzyOXbTTD6KlhKDUsawdWmx6c0
#define qEzyOXbTTD6KlhKDUsawdWmx6c0
#include <assert.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <boost/utility.hpp>
using std::string;
struct MemPool : boost::noncopyable {
explicit MemPool(size_t size); // anonymous in-memory-pool
MemPool(size_t size, int fd); // mmap()ed memory pool
MemPool(size_t size, const string filename); // mmap()ed memory pool
MemPool(MemPool &&src); // move ctor
MemPool& operator=(MemPool&&);
MemPool& operator=(MemPool&) = delete;
MemPool& operator=(MemPool) = delete;
~MemPool();
inline void* operator() () const; // return memory region; TODO: pure attr
inline size_t getSize() const;
void sync() const; // call msync()
void advise(size_t start, size_t len, int adv);
protected:
void *base;
size_t size;
bool isMMap;
void doMMap(int fd, size_t size);
int openMMappableFile(const string filename, size_t size);
private:
static char* global_offset;
MemPool() = delete;
MemPool(const MemPool&) = delete;
};
char* MemPool::global_offset = (char*) (void*) 0x2fffff000000;
inline void* MemPool::operator() () const {
return base;
}
inline size_t MemPool::getSize() const {
return size;
}
MemPool::MemPool(size_t size) : size(size), isMMap(false) {
if (size == 0) {
base = NULL;
}else{
base = malloc(size);
assert(base != NULL);
}
}
MemPool::MemPool(size_t size, int fd) : size(size),isMMap(true) {
if (size == 0) {
base = NULL;
}else{
doMMap(fd, size);
}
}
MemPool::MemPool(size_t size, const string filename) : size(size), isMMap(true) {
if (size == 0) {
base = NULL;
}else{
doMMap(openMMappableFile(filename, size), size);
}
}
MemPool::MemPool(MemPool &&src) : base(src.base), size(src.size), isMMap(src.isMMap) {
// std::cout << "Mempool " << base << " moved via copy" << std::endl;
src.base = NULL;
src.size = 0;
}
MemPool& MemPool::operator= (MemPool &&src) {
// std::cout << "Mempool " << base << " moved via assignment" << std::endl;
base = src.base;
size = src.size;
isMMap = src.isMMap;
src.base = NULL;
src.size = 0;
return *this;
}
MemPool::~MemPool() {
// std::cout << "Mempool " << base << " terminated";
if (size == 0 or base == NULL) {
// std::cout << " from move" << std::endl;
return;
}else{
// std::cout << std::endl;
}
if (isMMap) {
sync();
munmap(base, size);
}else{
free(base);
}
}
void MemPool::sync() const {
if (isMMap)
msync(base, size, MS_SYNC);
}
void MemPool::advise(size_t start, size_t len, int adv) {
// adjust region to page boundary (defensive)
if (start & 4095) {
len -= 4096 - (start & 4095);
len &= ~4095;
start &= 4095;
start +=1;
}
// detect underflow and to large len
if (len < size) {
assert(madvise((char*) base + start, len, adv) == 0);
}
}
void MemPool::doMMap(int fd, size_t size) {
base = (void*) mmap((void*) global_offset, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NONBLOCK, fd, 0);
assert(base != MAP_FAILED);
assert(base == (void*) global_offset);
global_offset += ((size / 4096 + 1) * 4096) + 1024 * 4096;
}
int MemPool::openMMappableFile(const string filename, size_t size) {
int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_LARGEFILE | O_NOATIME, 0644);
assert(fd != -1);
// check if the file size is correct
struct stat st;
fstat(fd, &st);
if ((size_t) st.st_size < size) {
// write one byte at the end of the file to make it big enough for the later mmap call (mmap does not increase file size)
assert(lseek64(fd, size-1, SEEK_SET) != (off_t) -1);
char c(0);
assert(write(fd, &c, 1) == 1);
}
return fd;
}
#endif // qEzyOXbTTD6KlhKDUsawdWmx6c0
|