OpenThread中的condition和barrier

来源:互联网 发布:浮云网淘宝小号 编辑:程序博客网 时间:2024/04/28 17:05

condition应用

condition源码
#ifndef _WIN32CONDITIONPRIVATEDATA_H_#define _WIN32CONDITIONPRIVATEDATA_H_#ifndef _WINDOWS_#define WIN32_LEAN_AND_MEAN#include <windows.h>#endif#define InterlockedGet(x) InterlockedExchangeAdd(x,0)namespace OpenThreads {class Condition;class Win32ConditionPrivateData {public:friend class Condition;/// number of waiters.long waiters_;Win32ConditionPrivateData (){waiters_ = 0;sema_ = CreateSemaphore(NULL,0,0x7fffffff,NULL);waiters_done_ = CreateEvent(NULL,FALSE,FALSE,NULL);}~Win32ConditionPrivateData ();inline int broadcast (){      int have_waiters = 0;long w = InterlockedGet(&waiters_);if (w > 0){  // we are broadcasting.        was_broadcast_ = 1;  have_waiters = 1;}int result = 0;if (have_waiters)    {// Wake up all the waiters.ReleaseSemaphore(sema_,waiters_,NULL);WaitForSingleObject(waiters_done_,INFINITE) ;//end of broadcastingwas_broadcast_ = 0;    }return result;}inline int signal(){long w = InterlockedGet(&waiters_);    int have_waiters = w > 0; int result = 0;if (have_waiters)    {if( !ReleaseSemaphore(sema_,1,NULL) )result = -1;    }return result;}inline int wait (Mutex& external_mutex, long timeout_ms){// Prevent race conditions on the <waiters_> count.InterlockedIncrement(&waiters_);int result = 0;        external_mutex.unlock();DWORD dwResult = WaitForSingleObject(sema_,timeout_ms);if(dwResult != WAIT_OBJECT_0)result = (int)dwResult;// We're ready to return, so there's one less waiter.InterlockedDecrement(&waiters_);long w = InterlockedGet(&waiters_);int last_waiter = was_broadcast_ && w == 0;if (result != -1 && last_waiter)SetEvent(waiters_done_);external_mutex.lock();return result;}protected:  /// Serialize access to the waiters count.  /// Mutex waiters_lock_;  /// Queue up threads waiting for the condition to become signaled.  HANDLE sema_;  /**   * An auto reset event used by the broadcast/signal thread to wait   * for the waiting thread(s) to wake up and get a chance at the   * semaphore.   */  HANDLE waiters_done_;  /// Keeps track of whether we were broadcasting or just signaling.  size_t was_broadcast_;};#undef InterlockedGet}

测试代码

#include <Windows.h>#include <OpenThreads/Thread.h>#include <OpenThreads/Mutex.h>#include <OpenThreads/Condition.h>#include <iostream>using namespace std;int g_number = 0;OpenThreads::Condition g_condition;OpenThreads::Mutex g_mutex;class A : public OpenThreads::Thread{void run(){while(1){g_mutex.lock();g_number++;g_mutex.unlock();cout<<"A: number = "<<g_number<<endl;if (g_number >= 10){g_condition.signal();cout<<"A: signal"<<endl;return;}::Sleep(10);}}};class B : public OpenThreads::Thread{void run(){while(1){g_mutex.lock();g_number++;g_mutex.unlock();cout<<"B: number = "<<g_number<<endl;if (g_number >= 10){g_condition.signal();cout<<"B: signal"<<endl;return;}::Sleep(10);}}};class C : public OpenThreads::Thread{void run(){g_mutex.lock();cout<<"C: wait"<<endl;g_condition.wait(&g_mutex);cout<<"C: number = -1"<<endl;g_number = -1;g_mutex.unlock();}};int main(){A a;B b;C c;a.start();b.start();c.start();a.join();b.join();c.join();}



barrier为condition和mutex的应用,让线程可以同步等待运行
 
barrier源码
#ifndef _Win32BARRIERPRIVATEDATA_H_#define _Win32BARRIERPRIVATEDATA_H_#ifndef _WINDOWS_#define WIN32_LEAN_AND_MEAN#include <windows.h>#endif#include <OpenThreads/Mutex.h>#include <OpenThreads/Condition.h>namespace OpenThreads {class Barrier;class Win32BarrierPrivateData {    friend class Barrier;private:    Win32BarrierPrivateData() {};    ~Win32BarrierPrivateData();    Condition cond;            // cv for waiters at barrier    Mutex    lock;            // mutex for waiters at barrier    volatile int       maxcnt;          // number of threads to wait for    volatile int       cnt;             // number of waiting threads    volatile int       phase;           // flag to seperate two barriers};

#include  <OpenThreads/Barrier.h>#include "Win32BarrierPrivateData.h"using namespace OpenThreads;// so compiler can place it somewhereWin32BarrierPrivateData::~Win32BarrierPrivateData(){};//----------------------------------------------------------------------------//// Decription: Constructor//// Use: public.//Barrier::Barrier(int numThreads) {    Win32BarrierPrivateData *pd = new Win32BarrierPrivateData();    pd->cnt = 0;    pd->phase = 0;    pd->maxcnt = numThreads;    _prvData = static_cast<void *>(pd);}//----------------------------------------------------------------------------//// Decription: Destructor//// Use: public.//Barrier::~Barrier() {    Win32BarrierPrivateData *pd =        static_cast<Win32BarrierPrivateData*>(_prvData);    delete pd;}//----------------------------------------------------------------------------//// Decription: Reset the barrier to its original state//// Use: public.//void Barrier::reset() {    Win32BarrierPrivateData *pd =        static_cast<Win32BarrierPrivateData*>(_prvData);    pd->cnt = 0;    pd->phase = 0;}//----------------------------------------------------------------------------//// Decription: Block until numThreads threads have entered the barrier.//// Use: public.//void Barrier::block(unsigned int numThreads) {    Win32BarrierPrivateData *pd =        static_cast<Win32BarrierPrivateData*>(_prvData);    if(numThreads != 0) pd->maxcnt = numThreads;    int my_phase;    pd->lock.lock();    my_phase = pd->phase;    ++pd->cnt;    if (pd->cnt == pd->maxcnt) {             // I am the last onepd->cnt = 0;                         // reset for next usepd->phase = 1 - my_phase;            // toggle phasepd->cond.broadcast();    }else{     while (pd->phase == my_phase) {pd->cond.wait(&pd->lock);}}    pd->lock.unlock();}



原创粉丝点击