2011-06-14 57 views
1

我想实现一个并发对象池,其中在shared_ptr返回并显式返回到池不是必需的。我基本上在一个并发队列中为它分配了一个推送shared_ptrs的数组,并实现了一个自定义的deletor。似乎工作。我错过了什么?并发对象池提供boost :: 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 
+0

这属于http://codereview.stackexchange.com/ – 2011-06-14 08:16:02

+0

标题中的匿名命名空间对我来说似乎是一个坏主意;一种快速处理ODR违规的方法。 – 2011-06-14 15:23:22

+0

[Boost.Flyweight](http://www.boost.org/doc/libs/release/libs/flyweight/doc/index.html)是否已经解决了您的问题? – ildjarn 2011-06-14 15:24:05

回答

2

ConcurrentObjectPool的析构函数中设置_goingDown标志与读取payBack()中的标志之间存在竞争。它可能导致内存泄漏。

实际上,如果不尝试使析构函数安全地与payBack()同时运行,可能会更好。不管怎么说,从_goingDown标志是池对象的一部分开始,因此在池被销毁后访问它会导致未定义的行为 - 即所有对象在销毁之前必须返回到池中。

0

看起来不错。您是否遇到使用它的任何问题?

+1

需要确定。我总是搞砸了并发。 – Nikhil 2011-06-14 07:59:58