//
// Created on 1/25/18
//
#include <iostream>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
using namespace std;
template <typename T>
struct Node {
typedef T Data_t;
T _data;
Node<T>* _next;
};
// Memory pool based on memory from stack
template <typename T, size_t C>
class MemPool {
public:
typedef Node<T> Node_t;
MemPool() {
_freeList = nullptr;
// Initialize the memory
memset(_buff, C, sizeof(T));
// Create a link list of free nodes
typename Node_t::Data_t count(0);
for (size_t ii = 0; ii < C; ii++) {
_buff[ii]._data = count++;
put(&_buff[ii]);
}
}
// get a node from the pool
Node_t* get() {
if (_freeList) {
Node_t *node = _freeList;
_freeList = _freeList->_next;
return node;
}
return nullptr;
}
// free the node back to pool
void put(Node_t* node) {
if (!_freeList) {
_freeList = node;
_freeList->_next = nullptr;
} else {
node->_next = _freeList;
_freeList = node;
}
return;
}
private:
Node_t* _freeList;
Node_t _buff[C];
};
// Memory pool based on memory from file via mmap
template <typename T>
class MemMapPool {
public:
typedef Node<T> Node_t;
MemMapPool(size_t count) {
_mmappedData = nullptr;
_freeList = nullptr;
int psz = getpagesize();
_mmappedDataSz = count * sizeof(T);
if (_mmappedDataSz > psz) {
_mmappedDataSz = ((_mmappedDataSz/psz) + 1) * psz;
} else {
_mmappedDataSz = psz;
}
Node_t* buff = getMappedMemory();
assert(buff);
// Create a link list of free nodes
typename Node_t::Data_t index(0);
for (size_t ii = 0; ii < count; ii++) {
buff[ii]._data = index++;
put(&buff[ii]);
}
}
~MemMapPool() {
_freeList = nullptr;
if (_mmappedData) {
munmap(_mmappedData, _mmappedDataSz);
}
}
Node_t* getMappedMemory() {
int fd = open("mem", O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
assert(fd>0);
int err = ftruncate(fd, _mmappedDataSz);
assert(err == 0);
_mmappedData = mmap(NULL, _mmappedDataSz, PROT_WRITE, MAP_PRIVATE, fd, 0);
assert(_mmappedData != MAP_FAILED);
memset(_mmappedData, 1, _mmappedDataSz);
return (Node_t*)_mmappedData;
}
// get a node from the pool
Node_t* get() {
if (_freeList) {
Node_t *node = _freeList;
_freeList = _freeList->_next;
return node;
}
return nullptr;
}
// free the node back to pool
void put(Node_t* node) {
if (!_freeList) {
_freeList = node;
_freeList->_next = nullptr;
} else {
node->_next = _freeList;
_freeList = node;
}
return;
}
private:
Node_t* _freeList;
void* _mmappedData;
size_t _mmappedDataSz;
};
static void cling_main() {
// MemPool<int, 10> pool;
// MemPool<int, 10>::Node_t *node;
MemMapPool<int> pool(10);
MemMapPool<int>::Node_t *node;
while ((node = pool.get())) {
cout << node->_data << endl;
}
}
#ifdef CLING
cling_main();
#else
int main(int argc, const char* argv[]) {
cling_main();
return 0;
}
#endif
Comments