muduo 库解析之九:Condition

Condition Variable

初始化和销毁

#include <pthread.h>

int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);

pthread_cond_t cond = PTHREAD_COND_INITIALIZER
  • pthread_cond_init函数初始化一个Condition Variable,attr参数为NULL则表示缺省属性。
  • pthread_cond_destroy函数销毁一个Condition Variable。
  • 如果Condition Variable是静态分配的,也可以用宏定义PTHEAD_COND_INITIALIZER初始化,相当于用pthread_cond_init函数初始化并且attr参数为NULL
  • 成功返回0,失败返回错误号。

等待和通知

#include <pthread.h>

int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct 	timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
  • 一个Condition Variable总是和一个Mutex搭配使用的。一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待,这个函数做以下三步操作:
    • 释放Mutex。
    • 阻塞等待。
    • 当被唤醒时,重新获得Mutex并返回。
  • pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT
  • 一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程。
  • 调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程。

源码

Condition.h

#pragma once

#include "Mutex.h"
#include  <pthread.h>

namespace muduo
{
    class Condition
    {
    public:
        Condition(MutexLock& mutex) : mutex_(mutex)
        {
            MCHECK(pthread_cond_init(&pcond_,NULL));
        }

        ~Condition()
        {
            MCHECK(pthread_cond_destroy(&pcond_));
        }

        void wait()
        {
            //@ pthread_cond_wait will release mutex
            MutexLock::UnassignGuard ug(mutex_);
            MCHECK(pthread_cond_wait(&pcond_, mutex_.get_mutex()));
        }

        //@ returns true if time out, false otherwise.
        bool wait_for_seconds(double seconds);

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

        void notify_all()
        {
            MCHECK(pthread_cond_broadcast(&pcond_));
        }

    private:
        MutexLock& mutex_;
        pthread_cond_t pcond_;
    };
}

Condition.cc

#include "Condition.h"

namespace muduo
{

    //@ returns true if time out, false otherwise.
    bool Condition::wait_for_seconds(double seconds)
    {
        struct timespec abs_time;
        clock_gettime(CLOCK_REALTIME,&abs_time);
        const int64_t kNanoSecondsPerSecond = 1000000000;
        int64_t nano_seconds = static_cast<int64_t>(seconds * kNanoSecondsPerSecond);

        abs_time.tv_sec += static_cast<time_t>((abs_time.tv_sec + nano_seconds) / kNanoSecondsPerSecond);
        abs_time.tv_nsec += static_cast<long>((abs_time.tv_sec + nano_seconds) % kNanoSecondsPerSecond);

        MutexLock::UnassignGuard ug(mutex_);
        return ETIMEDOUT == pthread_cond_timedwait(&pcond_,mutex_.get_mutex(),&abs_time);
    }
}

原文地址:https://www.cnblogs.com/xiaojianliu/p/14697506.html