并发对象池给予提升::shared_ptr
我想实现一个并发对象池,其中返回shared_ptr,并且不需要将其显式返回到池。我基本上在并发队列中为其分配了一个推送共享指针的数组,并实现了一个自定义删除器。似乎有效。我错过了什么吗?
#ifndef CONCURRENTOBJECTPOOL_H
#define CONCURRENTOBJECTPOOL_H
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <tbb/concurrent_queue.h>
namespace COP
{
template<typename T>
class ConcurrentObjectPool;
namespace
{
template<typename T>
class ConcurrentObjectPoolDeletor
{
public:
ConcurrentObjectPoolDeletor(ConcurrentObjectPool<T>& aConcurrentObjectPool):
_concurrentObjectPool(aConcurrentObjectPool) {}
void operator()(T *p) const;
private:
ConcurrentObjectPool<T>& _concurrentObjectPool;
};
} // Anonymous namespace for ConcurrentObjectPoolDeletor
template <typename T>
class ConcurrentObjectPool
{
public:
ConcurrentObjectPool(const unsigned int aPoolSize)
: _goingDown(false),
_poolSize(aPoolSize),
_pool(new T[_poolSize]),
_ConcurrentObjectPoolDeletor(*this)
{
for(unsigned int i = 0; i < _poolSize; ++i)
{
boost::shared_ptr<T> curr(&_pool[i], _ConcurrentObjectPoolDeletor);
_objectQueue.push(curr);
}
}
boost::shared_ptr<T> loan()
{
boost::shared_ptr<T> curr;
_objectQueue.pop(curr);
return curr;
}
~ConcurrentObjectPool()
{
_goingDown = true;
_objectQueue.clear();
}
private:
void payBack(T * p)
{
if (! _goingDown)
{
boost::shared_ptr<T> curr(p, _ConcurrentObjectPoolDeletor);
_objectQueue.push(curr);
}
}
bool _goingDown;
const unsigned int _poolSize;
const boost::shared_array<T> _pool;
const ConcurrentObjectPoolDeletor<T> _ConcurrentObjectPoolDeletor;
tbb::concurrent_bounded_queue<boost::shared_ptr<T> > _objectQueue;
friend class ConcurrentObjectPoolDeletor<T>;
};
namespace
{
template<typename T>
void ConcurrentObjectPoolDeletor<T>::operator()(T *p) const
{
_concurrentObjectPool.payBack(p);
}
} // Anonymous namespace for ConcurrentObjectPoolDeletor
} // Namespace COP
#endif // CONCURRENTOBJECTPOOL_H
I wanted to implement a concurrent object pool where in a shared_ptr is returned and explicitly returning it to the pool is not required. I basically allocated an array pushed shared_ptrs for it in a concurrent queue and implemented a custom deletor. Seems to work. Am I missing anything?
#ifndef CONCURRENTOBJECTPOOL_H
#define CONCURRENTOBJECTPOOL_H
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <tbb/concurrent_queue.h>
namespace COP
{
template<typename T>
class ConcurrentObjectPool;
namespace
{
template<typename T>
class ConcurrentObjectPoolDeletor
{
public:
ConcurrentObjectPoolDeletor(ConcurrentObjectPool<T>& aConcurrentObjectPool):
_concurrentObjectPool(aConcurrentObjectPool) {}
void operator()(T *p) const;
private:
ConcurrentObjectPool<T>& _concurrentObjectPool;
};
} // Anonymous namespace for ConcurrentObjectPoolDeletor
template <typename T>
class ConcurrentObjectPool
{
public:
ConcurrentObjectPool(const unsigned int aPoolSize)
: _goingDown(false),
_poolSize(aPoolSize),
_pool(new T[_poolSize]),
_ConcurrentObjectPoolDeletor(*this)
{
for(unsigned int i = 0; i < _poolSize; ++i)
{
boost::shared_ptr<T> curr(&_pool[i], _ConcurrentObjectPoolDeletor);
_objectQueue.push(curr);
}
}
boost::shared_ptr<T> loan()
{
boost::shared_ptr<T> curr;
_objectQueue.pop(curr);
return curr;
}
~ConcurrentObjectPool()
{
_goingDown = true;
_objectQueue.clear();
}
private:
void payBack(T * p)
{
if (! _goingDown)
{
boost::shared_ptr<T> curr(p, _ConcurrentObjectPoolDeletor);
_objectQueue.push(curr);
}
}
bool _goingDown;
const unsigned int _poolSize;
const boost::shared_array<T> _pool;
const ConcurrentObjectPoolDeletor<T> _ConcurrentObjectPoolDeletor;
tbb::concurrent_bounded_queue<boost::shared_ptr<T> > _objectQueue;
friend class ConcurrentObjectPoolDeletor<T>;
};
namespace
{
template<typename T>
void ConcurrentObjectPoolDeletor<T>::operator()(T *p) const
{
_concurrentObjectPool.payBack(p);
}
} // Anonymous namespace for ConcurrentObjectPoolDeletor
} // Namespace COP
#endif // CONCURRENTOBJECTPOOL_H
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在
ConcurrentObjectPool
的析构函数中设置_goingDown
标志与在payBack()
中读取该标志之间存在竞争。它可能会导致内存泄漏。实际上,如果您不尝试使析构函数安全地与 payBack() 并发运行,也许会更好。无论如何,这是不安全的,因为
_goingDown
标志是池对象的一部分,因此在池被销毁后访问它会导致未定义的行为 - 即所有对象都必须返回到池中在它被摧毁之前。There is a race between setting the
_goingDown
flag in the destructor ofConcurrentObjectPool
and reading the flag inpayBack()
. It can lead to memory leaks.Actually, maybe it's better if you do not try to make the destructor safe to run concurrently with
payBack()
. It's not safe anyway, starting from the fact that the_goingDown
flag is a part of the pool object and so accessing it after the pool is destroyed would cause undefined behavior - i.e. all objects must be returned to the pool before it is destroyed.看起来不错。您使用它时遇到任何问题吗?
Looks good. Are you experiencing any problems using it?