|
|
@ -48,7 +48,8 @@ public:
|
|
|
|
if (capacity_ > 0) {
|
|
|
|
if (capacity_ > 0) {
|
|
|
|
nof_buffers = (uint32_t)capacity_;
|
|
|
|
nof_buffers = (uint32_t)capacity_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
used.reserve(nof_buffers);
|
|
|
|
pool.reserve(nof_buffers);
|
|
|
|
|
|
|
|
free_list.reserve(nof_buffers);
|
|
|
|
pthread_mutex_init(&mutex, nullptr);
|
|
|
|
pthread_mutex_init(&mutex, nullptr);
|
|
|
|
pthread_cond_init(&cv_not_empty, nullptr);
|
|
|
|
pthread_cond_init(&cv_not_empty, nullptr);
|
|
|
|
for (uint32_t i = 0; i < nof_buffers; i++) {
|
|
|
|
for (uint32_t i = 0; i < nof_buffers; i++) {
|
|
|
@ -57,21 +58,16 @@ public:
|
|
|
|
perror("Error allocating memory. Exiting...\n");
|
|
|
|
perror("Error allocating memory. Exiting...\n");
|
|
|
|
exit(-1);
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
available.push(b);
|
|
|
|
pool.push_back(b);
|
|
|
|
|
|
|
|
free_list.push_back(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
capacity = nof_buffers;
|
|
|
|
capacity = nof_buffers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
~buffer_pool()
|
|
|
|
~buffer_pool()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// this destructor assumes all buffers have been properly deallocated
|
|
|
|
for (auto* p : pool) {
|
|
|
|
while (available.size()) {
|
|
|
|
delete p;
|
|
|
|
delete available.top();
|
|
|
|
|
|
|
|
available.pop();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < used.size(); i++) {
|
|
|
|
|
|
|
|
delete used[i];
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_cond_destroy(&cv_not_empty);
|
|
|
|
pthread_cond_destroy(&cv_not_empty);
|
|
|
|
pthread_mutex_destroy(&mutex);
|
|
|
|
pthread_mutex_destroy(&mutex);
|
|
|
@ -79,11 +75,13 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
void print_all_buffers()
|
|
|
|
void print_all_buffers()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
printf("%d buffers in queue\n", (int)used.size());
|
|
|
|
printf("%d buffers in queue\n", static_cast<int>(pool.size() - free_list.size()));
|
|
|
|
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
|
|
|
|
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
|
|
|
|
std::map<std::string, uint32_t> buffer_cnt;
|
|
|
|
std::map<std::string, uint32_t> buffer_cnt;
|
|
|
|
for (uint32_t i = 0; i < used.size(); i++) {
|
|
|
|
for (uint32_t i = 0; i < pool.size(); i++) {
|
|
|
|
buffer_cnt[strlen(used[i]->debug_name) ? used[i]->debug_name : "Undefined"]++;
|
|
|
|
if (std::find(free_list.cbegin(), free_list.cend(), pool[i]) == free_list.cend()) {
|
|
|
|
|
|
|
|
buffer_cnt[strlen(used[i]->debug_name) ? pool[i]->debug_name : "Undefined"]++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::map<std::string, uint32_t>::iterator it;
|
|
|
|
std::map<std::string, uint32_t>::iterator it;
|
|
|
|
for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) {
|
|
|
|
for (it = buffer_cnt.begin(); it != buffer_cnt.end(); it++) {
|
|
|
@ -92,22 +90,21 @@ public:
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t nof_available_pdus() { return available.size(); }
|
|
|
|
uint32_t nof_available_pdus() { return free_list.size(); }
|
|
|
|
|
|
|
|
|
|
|
|
bool is_almost_empty() { return available.size() < capacity / 20; }
|
|
|
|
bool is_almost_empty() { return free_list.size() < capacity / 20; }
|
|
|
|
|
|
|
|
|
|
|
|
buffer_t* allocate(const char* debug_name = nullptr, bool blocking = false)
|
|
|
|
buffer_t* allocate(const char* debug_name = nullptr, bool blocking = false)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
buffer_t* b = nullptr;
|
|
|
|
buffer_t* b = nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
if (available.size() > 0) {
|
|
|
|
if (!free_list.empty()) {
|
|
|
|
b = available.top();
|
|
|
|
b = free_list.back();
|
|
|
|
used.push_back(b);
|
|
|
|
free_list.pop_back();
|
|
|
|
available.pop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (is_almost_empty()) {
|
|
|
|
if (is_almost_empty()) {
|
|
|
|
printf("Warning buffer pool capacity is %f %%\n", (float)100 * available.size() / capacity);
|
|
|
|
printf("Warning buffer pool capacity is %f %%\n", (float)100 * free_list.size() / capacity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
|
|
|
|
#ifdef SRSRAN_BUFFER_POOL_LOG_ENABLED
|
|
|
|
if (debug_name) {
|
|
|
|
if (debug_name) {
|
|
|
@ -117,14 +114,13 @@ public:
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
} else if (blocking) {
|
|
|
|
} else if (blocking) {
|
|
|
|
// blocking allocation
|
|
|
|
// blocking allocation
|
|
|
|
while (available.size() == 0) {
|
|
|
|
while (free_list.empty()) {
|
|
|
|
pthread_cond_wait(&cv_not_empty, &mutex);
|
|
|
|
pthread_cond_wait(&cv_not_empty, &mutex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// retrieve the new buffer
|
|
|
|
// retrieve the new buffer
|
|
|
|
b = available.top();
|
|
|
|
b = free_list.back();
|
|
|
|
used.push_back(b);
|
|
|
|
free_list.pop_back();
|
|
|
|
available.pop();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// do not print any warning
|
|
|
|
// do not print any warning
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -143,10 +139,8 @@ public:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
bool ret = false;
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
typename std::vector<buffer_t*>::iterator elem = std::find(used.begin(), used.end(), b);
|
|
|
|
if (std::find(pool.cbegin(), pool.cend(), b) != pool.cend()) {
|
|
|
|
if (elem != used.end()) {
|
|
|
|
free_list.push_back(b);
|
|
|
|
used.erase(elem);
|
|
|
|
|
|
|
|
available.push(b);
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_cond_signal(&cv_not_empty);
|
|
|
|
pthread_cond_signal(&cv_not_empty);
|
|
|
@ -156,8 +150,8 @@ public:
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
static const int POOL_SIZE = 4096;
|
|
|
|
static const int POOL_SIZE = 4096;
|
|
|
|
std::stack<buffer_t*> available;
|
|
|
|
std::vector<buffer_t*> pool;
|
|
|
|
std::vector<buffer_t*> used;
|
|
|
|
std::vector<buffer_t*> free_list;
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
pthread_cond_t cv_not_empty;
|
|
|
|
pthread_cond_t cv_not_empty;
|
|
|
|
uint32_t capacity;
|
|
|
|
uint32_t capacity;
|
|
|
|