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

VxWorks

开发平台:

C/C++

  1. /* qPriListLib.c - priority ordered linked list queue library */
  2. /* Copyright 1984-1992 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01h,19jul92,pme  made qPriListRemove 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 qPriListCalibrate().
  16. 01b,26jun90,jcf  fixed qPriListResort();
  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 simple priority insertion into a linked list.
  23. This queue performs a qPriListPut() operation preportional in time with number
  24. of nodes in the queue.  This general purpose priority queue has many uses
  25. including the basis for priority semaphore queues.
  26. This queue complies with the multi-way queue data structures and thus may be
  27. utilized by any multi-way queue.  The priority list multi-way queue
  28. class is accessed by the global id qPriListClassId.
  29. SEE ALSO: qLib.
  30. */
  31. #include "vxWorks.h"
  32. #include "qClass.h"
  33. #include "qPriListLib.h"
  34. #include "stdlib.h"
  35. IMPORT ULONG vxTicks; /* current time in ticks */
  36. /* locals */
  37. LOCAL Q_CLASS qPriListClass =
  38.     {
  39.     (FUNCPTR)qPriListCreate,
  40.     (FUNCPTR)qPriListInit,
  41.     (FUNCPTR)qPriListDelete,
  42.     (FUNCPTR)qPriListTerminate,
  43.     (FUNCPTR)qPriListPut,
  44.     (FUNCPTR)qPriListGet,
  45.     (FUNCPTR)qPriListRemove,
  46.     (FUNCPTR)qPriListResort,
  47.     (FUNCPTR)qPriListAdvance,
  48.     (FUNCPTR)qPriListGetExpired,
  49.     (FUNCPTR)qPriListKey,
  50.     (FUNCPTR)qPriListCalibrate,
  51.     (FUNCPTR)qPriListInfo,
  52.     (FUNCPTR)qPriListEach,
  53.     &qPriListClass
  54.     };
  55. LOCAL Q_CLASS qPriListFromTailClass =
  56.     {
  57.     (FUNCPTR)qPriListCreate,
  58.     (FUNCPTR)qPriListInit,
  59.     (FUNCPTR)qPriListDelete,
  60.     (FUNCPTR)qPriListTerminate,
  61.     (FUNCPTR)qPriListPutFromTail,
  62.     (FUNCPTR)qPriListGet,
  63.     (FUNCPTR)qPriListRemove,
  64.     (FUNCPTR)qPriListResort,
  65.     (FUNCPTR)qPriListAdvance,
  66.     (FUNCPTR)qPriListGetExpired,
  67.     (FUNCPTR)qPriListKey,
  68.     (FUNCPTR)qPriListCalibrate,
  69.     (FUNCPTR)qPriListInfo,
  70.     (FUNCPTR)qPriListEach,
  71.     &qPriListFromTailClass
  72.     };
  73. /* globals */
  74. Q_CLASS_ID qPriListClassId    = &qPriListClass;
  75. Q_CLASS_ID qPriListFromTailClassId = &qPriListFromTailClass;
  76. /******************************************************************************
  77. *
  78. * qPriListCreate - allocate and initialize a priority list queue
  79. *
  80. * This routine allocates and initializes a priority list queue by allocating a
  81. * Q_PRI_HEAD structure from the free memory pool.
  82. *
  83. * RETURNS:
  84. *  Pointer to a Q_PRI_HEAD, or
  85. *  NULL if out of memory.
  86. */
  87. Q_PRI_HEAD *qPriListCreate (void)
  88.     {
  89.     Q_PRI_HEAD *pQPriHead = (Q_PRI_HEAD *) malloc (sizeof (Q_PRI_HEAD));
  90.     if (pQPriHead == NULL)
  91. return (NULL);
  92.     qPriListInit (pQPriHead);
  93.     return (pQPriHead);
  94.     }
  95. /******************************************************************************
  96. *
  97. * qPriListInit - initialize a priority list queue
  98. *
  99. * This routine initializes the specified priority list queue.
  100. */
  101. STATUS qPriListInit
  102.     (
  103.     Q_PRI_HEAD *pQPriHead
  104.     )
  105.     {
  106.     dllInit (pQPriHead);  /* initialize doubly linked list */
  107.     return (OK);
  108.     }
  109. /******************************************************************************
  110. *
  111. * qPriListDelete - delete a priority list queue
  112. *
  113. * This routine deallocates memory associated with the queue.  All queued
  114. * nodes are lost.
  115. *
  116. * RETURNS:
  117. *  OK, or
  118. *  ERROR if memory cannot be deallocated.
  119. */
  120. STATUS qPriListDelete
  121.     (
  122.     Q_PRI_HEAD *pQPriHead
  123.     )
  124.     {
  125.     free ((char *) pQPriHead);
  126.     return OK;
  127.     }
  128. /******************************************************************************
  129. *
  130. * qPriListTerminate - terminate a priority list queue
  131. *
  132. * This routine terminates a priority list queue.  All queued nodes will be lost.
  133. *
  134. * ARGSUSED
  135. */
  136. STATUS qPriListTerminate
  137.     (
  138.     Q_PRI_HEAD *pQPriHead
  139.     )
  140.     {
  141.     return (OK);
  142.     }
  143. /*******************************************************************************
  144. *
  145. * qPriListPut - insert a node into a priority list queue
  146. *
  147. * This routine inserts a node into a priority list queue.  The insertion is
  148. * based on the specified prioriyt key.  The lower the key the higher the
  149. * priority.
  150. */
  151. void qPriListPut
  152.     (
  153.     Q_PRI_HEAD  *pQPriHead,
  154.     Q_PRI_NODE  *pQPriNode,
  155.     ULONG        key
  156.     )
  157.     {
  158.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  159.     pQPriNode->key = key;
  160.     while (pQNode != NULL)
  161.         {
  162. if (key < pQNode->key) /* it will be last of same priority */
  163.     {
  164.     dllInsert (pQPriHead, DLL_PREVIOUS (&pQNode->node),
  165.        &pQPriNode->node);
  166.     return;
  167.     }
  168. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node);
  169. }
  170.     dllInsert (pQPriHead, (DL_NODE *) DLL_LAST (pQPriHead), &pQPriNode->node);
  171.     }
  172. /*******************************************************************************
  173. *
  174. * qPriListPutFromTail - insert a node into a priority list queue from tail
  175. *
  176. * This routine inserts a node into a priority list queue.  The insertion is
  177. * based on the specified prioriyt key.  The lower the key the higher the
  178. * priority.  Unlike qPriListPut(2), this routine searches for the correct
  179. * position in the queue from the queue's tail.  This is useful if the
  180. * caller has a priori knowledge that the key is of low priority.
  181. */
  182. void qPriListPutFromTail
  183.     (
  184.     Q_PRI_HEAD  *pQPriHead,
  185.     Q_PRI_NODE  *pQPriNode,
  186.     ULONG        key
  187.     )
  188.     {
  189.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_LAST (pQPriHead);
  190.     pQPriNode->key = key;
  191.     while (pQNode != NULL)
  192.         {
  193. if (key >= pQNode->key) /* it will be last of same priority */
  194.     {
  195.     dllInsert (pQPriHead, &pQNode->node, &pQPriNode->node);
  196.     return;
  197.     }
  198. pQNode = (Q_PRI_NODE *) DLL_PREVIOUS (&pQNode->node);
  199. }
  200.     dllInsert (pQPriHead, (DL_NODE *)NULL, &pQPriNode->node);
  201.     }
  202. /*******************************************************************************
  203. *
  204. * qPriListGet - remove and return first node in priority list queue
  205. *
  206. * This routine removes and returns the first node in a priority list queue.  If
  207. * the queue is empty, NULL is returned.
  208. *
  209. * RETURNS
  210. *  Pointer to first queue node in queue head, or
  211. *  NULL if queue is empty.
  212. */
  213. Q_PRI_NODE *qPriListGet
  214.     (
  215.     Q_PRI_HEAD *pQPriHead
  216.     )
  217.     {
  218.     if (DLL_EMPTY (pQPriHead))
  219. return (NULL);
  220.     return ((Q_PRI_NODE *) dllGet (pQPriHead));
  221.     }
  222. /*******************************************************************************
  223. *
  224. * qPriListRemove - remove a node from a priority list queue
  225. *
  226. * This routine removes a node from the specified priority list queue.
  227. */
  228. STATUS qPriListRemove
  229.     (
  230.     Q_PRI_HEAD *pQPriHead,
  231.     Q_PRI_NODE *pQPriNode
  232.     )
  233.     {
  234.     dllRemove (pQPriHead, &pQPriNode->node);
  235.     return (OK);
  236.     }
  237. /*******************************************************************************
  238. *
  239. * qPriListResort - resort a node to a new position based on a new key
  240. *
  241. * This routine resorts a node to a new position based on a new key.
  242. */
  243. void qPriListResort
  244.     (
  245.     FAST Q_PRI_HEAD *pQPriHead,
  246.     FAST Q_PRI_NODE *pQPriNode,
  247.     FAST ULONG       newKey
  248.     )
  249.     {
  250.     FAST Q_PRI_NODE *pPrev = (Q_PRI_NODE *)DLL_PREVIOUS (&pQPriNode->node);
  251.     FAST Q_PRI_NODE *pNext = (Q_PRI_NODE *)DLL_NEXT (&pQPriNode->node);
  252.     if (((pPrev == NULL) || (newKey >= pPrev->key)) &&
  253. ((pNext == NULL) || (newKey <= pNext->key)))
  254. {
  255. pQPriNode->key = newKey;
  256. }
  257.     else
  258. {
  259. qPriListRemove (pQPriHead, pQPriNode);
  260. qPriListPut (pQPriHead, pQPriNode, newKey);
  261. }
  262.     }
  263. /*******************************************************************************
  264. *
  265. * qPriListAdvance - advance a queues concept of time
  266. *
  267. * Priority list queues need not keep track of time because nodes contain time of
  268. * expiration.  So this routine is a NOP.
  269. *
  270. * NOMANUAL
  271. * ARGSUSED
  272. */
  273. void qPriListAdvance
  274.     (
  275.     Q_PRI_HEAD *pQPriHead
  276.     )
  277.     {
  278.     /* Absolute queue so advancing key of lead node unnecessary */
  279.     }
  280. /*******************************************************************************
  281. *
  282. * qPriListGetExpired - return a time-to-fire expired node
  283. *
  284. * This routine returns a time-to-fire expired node in a priority list timer
  285. * queue.  Expired nodes result from a comparison with the global variable
  286. * vxTicks.  As many nodes may expire on a single advance of vxTicks, this
  287. * routine should be called inside a while loop until NULL is returned.  NULL
  288. * is returned when there are no expired nodes.
  289. *
  290. * RETURNS
  291. *  Pointer to first queue node in queue head, or
  292. *  NULL if queue is empty.
  293. */
  294. Q_PRI_NODE *qPriListGetExpired
  295.     (
  296.     Q_PRI_HEAD *pQPriHead
  297.     )
  298.     {
  299.     FAST Q_PRI_NODE *pQPriNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  300.     if ((pQPriNode != NULL) && (pQPriNode->key <= vxTicks))
  301. return ((Q_PRI_NODE *) dllGet (pQPriHead));
  302.     else
  303. return (NULL);
  304.     }
  305. /*******************************************************************************
  306. *
  307. * qPriListCalibrate - offset every node in a queue by some delta
  308. *
  309. * This routine offsets every node in a priority list queue by some delta.  The
  310. * offset may either by positive or negative.
  311. */
  312. void qPriListCalibrate
  313.     (
  314.     Q_PRI_HEAD *pQHead,         /* queue head of queue to calibrate nodes for */
  315.     ULONG       keyDelta        /* offset to add to each node's key */
  316.     )
  317.     {
  318.     FAST Q_PRI_NODE *pQPriNode;
  319.     for (pQPriNode = (Q_PRI_NODE *) DLL_FIRST (pQHead);
  320.          pQPriNode != NULL;
  321.  pQPriNode = (Q_PRI_NODE *) DLL_NEXT (&pQPriNode->node))
  322. {
  323.         pQPriNode->key += keyDelta; /* offset key */
  324. }
  325.     }
  326. /*******************************************************************************
  327. *
  328. * qPriListKey - return the key of a node
  329. *
  330. * This routine returns the key of a node currently in a priority list queue.
  331. *
  332. * RETURNS
  333. *  Node's key.
  334. */
  335. ULONG qPriListKey
  336.     (
  337.     Q_PRI_NODE *pQPriNode,
  338.     int         keyType                 /* 0 = normal; 1 = time queue */
  339.     )
  340.     {
  341.     if (keyType == 0)
  342. return (pQPriNode->key);
  343.     else
  344. return (pQPriNode->key - vxTicks);
  345.     }
  346. /*******************************************************************************
  347. *
  348. * qPriListInfo - gather information on a priority list queue
  349. *
  350. * This routine fills up to maxNodes elements of a nodeArray with nodes
  351. * currently in a priority list queue.  The actual number of nodes copied to the
  352. * array is returned.  If the nodeArray is NULL, then the number of nodes in
  353. * the priority list queue is returned.
  354. *
  355. * RETURNS
  356. *  Number of node pointers copied into the nodeArray, or
  357. *  Number of nodes in priority list queue if nodeArray is NULL
  358. */
  359. int qPriListInfo
  360.     (
  361.     Q_PRI_HEAD *pQPriHead,      /* priority queue to gather list for */
  362.     FAST int nodeArray[],       /* array of node pointers to be filled in */
  363.     FAST int maxNodes           /* max node pointers nodeArray can accomodate */
  364.     )
  365.     {
  366.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQPriHead);
  367.     FAST int *pElement  = nodeArray;
  368.     if (nodeArray == NULL) /* NULL node array means return count */
  369. return (dllCount (pQPriHead));
  370.     while ((pQNode != NULL) && (--maxNodes >= 0))
  371. {
  372. *(pElement++) = (int)pQNode; /* fill in table */
  373. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node); /* next node */
  374. }
  375.     return (pElement - nodeArray); /* return count of active tasks */
  376.     }
  377. /*******************************************************************************
  378. *
  379. * qPriListEach - call a routine for each node in a queue
  380. *
  381. * This routine calls a user-supplied routine once for each node in the
  382. * queue.  The routine should be declared as follows:
  383. * .CS
  384. *  BOOL routine (pQNode, arg)
  385. *      Q_PRI_NODE *pQNode; /@ pointer to a queue node          @/
  386. *      int   arg; /@ arbitrary user-supplied argument @/
  387. * .CE
  388. * The user-supplied routine should return TRUE if qPriListEach (2) is to
  389. * continue calling it for each entry, or FALSE if it is done and
  390. * qPriListEach can exit.
  391. *
  392. * RETURNS: NULL if traversed whole queue, or pointer to Q_PRI_NODE that
  393. *          qPriListEach stopped on.
  394. */
  395. Q_PRI_NODE *qPriListEach
  396.     (
  397.     Q_PRI_HEAD  *pQHead,        /* queue head of queue to call routine for */
  398.     FUNCPTR     routine,        /* the routine to call for each table entry */
  399.     int         routineArg      /* arbitrary user-supplied argument */
  400.     )
  401.     {
  402.     FAST Q_PRI_NODE *pQNode = (Q_PRI_NODE *) DLL_FIRST (pQHead);
  403.     while ((pQNode != NULL) && ((* routine) (pQNode, routineArg)))
  404. pQNode = (Q_PRI_NODE *) DLL_NEXT (&pQNode->node);
  405.     return (pQNode); /* return node we ended with */
  406.     }