windows-nt/Source/XPSP1/NT/net/rras/ip/sample/utils.c
2020-09-26 16:20:57 +08:00

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));
}