home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d169
/
src
/
dres
/
notinlib
/
graph.c
next >
Wrap
Text File
|
1988-11-22
|
6KB
|
256 lines
/*
* GRAPH.C
*/
#define GRAPH struct _GRAPH
#define GNODE struct _GNODE
#define GCTRL struct _GCTRL
/*
* Flags field: The upper 4 bits are copied to the lower 4 bits after
* the flags are processed, allowing for 'temporary'
* conditions.
*
* FL_SKIP Propogate a skip condition. As soon as the next node
* is ready to begin processing, cause it not to run
* its function and propogate the FL_SKIP to all of its
* children, and all of their children, etc...
*
* FL_SRC Infinite source, this arc is always ready with the
* given value.
*/
GLINK {
MINNODE FNode; /* link from, list based at node */
MINNODE TNode; /* link to, list based at node */
GNODE *FGNode; /* from this node */
GNODE *TGNode; /* to this node */
long FromId; /* Identify value slot for source */
long ToId; /* Identify value slot for destination */
long Value; /* value to pass to 'to' node */
ubyte Ready; /* value pending, else no value pending*/
ubyte Flags; /* FL_SKIP,FL_NULL,FL_SRC */
ubyte XFlags; /* XL_READ */
ubyte filler;
};
GNODE {
MINNODE GNode; /* master list node */
GRAPH *Graph; /* owning graph */
APTR Func; /* Function */
long Arg; /* Argument */
short WaitCnt; /* # parents who are not ready */
MINLIST ChildList; /* list of children */
MINLIST ParentList; /* list of parents */
MINLIST WakeUpList; /* WakeUp tasks waiting for an ARC to clear */
};
GRAPH {
MINLIST GNodes; /* list of all graphs in node */
long A45[2]; /* global base registers */
long UsrLen;
};
GRAPH *
AllocGraph(usrdatalen)
{
GRAPH *graph = AllocMem(sizeof(GRAPH), MEMF_PUBLIC|MEMF_CLEAR);
NewList(&graph->GNodes);
graph->a45[0] = A4;
graph->a45[1] = A5;
graph->UsrLen = usrdatalen;
}
GNODE *
AllocGraphNode(graph, func, arg, usrdata/NULL)
GRAPH *graph;
long arg;
{
GNODE *gnode = AllocMem(sizeof(GNODE), MEMF_PUBLIC|MEMF_CLEAR);
AddTail(&graph->GNodes, &gnode->GNode);
gnode->Graph = graph;
gnode->Func = func;
gnode->Arg = arg;
NewList(&gnode->ChildList);
NewList(&gnode->ParentList);
NewList(&gnode->WakeUpList);
}
/*
* Remove all arcs and free a graph node
*/
FreeGraphNode(gnode)
GNODE *gnode;
{
Forbid();
Remove(gnode);
while (glink = GetHead(&gnode->ChildList))
RemGraphArc(gnode, glink->FGTNode);
while (glink = GetHeadOff(&gnode->ParentList, 8))
RemGraphArc(glink->FGFNode, gnode);
Permit();
FreeMem(gnode, sizeof(GNODE));
};
FreeGraph(graph)
GRAPH *graph;
{
Forbid();
while (gnode = GetHead(&graph->GNodes))
FreeGraphNode(gnode);
Permit();
FreeMem(graph, sizeof(GRAPH));
}
/*
* Set the user data for a given node. The data is copied into an
* equivalent buffer for the node.
*/
SetUserData(gnode, usrdata/NULL)
GNODE *gnode;
{
}
/*
* Add a directed arc to the graph. Set the arc to 'not ready' and
* increment the child node's WaitCnt
*/
AddGraphArc(from, to)
GNODE *from, *to;
{
GLINK *glink = AllocMem(sizeof(GLINK), MEMF_PUBLIC);
Forbid();
AddTail(&from->ChildList, &glink->FNode);
AddTail(&to->ParentList, &glink->TNode);
glink->FGNode = from;
glink->FTNode = to;
++to->WaitCnt;
Permit();
}
chklink(glink, gnode)
GLINK *glink;
GNODE *gnode;
{
if (glink->TGNode == gnode)
return(glink);
return(NULL);
}
RemGraphArc(from, to)
GNODE *from, *to;
{
GLINK *glink;
Forbid();
if (glink = SearchFwdNode(GetHead(&from->ChildList), chklink, 0, to)) {
Remove(&glink->FNode);
Remove(&glink->TNode);
if (!glink->Ready) {
if (--to->WaitCnt == 0 && GetHeadOff(&to->ParentList, 8))
GHandler(to);
}
}
Permit();
}
SetGNodeFunc(gnode, func)
GNODE *gnode;
APTR func;
{
gnode->Func = func;
}
SetGNodeArg(gnode, arg)
GNODE *gnode;
{
gnode->Arg = arg;
}
APTR
GetGNodeFunc(gnode)
GNODE *gnode;
{
return(gnode->Func);
}
long
GetGNodeArg(gnode)
GNODE *gnode;
{
return(gnode->Arg);
}
/*
* This function may ONLY be called by a node function, and retrieves
* the value from one of the parent arcs (arcs comming in). When the
* node function returns, any remaining unread parent arc's values will
* be discarded.
*/
long
GetArcValue(ToId)
{
}
/*
* This function may ONLY be called by a node function, and sets the
* result value to one of its child arcs (arcs going out). When the
* node function returns, any remaining unset child arc's values will
* be SKIPd.
*
* NOTE! This function will block on child nodes which have yet to
* read the previous value with GetArcValue() or are still running.
*/
SetArcValue(gnode, FromId, flags)
GNODE *gnode;
{
}
/*
* This function may be called by anybody, and forces a value into an
* arc. This function is usually used to 'prime' a graph.
*/
PrimeArc(from, to, value)
GNODE *from, *to;
{
}
/*
* GetGraph()
*
* Load the two buffers with entries corrosponding to the graph. arcen
* and nodeen initially contain the number of ARC and NODE structure
* entries that have been allocated. These variables will hold the
* actual number of ARC and NODE entries in the graph regardless of
* whether the operation succeeds.
*
* 0 is returned if the operation does not succeed, 1 if it does.
* The size of the node structure depends on the size of attached
* user information.
*
* ARC structure: two words / entry, representing an arc (from, to),
* where each word is an index (by entry #) into nodebuf.
* i.e. 0, 1, 2 ... even if usrdatalen is 0.
*
* NODE structure: any user data that has been applied to the node, as
* specified by AllocGraphNode().
*/
GetArcs(graph, arcbuf, &arcen, nodebuf, &nodeen)
GRAPH *graph;
{
}