You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
5.2 KiB
135 lines
5.2 KiB
|
|
// Ruler
|
|
// 1 2 3 4 5 6 7 8
|
|
//345678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* The standard layout. */
|
|
/* */
|
|
/* The standard layout for 'cpp' files in this code is as */
|
|
/* follows: */
|
|
/* */
|
|
/* 1. Include files. */
|
|
/* 2. Constants local to the class. */
|
|
/* 3. Data structures local to the class. */
|
|
/* 4. Data initializations. */
|
|
/* 5. Static functions. */
|
|
/* 6. Class functions. */
|
|
/* */
|
|
/* The constructor is typically the first function, class */
|
|
/* member functions appear in alphabetical order with the */
|
|
/* destructor appearing at the end of the file. Any section */
|
|
/* or function this is not required is simply omitted. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
#include "LibraryPCH.hpp"
|
|
|
|
#include "Barrier.hpp"
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class constructor. */
|
|
/* */
|
|
/* Create a new barrier and initialize it. This call is not */
|
|
/* thread safe and should only be made in a single thread */
|
|
/* environment. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
BARRIER::BARRIER( VOID )
|
|
{
|
|
Waiting = 0;
|
|
|
|
if ( (Semaphore = CreateSemaphore( NULL,0,MaxCpus,NULL )) == NULL)
|
|
{ Failure( "Create semaphore in constructor for BARRIER" ); }
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Synchronize Threads. */
|
|
/* */
|
|
/* Synchronize a collection of threads. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
VOID BARRIER::Synchronize( SBIT32 Expecting )
|
|
{
|
|
//
|
|
// We make sure we are expecting at least two threads.
|
|
// If not then do nothing.
|
|
//
|
|
if ( Expecting > 1 )
|
|
{
|
|
//
|
|
// Cliam the lock.
|
|
//
|
|
Spinlock.ClaimLock();
|
|
|
|
//
|
|
// We see if the required number of threads has
|
|
// arrived.
|
|
//
|
|
if ( Expecting > (++ Waiting) )
|
|
{
|
|
//
|
|
// We are about to sleep so drop the lock.
|
|
//
|
|
Spinlock.ReleaseLock();
|
|
|
|
//
|
|
// The threads sleep here waiting for everyone
|
|
// else to arrive.
|
|
//
|
|
if
|
|
(
|
|
WaitForSingleObject( Semaphore,INFINITE )
|
|
!=
|
|
WAIT_OBJECT_0
|
|
)
|
|
{ Failure( "Sleep failed in Synchronize()" ); }
|
|
}
|
|
else
|
|
{
|
|
REGISTER SBIT32 Wakeup = (Expecting-1);
|
|
|
|
//
|
|
// The count of threads that have arrived is
|
|
// updated and the number of threads that are
|
|
// about to leave is updated.
|
|
//
|
|
Waiting -= Expecting;
|
|
|
|
//
|
|
// We are about to wake up all the sleepers so
|
|
// drop the lock.
|
|
//
|
|
Spinlock.ReleaseLock();
|
|
|
|
//
|
|
// Wakeup any sleeping threads and exit.
|
|
//
|
|
if ( Wakeup > 0 )
|
|
{
|
|
if ( ! ReleaseSemaphore( Semaphore,Wakeup,NULL ) )
|
|
{ Failure( "Wakeup failed in Synchronize()" ); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* */
|
|
/* Class destructor. */
|
|
/* */
|
|
/* Destory a barrier. This call is not thread safe and should */
|
|
/* only be made in a single thread environment. */
|
|
/* */
|
|
/********************************************************************/
|
|
|
|
BARRIER::~BARRIER( VOID )
|
|
{
|
|
if ( ! CloseHandle( Semaphore ) )
|
|
{ Failure( "Close semaphore in destructor for BARRIER" ); }
|
|
}
|