Files
OpenSceneGraph/src/OpenThreads/win32/Win32ThreadBarrier.cpp
Robert Osfield 323ce02f23 Moved OpenThreads directly into OpenSceneGraph/trunk rather than being introduced via svn:externals.
This change has been done to make it easier for OpenSceneGraph users to check out the svn via https 
without any conflicts introduced with a http externals.
2008-04-01 10:49:53 +00:00

150 lines
3.9 KiB
C++

/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
//
// Win32Barrier.c++ - C++ Barrier class built on top of POSIX threads.
// ~~~~~~~~~~~~~~~~~~
//
#include <OpenThreads/Barrier>
#include <OpenThreads/Thread>
#include <OpenThreads/ScopedLock>
#include "Win32BarrierPrivateData.h"
using namespace OpenThreads;
// so compiler can place it somewhere
Win32BarrierPrivateData::~Win32BarrierPrivateData()
{
};
//----------------------------------------------------------------------------
//
// Description: Constructor
//
// Use: public.
//
Barrier::Barrier(int numThreads) {
Win32BarrierPrivateData *pd = new Win32BarrierPrivateData();
pd->cnt = 0;
pd->phase = 0;
pd->maxcnt = numThreads;
_valid = true;
_prvData = static_cast<void *>(pd);
}
//----------------------------------------------------------------------------
//
// Description: Destructor
//
// Use: public.
//
Barrier::~Barrier() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
delete pd;
}
//----------------------------------------------------------------------------
//
// Description: Reset the barrier to its original state
//
// Use: public.
//
void Barrier::reset() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
pd->cnt = 0;
pd->phase = 0;
}
//----------------------------------------------------------------------------
//
// Description: 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;
ScopedLock<Mutex> lock(pd->lock);
if( _valid )
{
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);
}
}
}
}
void Barrier::invalidate()
{
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
pd->lock.lock();
_valid = false;
pd->lock.unlock();
release();
}
//----------------------------------------------------------------------------
//
// Description: Release the barrier, now.
//
// Use: public.
//
void Barrier::release() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
int my_phase;
ScopedLock<Mutex> lock(pd->lock);
my_phase = pd->phase;
pd->cnt = 0; // reset for next use
pd->phase = 1 - my_phase; // toggle phase
pd->cond.broadcast();
}
//----------------------------------------------------------------------------
//
// Description: Return the number of threads currently blocked in the barrier
//
// Use: public
//
int Barrier::numThreadsCurrentlyBlocked() {
Win32BarrierPrivateData *pd =
static_cast<Win32BarrierPrivateData*>(_prvData);
int numBlocked = -1;
ScopedLock<Mutex> lock(pd->lock);
numBlocked = pd->cnt;
return numBlocked;
}