C++ 模版与线程安全锁的应用

来源:互联网 发布:刷单软件 编辑:程序博客网 时间:2024/06/05 15:17

/*
 * =====================================================================================
 *
 *       Filename:  safe.h
 *
 *    Description:  MT safe
 *
 *
 *
 * =====================================================================================
 */

#include <sys/types.h>
#include <pthread.h>

#ifndef __VOLLIN_J_SAFE_H__
#define __VOLLIN_J_SAFE_H__

#define LOCK(Mutex) JLockHelper __lock__(Mutex)

class JLockHelper;

struct JAbsXMutex
{
    virtual void Lock() const= 0;
    virtual void Unlock() const= 0;
};

/*****************************************************
 *  JXMutex    X锁(互斥锁)类
 *****************************************************/
class  JXMutex:public JAbsXMutex
{
public:
    JXMutex()
    {
        pthread_mutex_init (&m_Mutex,NULL);
    }
    virtual ~JXMutex()
    {
        pthread_mutex_destroy(&m_Mutex);
    }
private:
    JXMutex(const JXMutex&);                        //禁止锁拷贝
    const JXMutex& operator =(const JXMutex &);     //禁止锁赋值
public:
    void Lock() const
    {
        pthread_mutex_lock (&m_Mutex);    //锁定
    }
    void Unlock() const
    {
        pthread_mutex_unlock (&m_Mutex);    //解锁
    }
public:
    mutable pthread_mutex_t     m_Mutex;                    //互斥锁
};


/**************************************************************************************
 *  JSafe    基于各类锁的安全类模板
 **************************************************************************************/
template<class _Tp,class _Mutex = JXMutex>
class JSafe
{
public:
    typedef _Tp value_type;
    typedef _Mutex lock_type;
    JSafe(void){}
    ~JSafe(void){}
    explicit JSafe(const _Tp& other)
    {
        m_Data = other;
    }
    JSafe(const JSafe& other)
    {
        LOCK(other);
        m_Data = other.m_Data;
    }
    operator const _Tp() const   //定义强制类型转换,注意已锁定时不能使用;虽然使用起来方便,但实际上都可以由获取值的Value函数代替
    {
        LOCK(m_Mutex);
        return m_Data;
    }
    JSafe& operator =(const JSafe& other)
    {
        LOCK(other);
        {
            LOCK(m_Mutex);
            m_Data = other.m_Data;
        }
        return *this;
    }
    void Value(const _Tp& other)//设置值
    {
        LOCK(m_Mutex);
        m_Data = other;
    }
    const _Tp Value(void) const //获取值
    {
        LOCK(m_Mutex);
        return m_Data;
    }
    void Lock(void) const //加锁
    {
        m_Mutex.Lock();
    }
    void Unlock(void) const //解锁
    {
        m_Mutex.Unlock();
    }
    _Tp&    Data(void) //加锁后方可安全使用此函数得到资源的引用,如未加锁直接调用可能造成相应的安全问题
    {
        return m_Data;
    }
protected:
    _Tp m_Data;         //数据成员
    mutable _Mutex  m_Mutex;    //锁成员
    friend class JLockHelper;
};

/**************************************************************************************
 * JLockHelper    使用于有Lock,及Unlock成员函数的安全类或锁类的辅助加锁对象,
 *                可以做到异常安全的解锁
 * 说明:          在创建类时加锁,析构时解锁;一种简单的但不是必须的使用方法是使用{}
 *                将要加锁的代码括起来,在{}中第一行定义该辅助类,则}时将自动解锁
 ****************************************************************************************/
class JLockHelper
{
public:
    JLockHelper(const JAbsXMutex& xMutex):m_xMutex(xMutex)
    {
        m_xMutex.Lock();
    }

    template<class _Tp,class _Mutex>
    JLockHelper(const JSafe<_Tp,_Mutex>& S):m_xMutex(S.m_Mutex)
    {
        m_xMutex.Lock();
    }

    ~JLockHelper()
    {
        m_xMutex.Unlock();
    }

private:
    const JAbsXMutex& m_xMutex;
};


template<class _Tp>
class JSafeNum : public JSafe<_Tp>
{
public:
    typedef JSafe<_Tp> safe_type;
    explicit JSafeNum(const _Tp& _Value = 0):JSafe<_Tp>(_Value){}
    JSafeNum& operator ++()
    {
        LOCK(safe_type::m_Mutex);
        safe_type::m_Data++;
        return *this;
    }
    JSafeNum operator ++(int)
    {
        LOCK(safe_type::m_Mutex);
        JSafeNum tmp(safe_type::m_Data++);
        return tmp;
    }
    JSafeNum& operator +=(const _Tp& other)
    {
        LOCK(safe_type::m_Mutex);
        safe_type::m_Data += other;
        return *this;
    }
    JSafeNum& operator --(void)
    {
        LOCK(safe_type::m_Mutex);
        safe_type::m_Data--;
        return *this;
    }
    JSafeNum operator --(int)
    {
        LOCK(safe_type::m_Mutex);
        JSafeNum tmp(safe_type::m_Data--);
        return tmp;
    }
    JSafeNum& operator -=(const _Tp& other)
    {
        LOCK(safe_type::m_Mutex);
        safe_type::m_Data -= other;
        return *this;
    }
    JSafeNum& operator =(const _Tp& other)
    {
        LOCK(safe_type::m_Mutex);
        safe_type::m_Data = other;
        return *this;
    }
};

typedef JSafe<bool> JSafeBool;
typedef JSafeNum<int> JSafeInt;
typedef JSafeNum<long> JSafeLong;
typedef JSafeNum<u_int> JSafeUint;

//安全容器,适用于stl容器类
template<class _Con>
class JSafeCon :public JSafe<_Con>
{
public:
    typedef JSafe<_Con> _Base;
    typedef JSafeCon<_Con> _Self;
    typedef _Con con_type;
    typedef typename con_type::iterator iterator;
    explicit JSafeCon(void):_Base(){}
    bool empty()
    {
        LOCK(_Base::m_Mutex);
        return _Base::m_Data.empty();
    }
    size_t size()
    {
        LOCK(_Base::m_Mutex);
        return _Base::m_Data.size();
    }
    void swap(con_type& Seq)
    {
        LOCK(_Base::m_Mutex);
        _Base::m_Data.swap(Seq);
    }
    //以下两个函数及其使用均需在同步的保护下
    iterator begin()
    {
        return _Base::m_Data.begin();
    }
    iterator end()
    {
        return _Base::m_Data.end();
    }
};

//安全序列(适用于stl的序列容器类如vector,list,...)
template<class _Sequence>
class JSafeSeq : public JSafeCon<_Sequence>
{
public:
    typedef JSafeCon<_Sequence> _Base;
    typedef JSafeSeq<_Sequence> _Self;
    typedef _Sequence seq_type;
    typedef typename seq_type::iterator iterator;
    typedef typename seq_type::value_type value_type;

    explicit JSafeSeq(void):_Base(){}
    void push_back(const value_type& Val)
    {
        LOCK(_Base::m_Mutex);
        _Base::m_Data.push_back(Val);
    }
};

//适用于stl前向插入序列如deque等
template<class _FSeq>
class JSafeFSeq:public JSafeSeq<_FSeq>
{
public:
    typedef JSafeSeq<_FSeq> _Base;
    typedef JSafeFSeq<_FSeq> _Self;
    typedef typename _Base::seq_type seq_type;
    typedef typename seq_type::iterator iterator;
    typedef typename seq_type::value_type value_type;

    explicit JSafeFSeq(void):_Base(){}

    bool pop_front(value_type& Val)//取出第一个元素
    {
        LOCK(_Base::m_Mutex);
        if (_Base::m_Data.empty())
        {
            return false;
        }
        else
        {
            Val = *(_Base::m_Data.begin());
            _Base::m_Data.pop_front();
            return true;
        }
    }
};

//安全map类,适用于stl::map
template<class _Map>
class JSafeMap :public JSafeCon<_Map>
{
public:
    typedef JSafeCon<_Map> _Base;
    typedef JSafeSeq<_Map> _Self;
    typedef _Map map_type;
    typedef typename map_type::iterator iterator;
    typedef typename map_type::const_iterator const_iterator;
    typedef typename map_type::value_type value_type;
    typedef typename value_type::first_type key_type;
    typedef typename value_type::second_type data_type;
    explicit JSafeMap(void):_Base(){}
    void insert(const value_type& Val)
    {
        LOCK(_Base::m_Mutex);
        _Base::m_Data.insert(Val);
    }
    bool find(const key_type& Key) const
    {
        LOCK(_Base::m_Mutex);
        return _Base::m_Data.find(Key) != _Base::m_Data.end();
    }
    bool find(const key_type& Key,data_type& Val) const
    {
        LOCK(_Base::m_Mutex);
        const_iterator it = _Base::m_Data.find(Key);
        if ( _Base::m_Data.end() != it )
        {
            Val = it->second;
            return true;
        }
        return false;
    }
    void erase(const key_type& Key)
    {
        LOCK(_Base::m_Mutex);
        _Base::m_Data.erase(Key);
    }
    data_type get(const key_type& Key,const data_type& Default) const
    {
        LOCK(_Base::m_Mutex);
        const_iterator it = _Base::m_Data.find(Key);
        if ( _Base::m_Data.end() == it )
        {
            return Default;
        }
        else
        {
            return it->second();
        }
    }
    bool find_erase(const key_type& Key,data_type& Val)
    {
        LOCK(_Base::m_Mutex);
        iterator it = _Base::m_Data.find(Key);
        if ( _Base::m_Data.end() != it )
        {
            Val = it->second;
            _Base::m_Data.erase(it);
            return true;
        }
        return false;
    }
    void set(const key_type& Key,const data_type& Val)
    {
        LOCK(_Base::m_Mutex);
        _Base::m_Data[Key] = Val;
    }
};

#endif //head file