qPriDeltaLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:11k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* qPriDeltaLib.c - priority queue with relative priority sorting library */
  2. /* Copyright 1984-1992 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01h,19jul92,pme  made qPriDeltaRemove return STATUS.
  8. 01g,26may92,rrr  the tree shuffle
  9. 01f,19nov91,rrr  shut up some ansi warnings.
  10. 01e,04oct91,rrr  passed through the ansification filter
  11.                   -changed functions to ansi style
  12.   -changed VOID to void
  13.   -changed copyright notice
  14. 01d,28sep90,jcf  documentation.
  15. 01c,05jul90,jcf  added null routine for calibrateRtn field in Q_CLASS.
  16. 01b,26jun90,jcf  fixed queue class definition.
  17. 01a,14jun89,jcf  written.
  18. */
  19. /*
  20. DESCRIPTION
  21. This library contains routines to manage a priority queue.  The queue is
  22. maintained in priority order with each node key a priority delta to the node
  23. ahead of it.  This queue performs a qPriDeltaPut() operation preportional in
  24. time with number of nodes in the queue.  This queue is used for timer queues.
  25. This queue complies with the multi-way queue data structures and thus may be
  26. utilized by any multi-way queue.  The priority delta multi-way queue
  27. class is accessed by the global id qPriDeltaClassId.
  28. SEE ALSO: qLib.
  29. */
  30. #include "vxWorks.h"
  31. #include "qClass.h"
  32. #include "qPriDeltaLib.h"
  33. #include "stdlib.h"
  34. IMPORT ULONG vxTicks; /* current time in ticks */
  35. /* forward static functions */
  36. static STATUS qPriDeltaNullRtn (void);
  37. /* locals */
  38. LOCAL Q_CLASS qPriDeltaClass =
  39.     {
  40.     (FUNCPTR)qPriDeltaCreate,
  41.     (FUNCPTR)qPriDeltaInit,
  42.     (FUNCPTR)qPriDeltaDelete,
  43.     (FUNCPTR)qPriDeltaTerminate,
  44.     (FUNCPTR)qPriDeltaPut,
  45.     (FUNCPTR)qPriDeltaGet,
  46.     (FUNCPTR)qPriDeltaRemove,
  47.     (FUNCPTR)qPriDeltaResort,
  48.     (FUNCPTR)qPriDeltaAdvance,
  49.     (FUNCPTR)qPriDeltaGetExpired,
  50.     (FUNCPTR)qPriDeltaKey,
  51.     (FUNCPTR)qPriDeltaNullRtn,
  52.     (FUNCPTR)qPriDeltaInfo,
  53.     (FUNCPTR)qPriDeltaEach,
  54.     &qPriDeltaClass
  55.     };
  56. /* globals */
  57. Q_CLASS_ID qPriDeltaClassId = &qPriDeltaClass;
  58. /******************************************************************************
  59. *
  60. * qPriDeltaCreate - allocate and initialize a priority delta queue
  61. *
  62. * This routine allocates and initializes a priority delta queue by allocating
  63. * a Q_PRI_HEAD structure from the free memory pool.
  64. *
  65. * RETURNS:
  66. *  Pointer to a Q_PRI_HEAD, or
  67. *  NULL if out of memory.
  68. */
  69. Q_PRI_HEAD *qPriDeltaCreate (void)
  70.     {
  71.     Q_PRI_HEAD *pQPriHead = (Q_PRI_HEAD *) malloc (sizeof (Q_PRI_HEAD));
  72.     if (pQPriHead == NULL)
  73. return (NULL);
  74.     qPriDeltaInit (pQPriHead);
  75.     return (pQPriHead);
  76.     }
  77. /******************************************************************************
  78. *
  79. * qPriDeltaInit - initialize a priority delta queue
  80. *
  81. * This routine initializes the specified priority delta queue.
  82. */
  83. STATUS qPriDeltaInit
  84.     (
  85.     Q_PRI_HEAD *pQPriHead
  86.     )
  87.     {
  88.     dllInit (pQPriHead);  /* initialize doubly linked list */
  89.     return (OK);
  90.     }
  91. /******************************************************************************
  92. *
  93. * qPriDeltaDelete - delete a priority delta queue
  94. *
  95. * This routine deallocates memory associated with the queue.  All queued
  96. * nodes are lost.
  97. *
  98. * RETURNS:
  99. *  OK, or
  100. *  ERROR if memory cannot be deallocated.
  101. */
  102. STATUS qPriDeltaDelete
  103.     (
  104.     Q_PRI_HEAD *pQPriHead
  105.     )
  106.     {
  107.     free ((char *) pQPriHead);
  108.     return OK;
  109.     }
  110. /******************************************************************************
  111. *
  112. * qPriDeltaTerminate - terminate a priority delta queue
  113. *
  114. * This routine terminates a priority delta queue.  All queued nodes are lost.
  115. *
  116. * ARGSUSED
  117. */
  118. STATUS qPriDeltaTerminate
  119.     (
  120.     Q_PRI_HEAD *pQPriHead
  121.     )
  122.     {
  123.     return (OK);
  124.     }
  125. /*******************************************************************************
  126. *
  127. * qPriDeltaPut - insert a node into a priority delta queue
  128. *
  129. * This routine inserts a node into a priority delta queue.  The insertion is
  130. * based on the priority key.  Lower key values are higher in priority.
  131. */
  132. void qPriDeltaPut
  133.     (
  134.     Q_PRI_HEAD  *pQPriHead,
  135.     Q_PRI_NODE  *pQPriNode,
  136.     ULONG       key
  137.     )
  138.     {
  139.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  140.     pQPriNode->key = key - vxTicks; /* relative queue keeps delta time */
  141.     while (pQNode != NULL) /* empty list? */
  142.         {
  143. if (pQPriNode->key < pQNode->key)
  144.     {
  145.     /* We've reached the place in the delta queue to insert this task */
  146.     dllInsert (pQPriHead, DLL_PREVIOUS (&pQNode->node),
  147.        &pQPriNode->node);
  148.     /* Now decrement the delta key of the guy behind us. */
  149.     pQNode->key -= pQPriNode->key;
  150.     return; /* we're done */
  151.     }
  152. pQPriNode->key -= pQNode->key;
  153. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node);
  154. }
  155.     /* if we fall through, add to end of delta q */
  156.     dllInsert (pQPriHead, (DL_NODE *) DLL_LAST (pQPriHead), &pQPriNode->node);
  157.     }
  158. /*******************************************************************************
  159. *
  160. * qPriDeltaGet - remove and return first node in priority delta queue
  161. *
  162. * This routine removes and returns the first node in a priority delta queue.  If
  163. * the queue is empty, NULL is returned.
  164. *
  165. * RETURNS
  166. *  Pointer to first queue node in queue head, or
  167. *  NULL if queue is empty.
  168. */
  169. Q_PRI_NODE *qPriDeltaGet
  170.     (
  171.     Q_PRI_HEAD *pQPriHead
  172.     )
  173.     {
  174.     if (DLL_EMPTY (pQPriHead))
  175. return (NULL);
  176.     return ((Q_PRI_NODE *) dllGet (pQPriHead));
  177.     }
  178. /*******************************************************************************
  179. *
  180. * qPriDeltaRemove - remove a node from a priority delta queue
  181. *
  182. * This routine removes a node from the specified priority delta queue.
  183. */
  184. STATUS qPriDeltaRemove
  185.     (
  186.     Q_PRI_HEAD *pQPriHead,
  187.     Q_PRI_NODE *pQPriNode
  188.     )
  189.     {
  190.     Q_PRI_NODE *pNextNode = (Q_PRI_NODE *) DLL_NEXT (&pQPriNode->node);
  191.     if (pNextNode != NULL)
  192. pNextNode->key += pQPriNode->key; /* add key to next node */
  193.     dllRemove (pQPriHead, &pQPriNode->node);
  194.     return (OK);
  195.     }
  196. /*******************************************************************************
  197. *
  198. * qPriDeltaResort - resort a node to a new position based on a new key
  199. *
  200. * This routine resorts a node to a new position based on a new priority key.
  201. */
  202. void qPriDeltaResort
  203.     (
  204.     Q_PRI_HEAD *pQPriHead,
  205.     Q_PRI_NODE *pQPriNode,
  206.     ULONG       newKey
  207.     )
  208.     {
  209.     qPriDeltaRemove (pQPriHead, pQPriNode);
  210.     qPriDeltaPut (pQPriHead, pQPriNode, newKey);
  211.     }
  212. /*******************************************************************************
  213. *
  214. * qPriDeltaAdvance - advance a queues concept of time
  215. *
  216. * Priority delta queues keep nodes prioritized by time-to-fire.  The library
  217. * utilizes this routine to advance time.  It is usually called from within a
  218. * clock-tick interrupt service routine.
  219. */
  220. void qPriDeltaAdvance
  221.     (
  222.     Q_PRI_HEAD *pQPriHead
  223.     )
  224.     {
  225.     FAST Q_PRI_NODE *pQPriNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  226.     if (pQPriNode != NULL)
  227. pQPriNode->key --;
  228.     }
  229. /*******************************************************************************
  230. *
  231. * qPriDeltaGetExpired - return a time-to-fire expired node
  232. *
  233. * This routine returns a time-to-fire expired node in a priority delta timer
  234. * queue.  Expired nodes result from a qPriDeltaAdvance(2) advancing a node
  235. * beyond its delay.  As many nodes may expire on a single qPriDeltaAdvance(2),
  236. * this routine should be called within a while loop until NULL is returned.
  237. * NULL is returned when there are no expired nodes.
  238. *
  239. * RETURNS
  240. *  Pointer to first queue node in queue head, or
  241. *  NULL if queue is empty.
  242. */
  243. Q_PRI_NODE *qPriDeltaGetExpired
  244.     (
  245.     Q_PRI_HEAD *pQPriHead
  246.     )
  247.     {
  248.     FAST Q_PRI_NODE *pQPriNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  249.     if (pQPriNode != NULL)
  250. {
  251. if (pQPriNode->key != 0)
  252.     pQPriNode = NULL;
  253. else
  254.     qPriDeltaRemove (pQPriHead, pQPriNode); /* get off delay list */
  255. }
  256.     return (pQPriNode);
  257.     }
  258. /*******************************************************************************
  259. *
  260. * qPriDeltaKey - return the key of a node
  261. *
  262. * This routine returns the key of a node currently in a priority delta queue.
  263. *
  264. * RETURNS
  265. *  Node's key.
  266. *
  267. * ARGSUSED
  268. */
  269. ULONG qPriDeltaKey
  270.     (
  271.     Q_PRI_NODE  *pQPriNode      /* node to get key for */
  272.     )
  273.     {
  274.     FAST ULONG sum = 0;
  275.     while (pQPriNode != NULL)
  276.         {
  277. sum += pQPriNode->key;
  278. pQPriNode = (Q_PRI_NODE *) DLL_PREVIOUS (&pQPriNode->node);
  279. }
  280.     return (sum); /* return key */
  281.     }
  282. /*******************************************************************************
  283. *
  284. * qPriDeltaInfo - gather information on a priority delta queue
  285. *
  286. * This routine fills up to maxNodes elements of a nodeArray with nodes
  287. * currently in a multi-way queue.  The actual number of nodes copied to the
  288. * array is returned.  If the nodeArray is NULL, then the number of nodes in
  289. * the priority delta queue is returned.
  290. *
  291. * RETURNS
  292. *  Number of node pointers copied into the nodeArray, or
  293. *  Number of nodes in multi-way queue if nodeArray is NULL
  294. */
  295. int qPriDeltaInfo
  296.     (
  297.     Q_PRI_HEAD *pQPriHead,      /* priority queue to gather list for */
  298.     FAST int nodeArray[],       /* array of node pointers to be filled in */
  299.     FAST int maxNodes           /* max node pointers nodeArray can accomodate */
  300.     )
  301.     {
  302.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  303.     FAST int *pElement  = nodeArray;
  304.     if (nodeArray == NULL) /* NULL node array means return count */
  305. return (dllCount (pQPriHead));
  306.     while ((pQNode != NULL) && (--maxNodes >= 0))
  307. {
  308. *(pElement++) = (int)pQNode; /* fill in table */
  309. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node); /* next node */
  310. }
  311.     return (pElement - nodeArray); /* return count of active tasks */
  312.     }
  313. /*******************************************************************************
  314. *
  315. * qPriDeltaEach - call a routine for each node in a queue
  316. *
  317. * This routine calls a user-supplied routine once for each node in the
  318. * queue.  The routine should be declared as follows:
  319. * .CS
  320. *  BOOL routine (pQNode, arg)
  321. *      Q_PRI_NODE *pQNode; /@ pointer to a queue node          @/
  322. *      int      arg; /@ arbitrary user-supplied argument @/
  323. * .CE
  324. * The user-supplied routine should return TRUE if qPriDeltaEach (2) is to
  325. * continue calling it for each entry, or FALSE if it is done and
  326. * qPriDeltaEach can exit.
  327. *
  328. * RETURNS: NULL if traversed whole queue, or pointer to Q_PRI_NODE that
  329. *          qPriDeltaEach stopped on.
  330. */
  331. Q_PRI_NODE *qPriDeltaEach
  332.     (
  333.     Q_PRI_HEAD  *pQHead,        /* queue head of queue to call routine for */
  334.     FUNCPTR     routine,        /* the routine to call for each table entry */
  335.     int         routineArg      /* arbitrary user-supplied argument */
  336.     )
  337.     {
  338.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQHead);
  339.     while ((pQNode != NULL) && ((* routine) (pQNode, routineArg)))
  340. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node);
  341.     return (pQNode); /* return node we ended with */
  342.     }
  343. /*******************************************************************************
  344. *
  345. * qPriDeltaNullRtn - nop that returns OK
  346. *
  347. * This routine does nothing and returns OK.  It is used to by the queue class
  348. * structure for unsupported functions.
  349. */
  350. LOCAL STATUS qPriDeltaNullRtn (void)
  351.     {
  352.     return (OK);
  353.     }