2011-06-14 60 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