线程安全堆栈实现
Thread safe stack implementation
阅读
Anthony Williams的"C++ Concurrency in Action"(第1版)
您可以找到线程安全堆栈的以下实现:
struct empty_stack: std::exception
{
const char* what() const throw()
{
return "empty stack";
}
};
template<typename T>
class threadsafe_stack
{
private:
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack(){}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data=other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(new_value);
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
std::shared_ptr<T> const res(std::make_shared<T>(data.top()));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=data.top();
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
};
因此,在讨论可能的实现时,作者提出了 pop() 的下一个版本:
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=data.top();
data.pop();
}
并突出显示了一些注意事项,其中一个警告是,此解决方案要求存储在堆栈中的类型必须是可分配的。
同时,他展示了下一个用法示例:
std::vector<int> result;
some_stack.pop(result);
现在我的反对意见:在我看来,需要另一个警告:存储在线程安全堆栈中的类型的赋值运算符不得像 std::
vector 的赋值运算符那样抛出异常。
我的反对是基于吗?
我反对的理由:它源于对作者提出的下一个解决方案(未实现)的分析:
"如果 return by value 不能抛出异常,你可以编写一个值返回 pop(),所以存储在线程安全堆栈中的类型需要一个不抛出的复制构造函数或移动构造函数"。
谢谢你的时间。
为什么你觉得抛出empty_stack
是可以的,但抛出向量赋值可能抛出的任何内容就不行了?
T pop()
的问题在于它需要首先从堆栈中删除值,然后复制它 - 这可能会抛出,此时您将丢失值; 它既不会返回也不会留在容器中。换句话说,这样的设计不能提供强有力的例外保证。
这就是为什么std::stack
提供了两个单独的调用 -T top()
读取顶部而不修改堆栈(如果抛出,堆栈保持不变),以及修改堆栈并保证不抛出的void pop()
。
相关文章:
- 如何在 c++ 中实现堆栈数组?
- 使用链表实现堆栈时出错
- 在给定程序中降低矢量数组实现堆栈的时间复杂度有哪些不同的可能方法?
- C++ 使用数组实现堆栈
- 关于在C 中实现堆栈的问题
- 使用链接列表在C 中实现堆栈
- c++ 中 if 语句中的多个条件(通过链表实现堆栈)
- C 内存泄漏错误在实现堆栈类时
- 尝试实现堆栈时C++未定义的引用
- 链表与动态数组用于使用向量类实现堆栈
- 在C++中实现堆栈类
- 可视化 在C++中实现堆栈
- 使用链接列表实现堆栈,调试断言失败
- 我怎样才能实现堆栈的向量
- 在没有动态内存分配的情况下实现堆栈
- 如何使用 std::vector 实现堆栈
- 在c++中使用链表实现堆栈
- 在哪里实现堆栈类(在非递归二进制搜索函数中使用)
- 使用双链表实现堆栈的错误
- 在c++中使用链表实现堆栈,复制构造函数