206 lines
4.3 KiB
C
206 lines
4.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1999, Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
sample\utils.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
The file contains miscellaneous utilities.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "pchsample.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
DWORD
|
||
|
QueueSampleWorker(
|
||
|
IN WORKERFUNCTION pfnFunction,
|
||
|
IN PVOID pvContext
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called to queue a worker function in a safe fashion;
|
||
|
if cleanup is in progress or if SAMPLE has stopped, this function
|
||
|
discards the work-item.
|
||
|
|
||
|
Locks
|
||
|
Acquires exclusively g_ce.rwlLock
|
||
|
Releases g_ce.rwlLock
|
||
|
|
||
|
Arguments
|
||
|
pfnFunction function to be called
|
||
|
pvContext opaque ptr used in callback
|
||
|
|
||
|
Return Value
|
||
|
NO_ERROR if success
|
||
|
Failure code o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr = NO_ERROR;
|
||
|
BOOL bSuccess = FALSE;
|
||
|
|
||
|
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// cannot queue a work function when SAMPLE has quit or is quitting
|
||
|
if (g_ce.iscStatus != IPSAMPLE_STATUS_RUNNING)
|
||
|
{
|
||
|
dwErr = ERROR_CAN_NOT_COMPLETE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
bSuccess = QueueUserWorkItem((LPTHREAD_START_ROUTINE)pfnFunction,
|
||
|
pvContext,
|
||
|
0); // no flags
|
||
|
if (bSuccess)
|
||
|
g_ce.ulActivityCount++;
|
||
|
else
|
||
|
dwErr = GetLastError();
|
||
|
} while (FALSE);
|
||
|
|
||
|
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
EnterSampleAPI(
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called when entering a SAMPLE api, as well as when
|
||
|
entering the input thread and timer thread. It checks to see if SAMPLE
|
||
|
has stopped, and if so it quits; otherwise it increments the count of
|
||
|
active threads.
|
||
|
|
||
|
Locks
|
||
|
Acquires exclusively g_ce.rwlLock
|
||
|
Releases g_ce.rwlLock
|
||
|
|
||
|
Arguments
|
||
|
None
|
||
|
|
||
|
Return Value
|
||
|
TRUE if entered successfully
|
||
|
FALSE o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
BOOL bEntered = FALSE;
|
||
|
|
||
|
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
if (g_ce.iscStatus is IPSAMPLE_STATUS_RUNNING)
|
||
|
{
|
||
|
// SAMPLE is running, so continue
|
||
|
g_ce.ulActivityCount++;
|
||
|
bEntered = TRUE;
|
||
|
}
|
||
|
|
||
|
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
return bEntered;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
EnterSampleWorker(
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called when entering a SAMPLE worker-function. Since
|
||
|
there is a lapse between the time a worker-function is queued and the
|
||
|
time the function is actually invoked by a worker thread, this function
|
||
|
must check to see if SAMPLE has stopped or is stopping; if this is the
|
||
|
case, then it decrements the activity count, releases the activity
|
||
|
semaphore, and quits.
|
||
|
|
||
|
Locks
|
||
|
Acquires exclusively g_ce.rwlLock
|
||
|
Releases g_ce.rwlLock
|
||
|
|
||
|
Arguments
|
||
|
None
|
||
|
|
||
|
Return Value
|
||
|
TRUE if entered successfully
|
||
|
FALSE o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
BOOL bEntered = FALSE;
|
||
|
|
||
|
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
do // breakout loop
|
||
|
{
|
||
|
// SAMPLE is running, so the function may continue
|
||
|
if (g_ce.iscStatus is IPSAMPLE_STATUS_RUNNING)
|
||
|
{
|
||
|
bEntered = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// SAMPLE is not running, but it was, so the function must stop
|
||
|
if (g_ce.iscStatus is IPSAMPLE_STATUS_STOPPING)
|
||
|
{
|
||
|
g_ce.ulActivityCount--;
|
||
|
ReleaseSemaphore(g_ce.hActivitySemaphore, 1, NULL);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// SAMPLE probably never started. quit
|
||
|
} while (FALSE);
|
||
|
|
||
|
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
return bEntered;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
VOID
|
||
|
LeaveSampleWorker(
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description
|
||
|
This function is called when leaving a SAMPLE api or worker function.
|
||
|
It decrements the activity count, and if it detects that SAMPLE has
|
||
|
stopped or is stopping, it releases the activity semaphore.
|
||
|
|
||
|
Locks
|
||
|
Acquires exclusively g_ce.rwlLock
|
||
|
Releases g_ce.rwlLock
|
||
|
|
||
|
Arguments
|
||
|
None
|
||
|
|
||
|
Return Value
|
||
|
TRUE if entered successfully
|
||
|
FALSE o/w
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ACQUIRE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
|
||
|
g_ce.ulActivityCount--;
|
||
|
|
||
|
if (g_ce.iscStatus is IPSAMPLE_STATUS_STOPPING)
|
||
|
ReleaseSemaphore(g_ce.hActivitySemaphore, 1, NULL);
|
||
|
|
||
|
RELEASE_WRITE_LOCK(&(g_ce.rwlLock));
|
||
|
}
|