我实现了一个线程安全的模板化队列:
template<class T> class queue {
private:
boost::mutex mutex;
boost::condition_variable emptyCondition;
boost::condition_variable fullCondition;
boost::scoped_ptr< std::queue<T> > std_queue;
...
public:
...
T pop() {
T r; // [*]
{
boost::mutex::scoped_lock popLock(mutex);
while (queueIsEmpty())
emptyCondition.wait(popLock);
r = std_queue->front();
std_queue->pop();
}
fullCondition.notify_one();
return r;
}
...
我无法以我的方式实例化对象(标有[*]
的地方),因为缺少T
的构造函数,没有正式的参数。
那么:有没有办法,可能使用指向T
的指针和复制构造函数(我知道它是为每个T
实现的),以避免许多模板特化?
修改1
我也想过这个可能的解决方案。
T pop() {
boost::mutex::scoped_lock popLock(mutex);
while (queueIsEmpty())
emptyCondition.wait(popLock);
T r(std_queue->front());
std_queue->pop();
// update overall number of pop
popNo++;
popLock.unlock();
fullCondition.notify_one();
return r;
}
它会起作用吗?
答案 0 :(得分:2)
此方案的一个选项是使用boost::optional
:
T pop() {
boost::optional<T> r;
{
boost::mutex::scoped_lock popLock(mutex);
while (queueIsEmpty())
emptyCondition.wait(popLock);
r = std_queue->front();
std_queue->pop();
}
fullCondition.notify_one();
return *r; // r is guaranteed to be engaged at this point
}
boost::optional
在运行时会注意跟踪是否已构造其包含的T
,因此是否需要销毁它。 (请注意,此处您实际上并不需要boost::mutex::scoped_lock; you can use
boost :: lock_guard`的完整功能。)
另一种方法是注意scoped_lock
可以释放:
T pop() {
boost::mutex::scoped_lock popLock(mutex);
while (queueIsEmpty())
emptyCondition.wait(popLock);
T r = std_queue->front();
std_queue->pop();
popLock.release();
fullCondition.notify_one();
return r;
}
这里的缺点是popLock
的范围不太清楚,代码更改可能导致不安全的代码或死锁。
答案 1 :(得分:0)
如果您手动解锁,可以摆脱括号,这样就无需预先创建T:
T pop() {
boost::mutex::scoped_lock popLock(mutex);
while (queueIsEmpty())
emptyCondition.wait(popLock);
T r = std_queue->front();
std_queue->pop();
popLock.unlock();
fullCondition.notify_one();
return r;
}