OpenThread中的condition和barrier

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();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值