Leaked source code of windows server 2003
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.
 
 
 
 
 
 

273 lines
8.3 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996.
//
// File: workq.cxx
//
// Contents: Definitions of CWorkQueue methods
//
// Classes:
//
// Functions: Constructor, destructor, AddItem, GetNextItem, Done
//
// Coupling:
//
// Notes: For use in uni- or multi-threaded applications
//
// History: 9-30-1996 ericne Created
//
//----------------------------------------------------------------------------
#include "workq.hxx"
//+---------------------------------------------------------------------------
//
// Member: ::CWorkQueue
//
// Synopsis: Initializes members
//
// Arguments: (none)
//
// Returns:
//
// History: 9-30-1996 ericne Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, int I>
CWorkQueue<T,I>::CWorkQueue()
: m_iAddItemIndex( 0 ),
m_iGetItemIndex( 0 ),
m_hSemFull( NULL ),
m_hSemEmpty( NULL ),
m_hEventDone( NULL )
{
InitializeCriticalSection( &m_CriticalSection );
// Create a semaphore with an initial count of 0. Each time
// GetItem is called, this value is decrimented. Each time
// AddItem is called, this value is incremented.
while( 1 )
{
m_hSemFull = CreateSemaphore( NULL, // No security attributes
0, // Initial value of 0
I, // Maximum value of I
NULL ); // No name
if( NULL != m_hSemFull )
break;
printf( "CreateSemaphore failed. Will try again in %d milliseconds.\r\n"
"GetLastError() returned 0x%08x\r\n",
dwSleepTime, GetLastError() );
Sleep( dwSleepTime );
}
// Create a semaphore with an initial count of I. Each time
// AddItem is called, this value is decrimented. Each time
// GetItem is called, this value is incremented.
while( 1 )
{
m_hSemEmpty = CreateSemaphore( NULL, // No security attributes
I, // Initial value of I
I, // Maximum value of I
NULL ); // No name
if( NULL != m_hSemEmpty )
break;
printf( "CreateSemaphore failed. Will try again in %d milliseconds.\r\n"
"GetLastError() returned 0x%08x\r\n",
dwSleepTime, GetLastError() );
Sleep( dwSleepTime );
}
// This event is used by a producer thread to signal the consumer threads
// that no additional work items will be placed in the queue
while( 1 )
{
m_hEventDone = CreateEvent( NULL, // No security attributes
TRUE, // Manual reset
FALSE, // Initial state of non-signaled
NULL ); // No name
if( NULL != m_hEventDone )
break;
printf( "CreateEvent failed. Will try again in %d milliseconds.\r\n"
"GetLastError() returned 0x%08x\r\n",
dwSleepTime, GetLastError() );
Sleep( dwSleepTime );
}
} //::CWorkQueue
//+---------------------------------------------------------------------------
//
// Member: ::~CWorkQueue
//
// Synopsis: Closes the handles to the semaphores
//
// Arguments: (none)
//
// Returns:
//
// History: 9-30-1996 ericne Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, int I>
CWorkQueue<T,I>::~CWorkQueue()
{
if( ! CloseHandle( m_hSemFull ) )
printf( "~CWorkQueue(): Could not close handle to semaphore."
"GetLastError() returns 0x%08x", GetLastError() );
if( ! CloseHandle( m_hSemEmpty ) )
printf( "~CWorkQueue(): Could not close handle to semaphore."
"GetLastError() returns 0x%08x", GetLastError() );
if( ! CloseHandle( m_hEventDone ) )
printf( "~CWorkQueue(): Could not close handle to event."
"GetLastError() returns 0x%08x", GetLastError() );
DeleteCriticalSection( &m_CriticalSection );
} //::~CWorkQueue
//+---------------------------------------------------------------------------
//
// Member: ::AddItem
//
// Synopsis: Adds an item to the queue
//
// Arguments: [ToAdd] -- The item to add
//
// Returns: none
//
// History: 9-30-1996 ericne Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, int I>
void CWorkQueue<T,I>::AddItem( const T &ToAdd )
{
// Wait until m_hSemEmpty is greater than zero, then decriment
if( WAIT_OBJECT_0 != WaitForSingleObject( m_hSemEmpty, INFINITE ) )
printf( "CWorkQueue::AddItem() : Wait for semaphore failed.\r\n"
"GetLastError() returns 0x%08x\r\n", GetLastError() );
// enter the critical section
EnterCriticalSection( &m_CriticalSection );
// Bit-wise copy the structure
memcpy( (void*)&m_WorkItems[m_iAddItemIndex], (void*)&ToAdd, sizeof( T ) );
// Increment the index
m_iAddItemIndex = ( m_iAddItemIndex + 1 ) % I;
// Leave the critical section
LeaveCriticalSection( &m_CriticalSection );
// Incriment m_hSemFull
if( ! ReleaseSemaphore( m_hSemFull, 1, NULL ) )
printf( "CWorkQueue::AddItem() : Could not release semaphore.\r\n"
"GetLastError() returns 0x%08x\r\n", GetLastError() );
} //::AddItem
//+---------------------------------------------------------------------------
//
// Member: ::Done
//
// Synopsis: Called by a producer thread when it is finished adding stuff
// to the queue
//
// Arguments: (none)
//
// Returns: void
//
// History: 10-01-1996 ericne Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, int I>
void CWorkQueue<T,I>::Done( )
{
// Since this is a manual-reset event, m_hEventDone stays signaled forever.
SetEvent( m_hEventDone );
} //::Done
//+---------------------------------------------------------------------------
//
// Member: ::GetItem
//
// Synopsis: Gets the next work item from the queue.
//
// Arguments: [NextItem] -- Passed by reference. Item is filled in by
// the function
//
// Returns: TRUE if an item was gotten from the queue
// FALSE if queue is empty and m_hEventDone is signaled
//
// History: 9-30-1996 ericne Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, int I>
BOOL CWorkQueue<T,I>::GetItem( T &NextItem )
{
DWORD dwWait = 0;
HANDLE pHandles[2] = { m_hSemFull, m_hEventDone };
// wait until m_hSemFull is > 0 or until m_hEventDone is set
dwWait = WaitForMultipleObjects( 2, pHandles, FALSE, INFINITE );
if( WAIT_OBJECT_0 == dwWait )
{
// There are more work items in the list
// ( done event may or may not be set )
EnterCriticalSection( &m_CriticalSection );
memcpy( (void*) &NextItem,
(void*) &m_WorkItems[m_iGetItemIndex],
sizeof( T ) );
m_iGetItemIndex = ( m_iGetItemIndex + 1 ) % I;
LeaveCriticalSection( &m_CriticalSection );
if( ! ReleaseSemaphore( m_hSemEmpty, 1, NULL ) )
printf( "CWorkQueue::GetItem() : Could not release semaphore.\r\n"
"GetLastError() returns 0x%08x\r\n", GetLastError() );
return( TRUE );
}
else if( WAIT_OBJECT_0 + 1 == dwWait )
{
// Nothing more in list and done event has been set
}
else
{
// An error occured
printf( "CWorkQueue::GetItem() : Wait failed.\r\n"
"GetLastError() returns 0x%08x\r\n", GetLastError() );
}
return( FALSE );
} //::GetItem