多线程mutex locker condition简单封装

#ifndef _MULTITHREAD_H_
#define _MULTITHREAD_H_

#include <pthread.h>
#include <assert.h>
#include <errno.h>


class MutexLock
{
public:
    MutexLock():holder_(0)
    {
        int iret = pthread_mutex_init(&mutex_,NULL);
        assert(0 == iret);(void) iret;
    }

    ~MutexLock()
    {
        assert(0 == holder_);//when destroy non lock
        int iret = pthread_mutex_destroy(&mutex_);
        assert(0 == iret);(void) iret;
    }

    /*bool isLockedByThisThread()
    {
        return holder_ == CurrentThread::tid();
    }

    void assertLocked()
    {
        assert(isLockedByThisThread() );
    }*/

protected:
    //internal usage
    void lock()
    {
        pthread_mutex_lock(&mutex_);
        //holder_ = CurrentThread::tid();
    }

    void unlock()
    {
        holder_ = 0;
        pthread_mutex_unlock(&mutex_);
    }

    pthread_mutex_t* getPthreadMutex() /*non-const*/
    {
        return &mutex_;
    }
private:
    pthread_mutex_t mutex_;
    pid_t holder_;
};

class MutexLockGuard
{
public:
    explicit MutexLockGuard(MutexLock& mutex):mutex_(mutex)
    {
        mutex_.lock();
    }
    ~MutexLockGuard()
    {
        mutex_.unlock();
    }
private:
    MutexLock& mutex_;
};

//prevent misuse like:
//MutexLockGuard(mutex_); 遗漏变量名,产生一个临时变量又马上销毁了
//right method: MutexLockGuard guard(mutex_);
#define MutexLockGuard(x) error "Missing guard object name"

class Condition
{
public:
    explicit Condition(MutexLock& mutex):mutex_(mutex)
    {
        pthread_cond_init(&pcond_,NULL);
    }
    ~Condition()
    {
        pthread_cond_destroy(&pcond_);
    }

    void wait()
    {
        pthread_cond_wait(&pcond_,mutex_.getPthreadMutex() );
    }

    bool waitForSeconds(int second)
    {
        /* struct timespct{
         *  time_t tv_sec;
         *  long tv_nsec;
         * };
         * */
        struct timespec abstime;
        /*clock_gettime 提供纳秒的精确度
         *int clock_gettime(clockid_t clk_id, struct timespec* tp);
         *clockid_t用于指定计时时钟的类型:
         *CLOCK_REALTIME,系统实时时间,随着系统实时时间改变而改变,从UTC1970-1-1 0:0:0开始计时,中间如果系统时间更改,则对应的时间相应改变
         *CLOCK_MONOTONIC,从系统启动这一刻起开始计时,不受系统时间被用户改变的影响
         *CLOCK_PROCESS_CPUTIME_ID,本进程到当前代码系统CPU花费时间
         *CLOCK_THREAD_CPUTIME_ID,线程CPU时间
         */
        clock_gettime(CLOCK_REALTIME,&abstime);
        abstime.tv_sec += second;
        return ETIMEDOUT == pthread_cond_timedwait(&pcond_,mutex_.getPthreadMutex(),&abstime);
    }

    void notify()
    {
        pthread_cond_signal(&pcond_);
    }

    void notifyAll()
    {
        pthread_cond_broadcast(&pcond_);
    }
private:
    MutexLock& mutex_;
    pthread_cond_t pcond_;
};
#endif //_MULTITHREAD_H_

学习完陈硕大神的多线程编程,自己也依葫芦画瓢封装了个简单的多线程MutextLock、MutexLockGuard、Condition,代码如上。

下面给出一个简单用法,用于构造一个简单的同步阻塞队列。

#include "MultiThread.h"
#include <deque>
#include <assert.h>

template<typename T>
class BlockingQueue
{
public:
    BlockingQueue()
        :mutex_(),
        notEmpty_(),
        queue_()
    {
    }

    ~BlockingQueue()
    {
    }

    void put(const T& x)
    {
        MutexLockGuard lock(mutex_);//局部作用域正好是临界区
        queue_.push_back(x);
        notEmpty_.notify();
    }

    T take()
    {
        MutexLockGuard lock(mutex_);
        //while判断,因为可能被意外唤醒,"惊群"
        while(queue_.empty() )
        {
            notEmpty_.wait();
        }
        assert(!queue_.empty() );
        T front(queue_.front() );
        queue_.pop_front();
        return front;
    }

    size_t size()
    {
        MutexLockGuard lock();
        return queue_.size();
    }
private:
    mutable MutexLock mutex_;
    Condition notEmpty_;
    std::deque<T> queue_;
};


通过上面例子我们可以看到简单封装的便捷使用,其中MutexLockGuard使用栈上空间,其局部作用域正好是临界区。该队列是线程安全的,我们将同步做到队列内部,避免外部线程分别加锁,降低了复杂性。

你可能感兴趣的:(多线程mutex locker condition简单封装)