C++ buffer pool?
C++ buffer pool?
我有一个强大的用例,可以预先分配我需要的所有内存,并在完成后释放它。
我已经提出了这个真正的简单缓冲池C++实现,我必须对其进行测试,但我不确定我尝试使用的指针算法是否允许我这样做。基本上是我接下来要做的一点和发布。我更喜欢围绕这个想法的一些技巧,而不是依赖任何类型的内存处理程序,这只会使客户端代码更加复杂。
#include <stdio.h>
#include <queue>
#include "utils_mem.h"
using namespace std;
template <class T>
class tbufferpool {
private:
const int m_initial;
const int m_size;
const int m_total;
T* m_buffer;
vector<T*> m_queue;
public:
// constructor
tbufferpool(int initial, int size) : m_initial(initial), m_size(size), m_total(initial*size*sizeof(T)) {
m_buffer = (T*) malloc(m_total);
T* next_buffer = m_buffer;
for (int i=0; i < initial; ++i, next_buffer += i*size) {
m_queue.push_back(next_buffer);
}
}
// get next buffer element from the pool
T* next() {
// check for pool overflow
if (m_queue.empty()) {
printf("Illegal bufferpool state, our bufferpool has %d buffers only.", m_initial);
exit(EXIT_FAILURE);
}
T* next_buffer = m_queue.back();
m_queue.pop_back();
return next_buffer;
}
// release element, make it available back in the pool
void release(T* buffer) {
assert(m_buffer <= buffer && buffer < (buffer + m_total/sizeof(T)));
m_queue.push_back(buffer);
}
void ensure_size(int size) {
if (size >= m_size) {
printf("Illegal bufferpool state, maximum buffer size is %d.", m_size);
exit(EXIT_FAILURE);
}
}
// destructor
virtual ~tbufferpool() {
free(m_buffer);
}
};
首先,当您增加指向 T 的指针时,它将指向内存中 T 的下一个元素。
m_queue.push(m_buffer + (i*size*sizeof(T)));
这应该是这样的
m_buffer = (T*) malloc(m_total);
T* next = m_buffer;
for (int i=0; i < initial; ++i) {
m_queue.push(next++);
}
第二
assert(m_buffer <= buffer && buffer < m_total);
它应该像
assert(m_buffer <= buffer && buffer <= m_buffer + m_total/sizeof(T));
希望对您有所帮助!
我不明白你为什么要"包装"STL队列<>容器。 只需将您的"缓冲区"放入队列中,然后根据需要提取地址即可。 当您在缓冲区中完成"段"时,只需将其从队列中弹出,它就会自动释放。 因此,您只需要实际的缓冲区类,而不是指向缓冲区的指针。
这让我感到重新发明了轮子。 现在,由于您需要一次分配整个内容,因此我将使用vector
不排队,因为vector<>
类型可以在构造时一次分配所有内容,并且push_back()
方法除非需要,否则不会重新分配,pop_back()
也是如此。 有关使用的方法,请参阅此处。
不过,基本上,这是我的粗略想法:
#include <myType.h> // Defines BufferType
const int NUMBUFFERS = 30;
int main()
{
vector<BufferType> myBuffers(NUMBUFFERS);
BufferType* segment = &(myBuffers[0]); // Gets first segment
myBuffers.pop_back(); // Reduces size by one
return 0;
}
我希望这能给你一个大致的想法。 您可以以这种方式使用向量中的缓冲区,并且只有一个分配或取消分配,如果您愿意,您可以使用类似堆栈的逻辑。 dequeue
类型也可能值得一看,或者其他标准容器,但如果只是"我只想要一个 alloc 或 de-alloc",我只会使用 vector,甚至是指向数组的智能指针。
我使用对象池发现了一些东西:
我不确定是否一次分配所有对象。我喜欢从包含对其自己的池的私有引用的"pooledObject"类中降下我所有的池化对象,因此允许使用简单的无参数"释放"方法,并且我始终绝对确定对象总是被释放回它自己的池。 我不确定如何使用静态数组 ctor 加载带有池引用的每个实例 - 我总是在循环中逐个构造对象。
另一个有用的私有成员是"分配"的布尔值,在对象被取消池化时设置,并在释放时清除。 这允许池类进行检测,除非对象被释放两次,则会立即检测。 如果不立即检测到"发布两次"错误可能会非常令人讨厌 - 奇怪的行为或崩溃发生在几分钟后,并且通常在另一个模块的另一个线程中发生。 最好尽快检测双重释放!
我发现将我的池级别转储到 1s 计时器上的状态栏很有用且令人放心。 如果发生泄漏,我可以看到它正在发生,并且通常,当数字惊人地下降时,我可以通过我所在的活动来了解泄漏的位置。 谁需要瓦尔格林德:)
关于线程,如果必须使池线程安全,则使用阻塞队列会有所帮助。 如果池用完,尝试获取对象的线程可以等到它们被释放,并且应用程序只会变慢,而不是崩溃/死锁。 另外,要小心重新。虚假共享。 您可能必须使用"填充"数组数据成员来确保没有两个对象共享缓存行。
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 为什么使用Pool和Bool而不是int8_t或char
- 如何"buffer" UNIX 信号
- C++ - Thread Pool
- 什么是 Direct3D 12.0 上的"Map Default Buffer"?
- VC++ wcscpy_s随机断言"Buffer is too small"
- 将uint8_t*buffer和size_tbufferlen从C++传递到C中的API函数的最佳方式是什么
- Thread Pool C++
- boost::asio::buffer 如何遍历字节
- 在 boost::<double>asio::buffer 中使用像 std::vector<std::complex> 这样的参数
- Cppcheck 静态代码分析器实际上可以检测到不太常见的警告(如 "Relative Path Traversal (CWE-23)" 或"Buffer Under-read(CWE-127)")吗
- 是否可以使用Boost ::或Boost ::变体带有boost :: pool
- boost::asio io_service thread pool with io_service::work
- tf2_ros::Buffer::canTransform() 为现有转换返回 False
- 使用boost :: pool时使用高CPU
- OpenCL/C++ - 返回一个 cl::Buffer 对象
- 如何在方法参数中使用boost :: asio :: buffer
- 尝试运行 NVIDIA FleX 时"buffer overflow detected"
- C++: buffer the cin istream
- C++ buffer pool?