Source code of Windows XP (NT5)
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.
|
|
/*++
Copyright (c) 1994 Microsoft Corporation All rights reserved.
Module Name:
sleepn.cxx
Abstract:
Handles delayed callbacks. Delay must be < 49.7 days, and the callback must execute very quickly.
Author:
Albert Ting (AlbertT) 19-Dec-1994
Revision History:
--*/
#include "spllibp.hxx"
#pragma hdrstop
TSleepNotify:: TSleepNotify( VOID ) /*++
Routine Description:
Single thread that servers as a timer.
Arguments:
Return Value:
Notes:
_hEvent is our validity variable.
--*/ { _hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if( !_hEvent ){ return; } }
#if 0
TSleepNotify:: ~TSleepNotify( VOID )
/*++
Routine Description:
Destroys the SleepNotify. This should never be called since we never should destruct the object.
Arguments:
Return Value:
--*/
{ if( _hEvent ){ CloseHandle( _hEvent ); } } #endif
VOID TSleepNotify:: vRun( VOID )
/*++
Routine Description:
Main worker loop for callbacks. We will wait on an object to pickup new notifications, and when we time out, do the callback.
Arguments:
VOID
Return Value:
VOID: never returns.
--*/
{ DWORD dwTimeout; DWORD dwResult; VSleepWorker* pSleepWorker;
TCritSecLock CSL( _CritSec );
while( TRUE ){
pSleepWorker = SleepWorker_pHead();
dwTimeout = pSleepWorker ? pSleepWorker->TickCountWake - GetTickCount() : INFINITE;
{ TCritSecUnlock CSU( _CritSec ); dwResult = WaitForSingleObject( _hEvent, dwTimeout ); }
if( dwResult == WAIT_TIMEOUT ){
//
// We added a new item, so go back to sleep with the
// new timeout value.
//
continue; }
//
// Traverse linked list for all items that must be callbacked.
//
PDLINK pdlink; TICKCOUNT TickCountNow = GetTickCount();
for( pdlink = SleepWorker_pdlHead(); SleepWorker_bValid( pdlink ); ){
pSleepWorker = SleepWorker_pConvert( pdlink ); pdlink = SleepWorker_pdlNext( pdlink );
if( pSleepWorker->TickCountWake - TickCountNow < kTickCountMargin ){
//
// We should wake up this guy now.
// There is a 1 hr margin since these call backs to
// take time to execute, and we may miss one of them.
//
pSleepWorker->vCallback();
//
// Remove current item from linked list.
//
pSleepWorker->SleepWorker_vDelinkSelf();
} else {
//
// This item still needs to sleep a little longer.
// Since they are ordered by sleep time, we can
// stop now.
//
break; } } } }
VOID TSleepNotify:: vAdd( VSleepWorker& SleepWorkerAdd, TICKCOUNT TickCountWake )
/*++
Routine Description:
Insert a SleepWorker into the list of items sleeping based on when it wants to wake. The shortest sleepers are first on the list.
Arguments:
SleepWorkerAdd -- Item that wants to sleep a while.
TickCountWake -- Tick count that we want to wake at.
Return Value:
--*/
{ TCritSecLock CSL( _CritSec );
//
// Traverse until we see someone that wants to sleep more than us.
//
PDLINK pdlink; VSleepWorker* pSleepWorker; TICKCOUNT TickCountNow = GetTickCount(); TICKCOUNT TickCountSleep = TickCountWake - TickCountNow;
for( pdlink = SleepWorker_pdlHead(); SleepWorker_bValid( pdlink ); pdlink = SleepWorker_pdlNext( pdlink ) ){
pSleepWorker = SleepWorker_pConvert( pdlink );
//
// If the amount this item wants to sleep is greater than
// the amount we want to sleep, then insert item here.
//
if( pSleepWorker->TickCountWake - TickCountNow > TickCountSleep ){
SleepWorker_vInsertBefore( pdlink, &SleepWorkerAdd ); return; } }
//
// No items or last item.
// Add to end of list.
//
SleepWorker_vAppend( &SleepWorkerAdd ); }
|