a8/a8/fifobuffer.cc
2023-05-13 13:23:32 +00:00

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();
}
}
}