很抱歉,这个问题的问题可能有点模糊。我正在尝试将这个ObjectPool代码从C#移植到C ++中,但似乎有些部分我不知道应该如何继续。代码如下:
using System;
namespace FastRank
{
public class ObjectPool<T> where T : class, new()
{
private int _count;
private T[] _pool;
public ObjectPool(int initSize)
{
_pool = new T[initSize];
}
public T Get()
{
lock (_pool)
{
if (_count > 0)
{
--_count;
T item = _pool[_count];
_pool[_count] = null;
return item;
}
}
return new T();
}
public void Return(T item)
{
lock (_pool)
{
if (_count == _pool.Length)
Array.Resize(ref _pool, _pool.Length*2 + 1);
_pool[_count++] = item;
}
}
}
}
我的问题是:
1)我应该如何在C ++中对泛型参数T实现该约束? (class,new())
2)有没有一种简单的方法来实现互斥锁部分?
3)在C ++中将_pool定义为vector而不是T []会更有效吗?
编辑 - &gt;实现了以下内容:
#include "object_pool.h"
#include <boost/thread.hpp>
#include <vector>
using namespace std;
template <class T>
ObjectPool<T>::ObjectPool(int init_size) {
pool_.reserve(init_size);
}
template <class T>
T ObjectPool<T>::Get() {
boost::lock_guard<boost::mutex> lock(guard_);
int sz = (int) pool_.size();
if (sz == 0) {
throw "Object pool size is now zero.";
}
else {
T item = pool_[sz-1];
pool_.pop_back();
return item;
}
}
template <class T>
void ObjectPool<T>::Return(T item) {
boost::lock_guard<boost::mutex> lock(guard_);
pool_.push_back(item);
}
想知道这段代码是否有问题......
答案 0 :(得分:2)
1)我应该如何在C ++中对泛型参数T实现该约束? (class,new())
一般来说,不要。如果它不能满足约束,它将无法编译。很简单。有一些棘手的方法来获得更好的错误信息,但我已经忘记了它们,因为我从来没有打扰过。
2)有没有一种简单的方法来实现互斥锁部分?
使用boost::mutex。
3)在C ++中将_pool定义为vector而不是T []会更有效吗?
考虑到没有大小的本地T[]
,是的。使用std::vector
。 (您可以将其作为参数,但不能在变量定义中使用。)
答案 1 :(得分:1)
这是一个天真的片段,说明了一种可能的方法:
#include <mutex>
template <typename T>
class SyncStack
{
T * m_data;
std::size_t m_size;
std::size_t m_count;
std::mutex m_lock;
public:
T get()
{
std::lock_guard<std::mutex> lock(m_lock);
if (m_count == 0) { throw UnderrunException; }
--m_count;
T x(m_data[m_count]);
m_data[m_count].~T();
return x;
}
void put(T x)
{
std::lock_guard<std::mutex> lock(m_lock);
::new (m_data + m_count) T(std::move(x));
++m_count;
}
};
此示例假定m_data
指向无限内存。重新分配有点棘手,涉及制作大量副本。
更简单的方法是将同步结构包装在另一个现有标准容器(如std::vector<T>
)周围。
答案 2 :(得分:0)
这就是我实现它的方式。您可以将tbb::concurrenct_queue
替换为std::mutex
看守std::queue
,但效率会降低。使用此实现,您需要担心将对象“返回”回池,它会自动处理。
#include <memory>
#include <tbb/concurrent_queue.h>
namespace FastRank
{
template<typename T>
class object_pool
{
typedef tbb::concurrent_bounded_queue<std::shared_ptr<T>> pool_t;
std::shared_ptr<pool_t> pool_;
public:
object_pool() : pool_(new pool_t())
{
}
std::shared_ptr<T> get()
{
std::shared_ptr<T> ptr;
if(!pool_.try_pop(ptr))
ptr = std::make_shared<T>();
auto pool = pool_;
return std::shared_ptr<T>(ptr.get(), [pool, ptr](T*){pool->push(ptr);});
}
}
}
没有concurrent_queue
#include <memory>
#include <queue>
#include <boost/mutex.hpp>
namespace FastRank
{
template<typename T>
class object_pool
{
typedef std::pair<std::queue<std::shared_ptr<T>>, boost::mutex> pool_t;
std::shared_ptr<pool_t> pool_;
public:
object_pool() : pool_(new pool_t())
{
}
std::shared_ptr<T> get()
{
std::shared_ptr<T> ptr;
{
boost::scoped_lock<boost::mutex> lock(pool_->second);
if(!pool_->first.empty())
{
ptr = std::move(pool->first.front());
pool->first.pop()
}
}
if(!ptr)
ptr = std::make_shared<T>();
auto pool = pool_;
return std::shared_ptr<T>(ptr.get(), [pool, ptr](T*)
{
boost::scoped_lock<boost::mutex> lock(pool->second);
pool->push(ptr);
});
}
}
}