mechanicker icon

Memory pool based on stack/file based memory

mechanicker | PRO | 01/25/18 06:28:19 PM UTC | 0 ⭐ | 420 👁️ | Never ⏰ | []
C++ |

3.61 KB

|

None

|

0 👍

/

0 👎

//
// 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