windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/callcont/hangman.c
2020-09-26 16:20:57 +08:00

339 lines
7.2 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
*
* $Archive: S:/STURGEON/SRC/CALLCONT/VCS/Hangman.c_v $
*
* INTEL Corporation Prorietary Information
*
* This listing is supplied under the terms of a license agreement
* with INTEL Corporation and may not be copied nor disclosed except
* in accordance with the terms of that agreement.
*
* Copyright (c) 1993-1994 Intel Corporation.
*
* $Revision: 1.16 $
* $Date: 22 Jan 1997 14:55:52 $
* $Author: MANDREWS $
*
* Deliverable:
*
* Abstract:
*
*
* Notes:
*
***************************************************************************/
#include "precomp.h"
#include "apierror.h"
#include "incommon.h"
#include "callcont.h"
#include "q931.h"
#include "ccmain.h"
#include "ccutils.h"
#include "hangman.h"
static BOOL bHangupInited = FALSE;
static struct {
PHANGUP pHead;
LOCK Lock;
} HangupTable;
static struct {
HHANGUP hHangup;
LOCK Lock;
} HangupHandle;
HRESULT InitHangupManager()
{
ASSERT(bHangupInited == FALSE);
HangupTable.pHead = NULL;
InitializeLock(&HangupTable.Lock);
HangupHandle.hHangup = CC_INVALID_HANDLE + 1;
InitializeLock(&HangupHandle.Lock);
bHangupInited = TRUE;
return CC_OK;
}
HRESULT DeInitHangupManager()
{
PHANGUP pHangup;
PHANGUP pNextHangup;
if (bHangupInited == FALSE)
return CC_OK;
pHangup = HangupTable.pHead;
while (pHangup != NULL) {
AcquireLock(&pHangup->Lock);
pNextHangup = pHangup->pNextInTable;
FreeHangup(pHangup);
pHangup = pNextHangup;
}
DeleteLock(&HangupHandle.Lock);
DeleteLock(&HangupTable.Lock);
bHangupInited = FALSE;
return CC_OK;
}
HRESULT _AddHangupToTable( PHANGUP pHangup)
{
ASSERT(pHangup != NULL);
ASSERT(pHangup->hHangup != CC_INVALID_HANDLE);
ASSERT(pHangup->bInTable == FALSE);
AcquireLock(&HangupTable.Lock);
pHangup->pNextInTable = HangupTable.pHead;
pHangup->pPrevInTable = NULL;
if (HangupTable.pHead != NULL)
HangupTable.pHead->pPrevInTable = pHangup;
HangupTable.pHead = pHangup;
pHangup->bInTable = TRUE;
RelinquishLock(&HangupTable.Lock);
return CC_OK;
}
HRESULT _RemoveHangupFromTable( PHANGUP pHangup)
{
HHANGUP hHangup;
BOOL bTimedOut;
ASSERT(pHangup != NULL);
ASSERT(pHangup->bInTable == TRUE);
// Caller must have a lock on the hangup object;
// in order to avoid deadlock, we must:
// 1. unlock the hangup object,
// 2. lock the HangupTable,
// 3. locate the hangup object in the HangupTable (note that
// after step 2, the hangup object may be deleted from the
// HangupTable by another thread),
// 4. lock the hangup object (someone else may have the lock)
// 5. remove the hangup object from the HangupTable,
// 6. unlock the HangupTable
//
// The caller can now safely unlock and destroy the hangup object,
// since no other thread will be able to find the object (its been
// removed from the HangupTable), and therefore no other thread will
// be able to lock it.
// Save the hangup handle; its the only way to look up
// the hangup object in the HangupTable. Note that we
// can't use pHangup to find the hangup object, since
// pHangup may be free'd up, and another hangup object
// allocated at the same address
hHangup = pHangup->hHangup;
// step 1
RelinquishLock(&pHangup->Lock);
step2:
// step 2
AcquireLock(&HangupTable.Lock);
// step 3
pHangup = HangupTable.pHead;
while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
pHangup = pHangup->pNextInTable;
if (pHangup != NULL) {
// step 4
AcquireTimedLock(&pHangup->Lock,10,&bTimedOut);
if (bTimedOut) {
RelinquishLock(&HangupTable.Lock);
Sleep(0);
goto step2;
}
// step 5
if (pHangup->pPrevInTable == NULL)
HangupTable.pHead = pHangup->pNextInTable;
else
pHangup->pPrevInTable->pNextInTable = pHangup->pNextInTable;
if (pHangup->pNextInTable != NULL)
pHangup->pNextInTable->pPrevInTable = pHangup->pPrevInTable;
pHangup->pNextInTable = NULL;
pHangup->pPrevInTable = NULL;
pHangup->bInTable = FALSE;
}
// step 6
RelinquishLock(&HangupTable.Lock);
if (pHangup == NULL)
return CC_BAD_PARAM;
else
return CC_OK;
}
HRESULT _MakeHangupHandle( PHHANGUP phHangup)
{
AcquireLock(&HangupHandle.Lock);
*phHangup = HangupHandle.hHangup++;
RelinquishLock(&HangupHandle.Lock);
return CC_OK;
}
HRESULT AllocAndLockHangup( PHHANGUP phHangup,
CC_HCONFERENCE hConference,
DWORD_PTR dwUserToken,
PPHANGUP ppHangup)
{
HRESULT status;
ASSERT(bHangupInited == TRUE);
// all parameters should have been validated by the caller
ASSERT(phHangup != NULL);
ASSERT(hConference != CC_INVALID_HANDLE);
ASSERT(ppHangup != NULL);
// set phHangup now, in case we encounter an error
*phHangup = CC_INVALID_HANDLE;
*ppHangup = (PHANGUP)MemAlloc(sizeof(HANGUP));
if (*ppHangup == NULL)
return CC_NO_MEMORY;
(*ppHangup)->bInTable = FALSE;
status = _MakeHangupHandle(&(*ppHangup)->hHangup);
if (status != CC_OK) {
MemFree(*ppHangup);
return status;
}
(*ppHangup)->hConference = hConference;
(*ppHangup)->wNumCalls = 0;
(*ppHangup)->dwUserToken = dwUserToken;
(*ppHangup)->pNextInTable = NULL;
(*ppHangup)->pPrevInTable = NULL;
InitializeLock(&(*ppHangup)->Lock);
AcquireLock(&(*ppHangup)->Lock);
*phHangup = (*ppHangup)->hHangup;
// add the Hangup to the Hangup table
status = _AddHangupToTable(*ppHangup);
if (status != CC_OK)
FreeHangup(*ppHangup);
return status;
}
// Caller must have a lock on the Hangup object
HRESULT FreeHangup( PHANGUP pHangup)
{
HHANGUP hHangup;
ASSERT(pHangup != NULL);
// caller must have a lock on the Hangup object,
// so there's no need to re-lock it
hHangup = pHangup->hHangup;
if (pHangup->bInTable == TRUE)
if (_RemoveHangupFromTable(pHangup) == CC_BAD_PARAM)
// the Hangup object was deleted by another thread,
// so just return CC_OK
return CC_OK;
// Since the hangup object has been removed from the HangupTable,
// no other thread will be able to find the hangup object and obtain
// a lock, so its safe to unlock the hangup object and delete it here
RelinquishLock(&pHangup->Lock);
DeleteLock(&pHangup->Lock);
MemFree(pHangup);
return CC_OK;
}
HRESULT LockHangup( HHANGUP hHangup,
PPHANGUP ppHangup)
{
BOOL bTimedOut;
ASSERT(hHangup != CC_INVALID_HANDLE);
ASSERT(ppHangup != NULL);
step1:
AcquireLock(&HangupTable.Lock);
*ppHangup = HangupTable.pHead;
while ((*ppHangup != NULL) && ((*ppHangup)->hHangup != hHangup))
*ppHangup = (*ppHangup)->pNextInTable;
if (*ppHangup != NULL) {
AcquireTimedLock(&(*ppHangup)->Lock,10,&bTimedOut);
if (bTimedOut) {
RelinquishLock(&HangupTable.Lock);
Sleep(0);
goto step1;
}
}
RelinquishLock(&HangupTable.Lock);
if (*ppHangup == NULL)
return CC_BAD_PARAM;
else
return CC_OK;
}
HRESULT ValidateHangup( HHANGUP hHangup)
{
PHANGUP pHangup;
ASSERT(hHangup != CC_INVALID_HANDLE);
AcquireLock(&HangupTable.Lock);
pHangup = HangupTable.pHead;
while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
pHangup = pHangup->pNextInTable;
RelinquishLock(&HangupTable.Lock);
if (pHangup == NULL)
return CC_BAD_PARAM;
else
return CC_OK;
}
HRESULT UnlockHangup( PHANGUP pHangup)
{
ASSERT(pHangup != NULL);
RelinquishLock(&pHangup->Lock);
return CC_OK;
}