内存分配器buffer_allocator(cpp)
当我们使用RDMA编程时,通常需要事先申请一大块内存,注册到RDMA中,然后手动管理这部分内存。下面是一个简单的顺序内存分配管理器的实现,申请从write_offset开始申请,释放从read_offset开始释放。
#include <iostream>
#include <mutex>
#include <cassert>
class BufferAlloc {
public:
BufferAlloc(char *_start, char *_end) :
start_(_start), end_(_end), max_size_(end_ - start_),
curr_write_offset_(0), curr_read_offset_(0), free_space_(max_size_){}
inline std::pair<bool, char*> Alloc(size_t size) {
std::scoped_lock<std::mutex> lock(latch_);
/*
size == 0, return false;
*/
if(size == 0) {
return {false, nullptr};
}
if(size > max_size_) {
std::cerr << "[Error]: exceed max size! [Location]: " << __FILE__ << ":" << __LINE__ << std::endl;
return {false, nullptr};
}
/*
back curr_write_offset and free space
*/
size_t curr_write_offset_bak = curr_write_offset_;
size_t free_space_bak = free_space_;
/*
找到起始位置
*/
if(curr_write_offset_ + size > max_size_) {
if(max_size_ - curr_write_offset_ > free_space_) {
return {false, nullptr};
}
free_space_ -= (max_size_ - curr_write_offset_);
curr_write_offset_ = 0;
}
/*
free space < size, return false, no enough space
*/
if(free_space_ < size) {
curr_write_offset_ = curr_write_offset_bak;
free_space_ = free_space_bak;
return {false, nullptr};
}
/*
当前写入位置合适
*/
size_t write_offset = curr_write_offset_;
free_space_ -= size;
curr_write_offset_ = (curr_write_offset_ + size) % max_size_;
return std::make_pair(true, start_ + write_offset);
}
inline void Free(size_t size) {
std::scoped_lock<std::mutex> lock(latch_);
/*
检查异常情况
*/
if(size == 0) {
return ;
}
if(size > max_size_) {
std::cerr << "[Error]: exceed max size! [Location]: " << __FILE__ << ":" << __LINE__ << std::endl;
return ;
}
/*
备份
*/
size_t curr_read_offset_bak = curr_read_offset_;
size_t free_space_bak = free_space_;
/*
获取当前读取位置
*/
if(curr_read_offset_ + size > max_size_) {
free_space_ += (max_size_ - curr_read_offset_);
curr_read_offset_ = 0;
}
/*
free失败
*/
if(free_space_ + size > max_size_) {
curr_read_offset_ = curr_read_offset_bak;
free_space_ = free_space_bak;
return ;
}
/*
free成功
*/
free_space_ += size;
curr_read_offset_ = (curr_read_offset_ + size) % max_size_;
if(curr_read_offset_ == curr_write_offset_) {
assert(free_space_ == max_size_);
curr_read_offset_ = 0;
curr_write_offset_ = 0;
}
return ;
}
inline size_t getFreeSpace() {
return free_space_;
}
inline size_t getUsedSpace() {
return max_size_ - free_space_;
}
inline size_t get_curr_write_offset() {
return curr_write_offset_;
}
inline size_t get_curr_read_offset() {
return curr_read_offset_;
}
private:
char *start_;
char *end_;
size_t max_size_;
size_t curr_write_offset_;
size_t curr_read_offset_;
size_t free_space_;
std::mutex latch_;
};