c++线程安全的栈

整理自c++并发编程实战

/*
 * threadsafe_stack.cpp
 *
 *  Created on: Nov 30, 2017
 *      Author: clh01s@163.com
 *      线程安全的栈
 */

#include <exception>
#include <iostream>
#include <mutex>
#include <stack>
#include <memory>
#include <string>

using namespace std;

struct empty_stack: exception
{
    const char* what() const throw();
};

template<typename T>
class threadsafe_stack
{
public:
    threadsafe_stack(){}
    threadsafe_stack(const threadsafe_stack& other)
    {
        lock_guard<mutex> lock(other.m);
        data = other.data;
    }
    //禁止使用=
    threadsafe_stack& operator=(const threadsafe_stack&) = delete;

    void push(T new_value)
    {
        //调用锁
        lock_guard<mutex> lock(m);
        /* 调用data.push()可能会抛出异常
         * 如果复制或者移动数据项抛出异常或
         * 者不能分配足够的内存来扩展下层的
         * 数据结构。
         * 不管怎样,stack保证了它是安全的
         * 因此这不是一个问题。
         */
        cout<<"push value = "<<new_value<<endl;
        data.push(move(new_value));
    }

    shared_ptr<T> pop()
    {
        lock_guard<mutex> lock(m);
        /* 在函数pop()重载的第一种形式中
         * 他的代码可能会抛出一个empty_stack
         * 异常,但是没有做任何修改,因此它时安全的
         */
        if(data.empty()) throw empty_stack();
        /* 创建res可能会抛出异常
         * 1.调用make_shared可能会抛出异常
         * 因为它无法为新对象和需要引用计数的
         * 内部数据分配内存。
         * 2.复制构造函数或移动构造函数中返回
         * 数据项被复制/移动到新分配的内存时也
         * 可能会抛出异常。
         * 这两种情况下c++运行库和标准库确保没
         * 有内存泄露并且新对象被正确销毁。因为
         * 你仍然没有修改下层的栈所以没有问题。
         */
        shared_ptr<T> const res(
                make_shared<T>(move(data.top())));
        //调用data.pop()保证了不会抛出异常,因此pop()的重载是异常安全的
        data.pop();
        return res;
    }

    void pop(T& value)
    {
        lock_guard<mutex> lock(m);
        if(data.empty()) throw empty_stack();
        /* 这次于第一次时类似的,只不过这次是拷贝赋值
         * 或移动赋值操作符抛出异常,而不是构造新对象
         * 和一个shared_ptr实例抛出异常
         */
        value = move(data.pop());
        //这于上一个重载相同不会抛出异常
        data.pop();
    }

    bool empty() const
    {
        lock_guard<mutex> lock(m);
        return data.empty();
    }
private:
    stack<T> data;
    mutable mutex m;
};

int main()
{
    threadsafe_stack<string> a;
    a.push("aa");
    a.push("bb");
    return 0;
}

程序输出:

clh@clh:~/testcode/并发$ g++ threadsafe_stack.cpp -std=c++11
clh@clh:~/testcode/并发$ ./a.out 
push value = aa
push value = bb

转载请注明源地址:http://blog.csdn.net/clh01s

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值