summaryrefslogtreecommitdiff
path: root/core/mempool.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/mempool.hpp')
-rw-r--r--core/mempool.hpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/core/mempool.hpp b/core/mempool.hpp
new file mode 100644
index 0000000..a5ac07b
--- /dev/null
+++ b/core/mempool.hpp
@@ -0,0 +1,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
contact: Jan Huwald // Impressum