211 lines
5.1 KiB
C
211 lines
5.1 KiB
C
|
/****************************** Module Header ******************************\
|
||
|
* Module Name: DMGQ.C
|
||
|
*
|
||
|
* DDE Manager queue control functions.
|
||
|
*
|
||
|
* Created: 9/1/89 Sanford Staab
|
||
|
* Modified:5/31/90 Rich Gartland, Aldus (Windows 3.0 port)
|
||
|
*
|
||
|
* This is a general queue manager - yes another one!
|
||
|
* Queues are each allocated within their own segment and have a
|
||
|
* QST structure associated with that heap. Each queue item
|
||
|
* is allocated within the heap segment. The offset of the items
|
||
|
* address combined with an instance count is used as the item ID.
|
||
|
* This is both unique and allows for instant location of an item.
|
||
|
* New items are added to the head of the queue which is a doubly linked
|
||
|
* list. The next links point to more recent entries, the prev pointers
|
||
|
* to older entries. The next of the head is the tail. The prev of the
|
||
|
* tail is the head. All pointers are far.
|
||
|
* Queue Data may be of any structure type that begins identical to
|
||
|
* a QUEUEITEM structure. Functions that require an cbItem perameter
|
||
|
* should be given the size of the specialized queue item structure.
|
||
|
*
|
||
|
* Copyright (c) 1988, 1989 Microsoft Corporation
|
||
|
\***************************************************************************/
|
||
|
|
||
|
#include "ddemlp.h"
|
||
|
|
||
|
|
||
|
/***************************** Private Function ****************************\
|
||
|
*
|
||
|
* Creates a Queue for items of cbItem.
|
||
|
* Returns NULL on error.
|
||
|
*
|
||
|
*
|
||
|
* History:
|
||
|
* Created 9/1/89 Sanfords
|
||
|
\***************************************************************************/
|
||
|
PQST CreateQ(cbItem)
|
||
|
WORD cbItem;
|
||
|
{
|
||
|
QST cq;
|
||
|
PQST pQ;
|
||
|
|
||
|
cq.cItems = 0;
|
||
|
cq.instLast = 0;
|
||
|
cq.cbItem = cbItem;
|
||
|
cq.pqiHead = NULL;
|
||
|
if (!(cq.hheap = DmgCreateHeap(sizeof(QST) + cbItem << 3)))
|
||
|
return(NULL);
|
||
|
if (!(pQ = (PQST)FarAllocMem(cq.hheap, sizeof(QST)))) {
|
||
|
DmgDestroyHeap(cq.hheap);
|
||
|
return(0);
|
||
|
}
|
||
|
*pQ = cq;
|
||
|
return(pQ);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***************************** Private Function ****************************\
|
||
|
*
|
||
|
*
|
||
|
* History:
|
||
|
* Created 9/1/89 Sanfords
|
||
|
\***************************************************************************/
|
||
|
BOOL DestroyQ(pQ)
|
||
|
PQST pQ;
|
||
|
{
|
||
|
if (pQ)
|
||
|
DmgDestroyHeap(pQ->hheap);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/***************************** Private Function ****************************\
|
||
|
*
|
||
|
* returns a long pointer to the queue item data created. The new item
|
||
|
* is added to the head of the queue. The queue's cbItem specified at
|
||
|
* creation is used for allocation.
|
||
|
*
|
||
|
*
|
||
|
* History:
|
||
|
* Created 9/1/89 Sanfords
|
||
|
\***************************************************************************/
|
||
|
PQUEUEITEM Addqi(pQ)
|
||
|
PQST pQ;
|
||
|
{
|
||
|
PQUEUEITEM pqi;
|
||
|
|
||
|
if ((pqi = (PQUEUEITEM)FarAllocMem(pQ->hheap, pQ->cbItem)) == NULL) {
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
SEMENTER();
|
||
|
if (pQ->cItems == 0) {
|
||
|
pQ->pqiHead = pqi->prev = pqi->next = pqi;
|
||
|
} else {
|
||
|
pqi->prev = pQ->pqiHead;
|
||
|
pqi->next = pQ->pqiHead->next;
|
||
|
pQ->pqiHead->next->prev = pqi;
|
||
|
pQ->pqiHead->next = pqi;
|
||
|
pQ->pqiHead = pqi;
|
||
|
}
|
||
|
SEMLEAVE();
|
||
|
pQ->cItems++;
|
||
|
pqi->inst = ++pQ->instLast;
|
||
|
return(pqi);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************** Private Function ****************************\
|
||
|
*
|
||
|
* The id given is an external LONG id, not an item instance number.
|
||
|
* If id is QID_NEWEST, the head item is deleted.
|
||
|
* If id is QID_OLDEST, the tail item is deleted.
|
||
|
*
|
||
|
*
|
||
|
* History:
|
||
|
* Created 9/1/89 Sanfords
|
||
|
\***************************************************************************/
|
||
|
void Deleteqi(pQ, id)
|
||
|
PQST pQ;
|
||
|
DWORD id;
|
||
|
{
|
||
|
PQUEUEITEM pqi;
|
||
|
|
||
|
SEMENTER();
|
||
|
pqi = Findqi(pQ, id);
|
||
|
if (pqi == NULL) {
|
||
|
SEMLEAVE();
|
||
|
return;
|
||
|
}
|
||
|
pqi->prev->next = pqi->next;
|
||
|
pqi->next->prev = pqi->prev;
|
||
|
if (pqi == pQ->pqiHead)
|
||
|
pQ->pqiHead = pqi->prev;
|
||
|
if (!(--pQ->cItems))
|
||
|
pQ->pqiHead = NULL;
|
||
|
FarFreeMem((LPSTR)pqi);
|
||
|
SEMLEAVE();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/***************************** Private Function ****************************\
|
||
|
*
|
||
|
* The id given is an external LONG id, not an item instance number.
|
||
|
*
|
||
|
* if id == QID_NEWEST, returns the head queue data item.
|
||
|
* if id == QID_OLDEST == 0L, returns the tail queue data item.
|
||
|
* if the id is not found or the queue is empty, NULL is returned.
|
||
|
* if found, pqi is returned.
|
||
|
*
|
||
|
*
|
||
|
* History:
|
||
|
* Created 9/1/89 Sanfords
|
||
|
\***************************************************************************/
|
||
|
PQUEUEITEM Findqi(pQ, id)
|
||
|
PQST pQ;
|
||
|
DWORD id;
|
||
|
{
|
||
|
PQUEUEITEM pqi;
|
||
|
|
||
|
SEMCHECKIN();
|
||
|
if (pQ == NULL || pQ->pqiHead == NULL)
|
||
|
return(NULL);
|
||
|
|
||
|
if (id == QID_OLDEST)
|
||
|
return(pQ->pqiHead->next);
|
||
|
|
||
|
if (id == QID_NEWEST)
|
||
|
return(pQ->pqiHead);
|
||
|
|
||
|
if (id) {
|
||
|
pqi = PFROMID(pQ, id);
|
||
|
if (pqi->inst == HIWORD(id)) {
|
||
|
return(pqi);
|
||
|
}
|
||
|
return(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* useful for traversing queues and deleting particular stuff in them.
|
||
|
*/
|
||
|
PQUEUEITEM FindNextQi(
|
||
|
PQST pQ,
|
||
|
PQUEUEITEM pqi,
|
||
|
BOOL fDelete)
|
||
|
{
|
||
|
PQUEUEITEM pqiNext;
|
||
|
|
||
|
if (pqi == NULL) {
|
||
|
return(pQ->cItems ? pQ->pqiHead : NULL);
|
||
|
}
|
||
|
|
||
|
pqiNext = pqi->next;
|
||
|
if (fDelete) {
|
||
|
Deleteqi(pQ, MAKEID(pqi));
|
||
|
}
|
||
|
return(pqiNext != pQ->pqiHead && pQ->cItems ? pqiNext : NULL);
|
||
|
}
|
||
|
|