C++用锁实现线程安全的stack容器

cpp 复制代码
#include <exception>
#include <memory>
#include <mutex>
#include <stack>
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()
    : data(std::stack<T>()){}
  threadsafe_stack(const threadsafe_stack& other)
  {
    std::lock_guard<std::mutex> lock(other.m);
    data = other.data; // 1 在构造函数体中的执行拷贝
  }
  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(); // 在调用pop前,检查栈是否为空
    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();
  }
};

为什么STL设计时top和pop没组合在一起?

假设有一个stack<vector>,vector是一个动态容器,当你拷贝一个vetcor,标准库会从堆上分配很多内存来完成这次拷贝。当这个系统处在重度负荷,或有严重的资源限制的情况下,这种内存分配就会失败,所以vector的拷贝构造函数可能会抛出一个std::bad_alloc异常。当vector中存有大量元素时,这种情况发生的可能性更大。当pop()函数返回"弹出值"时(也就是从栈中将这个值移除),会有一个潜在的问题:这个值被返回到调用函数的时候,栈才被改变;但当拷贝数据的时候,调用函数抛出一个异常会怎么样? 如果事情真的发生了,要弹出的数据将会丢失;它的确从栈上移出了,但是拷贝失败了!std::stack的设计人员将这个操作分为两部分:先获取顶部元素(top()),然后从栈中移除(pop())。这样,在不能安全的将元素拷贝出去的情况下,栈中的这个数据还依旧存在,没有丢失。当问题是堆空间不足,应用可能会释放一些内存,然后再进行尝试。

相关推荐
傻童:CPU10 小时前
C语言练习题
c语言·开发语言
极地星光10 小时前
协程:实战与系统集成(高级篇)
开发语言
咔咔咔的10 小时前
3461. 判断操作后字符串中的数字是否相等 I
c++
0和1的舞者10 小时前
《Git:从入门到精通(八)——企业级git开发相关内容》
大数据·开发语言·git·搜索引擎·全文检索·软件工程·初学者
liulilittle10 小时前
LwIP协议栈MPA多进程架构
服务器·开发语言·网络·c++·架构·lwip·通信
水淹萌龙11 小时前
玩转 Go 表达式引擎:expr 实战指南
开发语言·后端·golang
艾莉丝努力练剑11 小时前
【C++:继承】面向对象编程精要:C++继承机制深度解析与最佳实践
开发语言·c++·人工智能·继承·c++进阶
penguin_bark11 小时前
C++ 异步编程(future、promise、packaged_task、async)
java·开发语言·c++
小龙报11 小时前
《数组和函数的实践游戏---扫雷游戏(基础版附源码)》
c语言·开发语言·windows·游戏·创业创新·学习方法·visual studio
又是忙碌的一天11 小时前
Java基础 与运算
java·开发语言