【发布时间】:2019-12-24 07:23:33
【问题描述】:
我有一个假定的线程安全阻塞队列实现,它应该是 std::queue 的包装器 下面是它的实现:
template <typename _Tp>
class SharedQueue
{
public:
explicit SharedQueue(bool isBlocking = true) : isBlocking_(isBlocking) {}
virtual ~SharedQueue() {}
virtual const _Tp& front()
{
std::unique_lock<std::mutex> mlock(mtx_);
// if this is a blocking queue, wait to be notified when when a new object is added
if (isBlocking_)
{
while (queue_.empty())
{
cv_.wait(mlock);
}
}
return queue_.front();
}
virtual bool empty() const
{
std::unique_lock<std::mutex> mlock(mtx_);
return queue_.empty();
}
virtual size_t size() const
{
std::unique_lock<std::mutex> mlock(mtx_);
return queue_.size();
}
virtual void push(const _Tp& value)
{
std::unique_lock<std::mutex> mlock(mtx_);
queue_.push(value);
if (isBlocking_)
{
if (queue_.size() == 1)
{
cv_.notify_all();
}
}
}
virtual void push(_Tp&& value)
{
{
std::unique_lock<std::mutex> mlock(mtx_);
queue_.push(std::move(value));
if (isBlocking_)
{
if (queue_.size() == 1)
{
cv_.notify_all();
}
}
}
}
template <typename... _Args>
void emplace(_Args&&... __args)
{
{
std::unique_lock<std::mutex> mlock(mtx_);
queue_.emplace(std::forward<_Args>(__args)...);
if (isBlocking_)
{
if (queue_.size() == 1)
{
cv_.notify_all();
}
}
}
}
virtual void pop()
{
std::unique_lock<std::mutex> mlock(mtx_);
if (!queue_.empty())
{
queue_.pop();
}
}
private:
bool isBlocking_;
mutable std::mutex mtx_;
mutable std::condition_variable cv_;
std::queue<_Tp> queue_;
};
我希望能够将 unique_ptr 放置在此队列中,并且我知道当从客户端应用程序将 unique_ptr 推入队列时,我必须在 unique_ptr 上调用 std::move。 这是我的问题... 在我的 main 中,当我按如下方式创建 std::queue 时,我的程序编译得很好
std::queue<std::unique_ptr<int32_t>> q1;
但是,当我创建如下 SharedQueue 的实例时,程序无法编译。
SharedQueue<std::unique_ptr<int32_t>> q2;
我收到一条错误消息,告诉我复制构造函数在 unique_ptr 类中被删除,这是可以理解的。我想我只是想知道 std::queue 做了什么代码可以编译,而我的代码“似乎”是 std::queue 的包装器并类似地实现操作。
编辑: 如果我替换,我可以让 SharedQueue 编译
queue_.push(value);
与
queue_.push(std::forward<_Tp>(const_cast<_Tp&>(value)));
在接受左值引用的 push 方法中。
【问题讨论】:
-
您是否尝试将任何值推送到
q1? -
@Shawn 是的,当我使用 std::move 正确执行此操作时,我不会收到编译错误,但是当我尝试在没有它的情况下调用 push 时,我收到一个错误,告诉我的复制 ctor在 std::unique_ptr 类中被删除
-
没错。在不使用
std::move()的情况下查看您的SharedQueue推入队列的位置? -
那不要和不可复制的类型一起使用?
-
@tree 因为
std::queue使用模板/SFINAE 魔法和std::enable_if来包含仅在类可复制时才复制的函数。
标签: c++ multithreading c++11