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 broadcasting
was_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 somewhere
Win32BarrierPrivateData::~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 one
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->cond.broadcast();
}else{
while (pd->phase == my_phase) {
pd->cond.wait(&pd->lock);
}
}
pd->lock.unlock();
}