Commit fceb4c13 authored by zhanxw's avatar zhanxw

fix RingMemoryPool

add size_t definition

add header file
parent c6499773
......@@ -9,7 +9,7 @@ LIB = lib-base.a
LIB_DBG = lib-dbg-base.a
BASE = Argument Exception IO OrderedMap Regex TypeConversion Utils Logger \
RangeList SimpleMatrix Pedigree Kinship Profiler VersionChecker \
Socket Http TextMatrix Indexer KinshipHolder
Socket Http TextMatrix Indexer KinshipHolder RingMemoryPool
OBJ = $(BASE:%=%.o)
OBJ_DBG = $(BASE:%=%_dbg.o)
......
#include "RingMemoryPool.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memcpy
#include <cassert>
RingMemoryPool::RingMemoryPool() { init(0, DefaultCapacity); }
RingMemoryPool::RingMemoryPool(int numElementsInChunk) {
init(numElementsInChunk, DefaultCapacity);
}
/**
* Allocate @param numChunk of chunks, each chunk has @param
* numElementsInChunk elements.
*/
RingMemoryPool::RingMemoryPool(int numElementsInChunk, int numChunk) {
init(numElementsInChunk, numChunk);
}
void RingMemoryPool::init(int numElementsInChunk, int numChunk) {
assert(numElementsInChunk > 0);
assert(numChunk > 0);
numElementsInChunk_ = numElementsInChunk;
memory_.resize((size_t)numElementsInChunk * numChunk);
capacity_ = numChunk;
size_ = 0;
head_ = 0;
tail_ = 0;
headIndex_ = 0;
tailIndex_ = 0;
}
int RingMemoryPool::allocate() {
// Case 1: . . Head x x x Tail . . (head < tail)
// Case 2: x x Tail . . . Head x x (head > tail)
// Case 3: . . Head/Tail . . . (head == tail)
// Case 4: x x Head/Tail x x x (head == tail)
// . => empty slot
// x => used slot
assert(numElementsInChunk_ > 0);
// allocate memory if needed
assert(capacity_ > 0);
if (size_ == capacity_) {
capacity_ = 2 * size_;
memory_.resize(capacity_ * numElementsInChunk_);
if (tail_ <= head_ && size_ > 0) { // case 2 or 4
// need to move data from head_ to oldCapacity(which is size_)
// move [head ... oldCapacity ] to [ (head+oldCapacity) ... capacity_];
memcpy(memory_.data() + (head_ + size_) * numElementsInChunk_,
memory_.data() + head_ * numElementsInChunk_,
sizeof(float) * (size_ - head_) * numElementsInChunk_);
head_ += size_;
}
}
++tail_;
if (tail_ == capacity_) {
tail_ = 0;
}
const int ret = tailIndex_;
tailIndex_++;
size_++;
return ret;
}
void RingMemoryPool::deallocate(int idx) {
#ifndef NDEBUG
if (idx != headIndex_) {
fprintf(stderr,
"Cannot deallocate memory %d, headIndex = %d, tailIndex = %d\n",
idx, headIndex_, tailIndex_);
return;
}
#endif
assert(idx == headIndex_); // only dealloc the head elment
++head_;
if (head_ == capacity_) {
head_ = 0;
}
headIndex_++;
size_--;
}
float* RingMemoryPool::chunk(int idx) {
if (idx >= tailIndex_ || idx < headIndex_) {
return NULL;
}
const size_t pos = head_ + (idx - headIndex_);
float* ret = NULL;
if (pos < capacity_) {
ret = memory_.data() + pos * numElementsInChunk_;
} else {
ret = memory_.data() + (pos - capacity_) * numElementsInChunk_;
}
return ret;
}
float* RingMemoryPool::firstChunk() { return memory_.data(); }
float* RingMemoryPool::lastChunk() {
return memory_.data() + (capacity_ - 1) * numElementsInChunk_;
}
size_t RingMemoryPool::capacity() const { return capacity_; }
size_t RingMemoryPool::size() const { return size_; }
// internal data will be reset
void RingMemoryPool::setChunkSize(const size_t s) {
if (s == numElementsInChunk_) {
return;
}
numElementsInChunk_ = s;
if (memory_.size() == 0) {
capacity_ = DefaultCapacity;
memory_.resize(s * capacity_);
} else {
memory_.resize(s * (memory_.size() / s));
capacity_ = memory_.size() / s;
}
head_ = tail_ = headIndex_ = tailIndex_ = 0;
}
#ifndef _RINGMEMORYPOOL_H_
#define _RINGMEMORYPOOL_H_
#include <assert.h>
#include <string.h>
#include <cstddef> // size_t definnition
#include <vector>
/**
* This class uses a ring to store indice,
* and each index points to a chunk of memory of a fixed length.
* Limitation:
* when allocate memory, you get a sereis of index: 0, 1, 2, 3...
* wehn deallocate memory, you will need to deallocate 0, 1, 2, 3, ... in the
* same order
*/
class RingMemoryPool {
public:
RingMemoryPool() {
capacity_ = 0;
base_ = 0;
head_ = 0;
tail_ = 0;
numElementsInChunk_ = 0;
}
RingMemoryPool(int numElementsInChunk, int numChunk = 64)
: numElementsInChunk_(numElementsInChunk) {
memory_.resize(numElementsInChunk * numChunk);
capacity_ = numChunk;
base_ = 0;
head_ = 0;
tail_ = 0;
}
int allocate() {
if (tail_ == capacity_) {
const size_t oldSize = capacity_;
capacity_ = 2 * oldSize;
memory_.resize(capacity_ * numElementsInChunk_);
RingMemoryPool();
RingMemoryPool(int numElementsInChunk);
/**
* Allocate @param numChunk of chunks, each chunk has @param
* numElementsInChunk elements.
*/
RingMemoryPool(int numElementsInChunk, int numChunk);
void init(int numElementsInChunk, int numChunk);
if (head_ != 0) { // need to move data from head_ to capacity
// move [head ... oldSize ] to [ (head+oldSize) ... capacity_];
memcpy(memory_.data() + (head_ + oldSize) * numElementsInChunk_,
memory_.data() + head_ * numElementsInChunk_,
sizeof(float) * (oldSize - head_) * numElementsInChunk_);
base_ += oldSize;
}
}
const int idx = tail_;
++tail_;
return idx;
}
void deallocate(int idx) {
assert(idx == head_); // only dealloc the head elment
if (head_ < tail_) {
++head_;
}
assert(head_ <= tail_);
}
float* chunk(int idx) {
if (idx >= tail_ || idx < head_) {
return NULL;
}
const int pos = base_ + idx;
float* ret = NULL;
if (pos < capacity_) {
ret = memory_.data() + pos * numElementsInChunk_;
} else {
ret = memory_.data() + (pos - capacity_) * numElementsInChunk_;
}
return ret;
}
// internal data may be not kept
void setChunkSize(const int s) {
assert(s >= 0);
if (s == numElementsInChunk_) {
return;
}
numElementsInChunk_ = s;
if (memory_.size() == 0) {
capacity_ = 64;
memory_.resize(s * capacity_);
base_ = head_ = tail_ = 0;
} else if (memory_.size() % s == 0) {
capacity_ = memory_.size() / s;
base_ = head_ = tail_ = 0;
} else {
memory_.resize(s * (memory_.size() / s));
capacity_ = memory_.size() / s;
base_ = head_ = tail_ = 0;
}
}
int allocate();
void deallocate(int idx);
float* chunk(int idx);
float* firstChunk();
float* lastChunk();
size_t capacity() const;
size_t size() const;
// internal data will be reset
void setChunkSize(const size_t s);
private:
std::vector<float> memory_; // hold some memory
int capacity_; // how many indice can be hold
int base_; // the index for the first element
int head_; // index of chunk
int tail_; // index of chunk
int numElementsInChunk_;
static const int DefaultCapacity = 64;
std::vector<float> memory_; // hold chunks memory
size_t capacity_; // how many indice can be hold
size_t size_; // number of existing elements
size_t head_; // pointer to the ring head
size_t tail_; // pointer to the ring tail
int headIndex_; // the first unallocated index for the memory
int tailIndex_; // the index to be allocated
size_t numElementsInChunk_;
};
#endif /* _RINGMEMORYPOOL_H_ */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "base/RingMemoryPool.h"
int main() {
float* p;
......@@ -93,4 +95,42 @@ int main() {
mp.deallocate(8 + i);
}
}
{
RingMemoryPool mp(1, 4);
for (int i = 0; i < 3; ++i) {
int idx = mp.allocate();
p = mp.chunk(idx);
*p = i;
}
assert(mp.size() == 3); // mp: 0 1 2 .
mp.deallocate(0);
mp.deallocate(1);
assert(mp.size() == 1); // mp: . . 2 .
assert(mp.allocate() == 3); // mp: . . 2 3
*(mp.chunk(3)) = 3;
assert(*(mp.lastChunk()) == 3);
assert(mp.allocate() == 4); // mp: 4 . 2 3
*(mp.chunk(4)) = 4;
assert(*(mp.firstChunk()) == 4);
assert(mp.allocate() == 5); // mp: 4 5 2 3
*(mp.chunk(5)) = 5;
assert(mp.size() == 4);
assert(mp.capacity() == 4);
mp.deallocate(2);
mp.deallocate(3);
assert(mp.allocate() == 6);
assert(mp.allocate() == 7); // mp: 4 5 6 7
*(mp.chunk(6)) = 6;
*(mp.chunk(7)) = 7;
assert(*(mp.firstChunk()) == 4);
assert(*(mp.lastChunk()) == 7);
assert(mp.size() == 4);
assert(mp.capacity() == 4);
}
}
......@@ -25,7 +25,7 @@ void VCFInputFile::setRangeMode() {
fprintf(stderr,
"[ERROR] Cannot read VCF by range, please verify you have the "
"index file"
"(or create one use tabix).\nQuitting...");
"(or create one using tabix).\nQuitting...");
abort();
} else {
this->mode = VCFInputFile::VCF_RANGE_MODE;
......
......@@ -3943,6 +3943,8 @@ class MetaCovTest : public ModelFitter {
this->fout = fp;
while (queue.size() && getWindowSize(queue, loci) > windowSize) {
printCovariance(fout, queue, isBinaryOutcome());
genoPool.deallocate(queue.front().geno);
genoCovPool.deallocate(queue.front().covXZ);
queue.pop_front();
}
if (fitOK) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment