OpenThread中的condition和barrier

condition应用

condition源码
#ifndef _WIN32CONDITIONPRIVATEDATA_H_
#define _WIN32CONDITIONPRIVATEDATA_H_

#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include 
#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  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 
#include 
#include 
#include 
#include 
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 = "<= 10)
			{
				g_condition.signal();
				cout<<"A: signal"<


 
   
barrier为condition和mutex的应用,让线程可以同步等待运行
 
barrier源码
#ifndef _Win32BARRIERPRIVATEDATA_H_
#define _Win32BARRIERPRIVATEDATA_H_

#ifndef _WINDOWS_
#define WIN32_LEAN_AND_MEAN
#include 
#endif

#include 
#include 

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  
#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(pd);
}
//----------------------------------------------------------------------------
//
// Decription: Destructor
//
// Use: public.
//
Barrier::~Barrier() {
    Win32BarrierPrivateData *pd =
        static_cast(_prvData);
    delete pd;
}
//----------------------------------------------------------------------------
//
// Decription: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset() {
    Win32BarrierPrivateData *pd =
        static_cast(_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(_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();
}



你可能感兴趣的:(C++)