114 lines
3.0 KiB
C++
114 lines
3.0 KiB
C++
#include <cmath>
|
|
|
|
#include <a8/a8.h>
|
|
|
|
#include <a8/fifobuffer.h>
|
|
#include <a8/list.h>
|
|
|
|
const int BASE_BLOCK_SIZE = 128;
|
|
|
|
struct BufHead
|
|
{
|
|
list_head entry;
|
|
int len;
|
|
};
|
|
|
|
namespace a8
|
|
{
|
|
|
|
FifoBuffer::FifoBuffer(int buf_len)
|
|
{
|
|
if (buf_len <= 0) {
|
|
abort();
|
|
}
|
|
buf_ = (char*)malloc(buf_len);
|
|
buf_len_ = buf_len;
|
|
for (size_t i = 0; i < free_list_.size(); ++i) {
|
|
INIT_LIST_HEAD(&free_list_[i]);
|
|
}
|
|
}
|
|
|
|
FifoBuffer::~FifoBuffer()
|
|
{
|
|
free(buf_);
|
|
buf_ = nullptr;
|
|
buf_len_ = 0;
|
|
}
|
|
|
|
char* FifoBuffer::Alloc(int len)
|
|
{
|
|
if (len <= 0) {
|
|
abort();
|
|
}
|
|
int real_len = sizeof(BufHead) + len;
|
|
if (real_len > 1024 * 64) {
|
|
return (char*)malloc(len);
|
|
} else {
|
|
BufHead* buf_head = nullptr;
|
|
{
|
|
size_t index = GetIndex(real_len);
|
|
lock_.lock();
|
|
list_head* head = &free_list_[index];
|
|
if (!list_empty(head)) {
|
|
buf_head = list_first_entry(head, BufHead, entry);
|
|
list_del(&buf_head->entry);
|
|
}
|
|
lock_.unlock();
|
|
if (buf_head) {
|
|
return (char*)buf_head + sizeof(BufHead);
|
|
}
|
|
}
|
|
int p = offset_.fetch_add(len);
|
|
if (p > buf_len_) {
|
|
offset_.fetch_sub(len);
|
|
return (char*)malloc(len);
|
|
}
|
|
buf_head = (BufHead*)(buf_ + p);
|
|
buf_head->len = len;
|
|
return buf_ + p + sizeof(BufHead);
|
|
}
|
|
}
|
|
|
|
void FifoBuffer::Free(char* p)
|
|
{
|
|
if (p > buf_ && p < buf_ + buf_len_) {
|
|
BufHead* buf_head = (BufHead*)(p - sizeof(BufHead));
|
|
int real_len = sizeof(BufHead) + buf_head->len;
|
|
size_t index = GetIndex(real_len);
|
|
lock_.lock();
|
|
list_add(&buf_head->entry, &free_list_[index]);
|
|
lock_.unlock();
|
|
} else {
|
|
free(p);
|
|
}
|
|
}
|
|
|
|
size_t FifoBuffer::GetIndex(size_t size)
|
|
{
|
|
if (size <= BASE_BLOCK_SIZE * std::pow(2, 0)) {
|
|
return 0;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 1)) {
|
|
return 1;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 2)) {
|
|
return 2;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 3)) {
|
|
return 3;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 4)) {
|
|
return 4;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 5)) {
|
|
return 5;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 6)) {
|
|
return 6;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 7)) {
|
|
return 7;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 8)) {
|
|
return 8;
|
|
} else if (size <= BASE_BLOCK_SIZE * std::pow(2, 9)) {
|
|
return 9;
|
|
} else {
|
|
abort();
|
|
}
|
|
}
|
|
|
|
}
|