Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

145 lines
5.8 KiB

/* link.h, /atalk-ii/ins, Garth Conboy, 10/12/92 */
/* Copyright (c) 1992 by Pacer Software Inc., La Jolla, CA */
/* GC - Initial coding.
Manage the linking/unlinking of reference counted nodes within
linked lists.
*/
/* Link to a node: bump the reference count, and return the linked node. This
macro should be invoked from within a CriticalSection(). RefCount must be
the first field name is an structures managed by this package:
struct tag { int refCount;
...
} *Node;
*/
typedef struct {int refCount;} *GenericNode;
/* The Link macro does not do its own lock handling (see "lock.h") so it
must be invoked with an appropriate lock held or from within a critical
section. Locking is not required if "+= 1" is an atomic operation in
the target environment. */
#if IamNot a Primos
#define Link(p) (((p) is Empty) ? Empty : ((p)->refCount += 1, (p)))
#else
/* For debugging/testing link code, check for too many links. The funny
"(p)->refCount" is to ensure a compilation error if we try this on
a node that doesn't have a refernece count. */
#define TooManyLinks 30
#define Link(p) ((p)->refCount, LinkNode(p))
extern void far *LinkNode(void far *node);
#endif
/* Unlink a node: decrement the reference count, free the node if we're
the last referant. Return True if we really freed the beast. This
routine does its own lock handling, so it must not be invoked with
a lock held or from within a critical section. */
extern Boolean far Unlink(void far *node, LockType lock);
/* The following is an alternate version of Unlink -- it expects to be called
with a lock held (or within a critical section) -- it will decrement the
reference count, and return True if the node should be freed (it will not
actuall perform the free). */
extern Boolean far UnlinkNoFree(void far *node);
/* Find a node on a list: search a linked list for an entry, if found return
a Link to the node. A sample call would be:
p = FindOnList(connectionEndLocalHashBuckets[index],
myConnectionId, connectionId, nextByLocalInfo,
AdspLock);
"connectionEndLocalHashBuckets[index]" is the head of the list to walk.
"myConnectionId" is the value in the node that we're looking for.
"connectionId" is the field name within the node to look for the value.
"nextByLocalInfo" is the field name within the node that we should use
as the "next link."
"AdspLock" is the lock to grab durring the operation.
A simpler example would be:
p = FindOnList(connectionListenerList, refNum,
connectionListenerRefNum, next, AdspLock);
The routine FindNodeOnList() really implements this macro. It's called
as follows:
p = FindNodeOnList(head, value, valueSize, field,
fieldSize, next, lock);
"head" is the head of the list to walk.
"value" is the value in the node that we're looking for.
"valueSize" is the size (in bytes) of value we're looking for; used
only to verify a match with "fieldSize."
"field" is the address of the target field (the one that should contain
"value") within the "head" node ("field - head" will yield
the offset of this field within all nodes).
"fieldSize" is the size (in bytes) of the field.
"next" is the address of the "next" field (the one to walk) within the
"head" node ("next - head" will yield the offset of this field
within all nodes).
"lock" is the lock type to use.
This routine handles its own locking so it must not be called while
a lock is held or from within a CriticalSection().
*/
#define FindOnList(head, value, field, next, lock) \
(((head) is Empty) ? Empty : \
FindNodeOnList(head, &(value), sizeof(value), \
&((head)->field), sizeof((head)->field), \
&((head)->next), lock))
extern void *FindNodeOnList(void *head, void *value, long valueSize,
void *field, long fieldSize, void *next,
LockType lock);
/* Remove a node from a list: find a given node of a linked list, remove it
from the next chain, return the removed node (probably as passed in),
Unlink() the node, return Empty is the node is not on the list. An example
would be:
p = RemoveFromList(connectionListenerList,
currentListenerInfo, next, AdspLock);
The routine RemoveNodeFromList() really implements this macro. It's called
as follows:
p = RemoveNodeFromList(head, node, nextOffset, lock);
"head" is the address of the head of the list to walk.
"node" is the node to remove.
"next" is the address of the "next" field (the one to walk) within the
"head" node ("next - *head" will yield the offset of this field
within all nodes).
"lock" to take during the operation.
This routine handles its own locking so it must not be called while
a lock is held or from within a CriticalSection().
*/
#define RemoveFromList(head, node, next, lock) \
(((head) is Empty) ? Empty : \
RemoveNodeFromList(&(head), node, &((head)->next), lock))
extern void *RemoveNodeFromList(void **head, void *node,
void *next, LockType lock);
/* This version does not Unlink and does not use locks (it's up to the
caller). */
#define RemoveFromListNoUnlink(head, node, next) \
(((head) is Empty) ? Empty : \
RemoveNodeFromListNoUnlink(&(head), node, &((head)->next)))
extern void *RemoveNodeFromListNoUnlink(void **head, void *node, void *next);