collectn.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:9k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3.  * The contents of this file are subject to the Mozilla Public
  4.  * License Version 1.1 (the "License"); you may not use this file
  5.  * except in compliance with the License. You may obtain a copy of
  6.  * the License at http://www.mozilla.org/MPL/
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS
  9.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10.  * implied. See the License for the specific language governing
  11.  * rights and limitations under the License.
  12.  * 
  13.  * The Original Code is the Netscape security libraries.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation.  Portions created by Netscape are 
  17.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s):
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  */
  34. #include "collectn.h"
  35. #include "prerror.h"
  36. #include "prmem.h"
  37. #include "seccomon.h"
  38. #include "serv.h"
  39. SSMCollection *
  40. SSM_NewCollection(void)
  41. {
  42.     SSMCollection *coll;
  43.     coll = PR_NEWZAP(SSMCollection);
  44.     if (coll == NULL)
  45.         goto loser;
  46.     coll->lock = PR_NewMonitor();
  47.     if (coll->lock == NULL)
  48.         goto loser;
  49.     PR_INIT_CLIST(&coll->list);
  50.     return coll;
  51.  loser:
  52.     SSM_DestroyCollection(coll);
  53.     return NULL;
  54. }
  55. SSMStatus
  56. SSM_DestroyCollection(SSMCollection *victim)
  57. {
  58.     if (victim == NULL)
  59.         return PR_SUCCESS;
  60.     PR_ASSERT(victim->nItems == 0);
  61.     if (victim->nItems != 0)
  62.         return PR_FAILURE;
  63.     if (victim->lock)
  64.         PR_DestroyMonitor(victim->lock);
  65.     PR_Free(victim);
  66.     return PR_SUCCESS;
  67. }
  68. static SSMListItem *
  69. new_list_item(PRIntn priority, void *data)
  70. {
  71.     SSMListItem *item;
  72.     item = PR_NEWZAP(SSMListItem);
  73.     if (item == NULL)
  74.         return NULL;
  75.     item->priority = priority;
  76.     item->data = data;
  77.     return item;
  78. }
  79. static SSMListItem *
  80. find_list_item(SSMCollection *list, void *which)
  81. {
  82.     PRCList *link;
  83.   
  84.     for(link = PR_LIST_HEAD(&list->list); link != &list->list;
  85.         link = PR_NEXT_LINK(link)) 
  86.     {
  87.         SSMListItem *item = (SSMListItem *) link;
  88.         if (item->data == which)
  89.             return item;
  90.     }
  91.     return NULL;
  92. }
  93. /* Insert (item) into the list before (before). 
  94.    If (before) is NULL, append to the list. */
  95. SSMStatus
  96. ssm_InsertSafe(SSMCollection *list, PRIntn priority, void *data, void *before)
  97. {
  98.     SSMListItem *beforeItem = NULL, *item;
  99.     if ((data == NULL) || (list == NULL)) 
  100.     {
  101.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  102.         return PR_FAILURE;
  103.     }
  104.   
  105.     /* Find (before) in the list if it's here. */
  106.     if (before == NULL) 
  107.         beforeItem = (SSMListItem *) &list->list;
  108.     else
  109.         beforeItem = find_list_item(list, before);
  110.     /* Create a new list item. */
  111.     item = new_list_item(priority, data);
  112.     if (item == NULL)
  113.         return PR_FAILURE;
  114.     PR_INSERT_BEFORE(&item->link, &beforeItem->link);
  115.     list->nItems++;
  116.     list->priorityCount[priority]++;
  117.   
  118.     return PR_SUCCESS;
  119. }
  120. /* Insert (data) into the list before (before). 
  121.    If (before) is NULL, append to the list. */
  122. SSMStatus
  123. SSM_Insert(SSMCollection *list, PRIntn priority, void *data, void *before)
  124. {
  125.     SSMStatus rv;
  126.     if (list == NULL) 
  127.     {
  128.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  129.         return PR_FAILURE;
  130.     }
  131.     PR_EnterMonitor(list->lock);
  132.     rv = ssm_InsertSafe(list, priority, data, before);
  133.     PR_Notify(list->lock);
  134.     PR_ExitMonitor(list->lock);
  135.     return rv;
  136. }
  137. /* Remove (data) from the list. */
  138. SSMStatus
  139. ssm_RemoveSafe(SSMCollection *list, void *data)
  140. {
  141.     SSMStatus rv = PR_SUCCESS;
  142.     SSMListItem *item;
  143.     if ((data == NULL) || (list == NULL)) 
  144.     {
  145.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  146.         return PR_FAILURE;
  147.     }
  148.   
  149.     item = find_list_item(list, data);
  150.     if (item == NULL) 
  151.     {
  152.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  153.         return PR_FAILURE;
  154.     }
  155.     if ((item->priority >= 0) && (item->priority < SSM_PRIORITY_MAX))
  156.         list->priorityCount[item->priority]--;
  157.     PR_REMOVE_LINK(&item->link);
  158.     PR_Free(item);
  159.     list->nItems--;
  160.   
  161.     return rv;
  162. }
  163. /* Remove (item) from the list. */
  164. SSMStatus
  165. SSM_Remove(SSMCollection *list, void *item)
  166. {
  167.     SSMStatus rv;
  168.     if (list == NULL) 
  169.     {
  170.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  171.         return PR_FAILURE;
  172.     }
  173.     PR_EnterMonitor(list->lock);
  174.     rv = ssm_RemoveSafe(list, item);
  175.     PR_Notify(list->lock);
  176.     PR_ExitMonitor(list->lock);
  177.     return rv;
  178. }
  179. /* Count the number of items in the list. */
  180. PRIntn
  181. ssm_CountSafe(SSMCollection *list, PRIntn priority)
  182. {
  183.     PRIntn result = 0;
  184.     PRIntn i;
  185.     if (priority == SSM_PRIORITY_ANY)
  186.         result = list->nItems;
  187.     else
  188.     {
  189.         for(i=priority; i <= SSM_PRIORITY_MAX; i++)
  190.             result += list->priorityCount[i];
  191.     }
  192.     return result;
  193. }
  194. /* Count the number of items in the list. */
  195. PRIntn
  196. SSM_CountPriority(SSMCollection *list, PRIntn priority)
  197. {
  198.     int count;
  199.     if ((list == NULL) 
  200.         || (priority < SSM_PRIORITY_ANY) 
  201.         || (priority > SSM_PRIORITY_MAX)) 
  202.     {
  203.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  204.         return -1;
  205.     }
  206.     PR_EnterMonitor(list->lock);
  207.     count = ssm_CountSafe(list, priority);
  208.     PR_ExitMonitor(list->lock);
  209.     return count;
  210. }
  211. PRIntn
  212. SSM_Count(SSMCollection *list)
  213. {
  214.     return SSM_CountPriority(list, SSM_PRIORITY_ANY);
  215. }
  216. /* Get (which)th item from the list. zero-based index. */
  217. void *
  218. SSM_At(SSMCollection *list, PRIntn which)
  219. {
  220.     PRCList *link;
  221.     if ((list == NULL) || (which >= list->nItems)) {
  222.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  223.         return NULL;
  224.     }
  225.     PR_EnterMonitor(list->lock);
  226.     link = PR_LIST_HEAD(&list->list);
  227.     for ( ; which > 0 ; which--) {
  228.         link = PR_NEXT_LINK(link);
  229.     }
  230.  
  231.     PR_ExitMonitor(list->lock);
  232.     return ((SSMListItem *) link)->data;
  233. }
  234. SSMStatus
  235. SSM_Enqueue(SSMCollection *list, PRIntn priority, void *item)
  236. {
  237.     /* Insert this element at the end. */
  238.     return SSM_Insert(list, priority, item, NULL);
  239. }
  240. SSMListItem *
  241. ssm_FirstAtPriority(SSMCollection *list, PRIntn priority)
  242. {
  243.     SSMListItem *result;
  244.     SSMListItem *link;
  245.     result = NULL; /* in case we fail */
  246.     if ((list == NULL) || (priority > SSM_PRIORITY_MAX)) 
  247.     {
  248.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  249.         return NULL;
  250.     }
  251.     if (PR_CLIST_IS_EMPTY(&list->list))
  252.         result = NULL;
  253.     else if (priority == SSM_PRIORITY_ANY)
  254.         result = (SSMListItem *) PR_LIST_HEAD(&list->list);
  255.     else /* asked for priority and list not empty */
  256.     {
  257.         /* Find the first element from the list at (priority). */
  258.         link = (SSMListItem *) PR_LIST_HEAD(&list->list);
  259.         while((link != (SSMListItem *) &list->list) && 
  260.               (link->priority < priority))
  261.             link = (SSMListItem *) PR_NEXT_LINK(&link->link);
  262.         if (link != (SSMListItem *) &list->list)
  263.             result = link;
  264.     }
  265.     return result;
  266. }
  267. SSMStatus
  268. SSM_Dequeue(SSMCollection *list, PRIntn priority, 
  269.     void **result, PRBool doBlock)
  270. {
  271.     void *data = NULL;
  272.     SSMListItem *link;
  273. SSMStatus rv = PR_SUCCESS;
  274.     *result = NULL; /* in case we fail */
  275.     if (list == NULL) {
  276.         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  277.         return PR_FAILURE;
  278.     }
  279.     PR_EnterMonitor(list->lock);
  280.     while(doBlock && (ssm_CountSafe(list, priority) == 0)) {
  281.         rv = PR_Wait(list->lock, PR_INTERVAL_NO_TIMEOUT);
  282. if (rv == PR_PENDING_INTERRUPT_ERROR)
  283. {
  284. /* We got interrupted, bail */
  285. return rv;
  286. }
  287.         /*        SSM_DEBUG("ssm_CountSafe (prio %d) is %d.n", 
  288.                   priority, ssm_CountSafe(list, priority));*/
  289.     }
  290.     /* Pop the first element from the list at (priority). */
  291.     if (!PR_CLIST_IS_EMPTY(&list->list)) {
  292.         link = ssm_FirstAtPriority(list, priority);
  293.         if (link)
  294.         {
  295.             data = link->data;
  296.             if ((link->priority >= 0) && (link->priority < SSM_PRIORITY_MAX))
  297.                 list->priorityCount[link->priority]--;
  298.     
  299.             PR_REMOVE_LINK(&link->link);
  300.             PR_Free(link);
  301.             list->nItems--;
  302.         }
  303.     }
  304.     PR_Notify(list->lock);
  305.     PR_ExitMonitor(list->lock);
  306.     *result = data;
  307.     return PR_SUCCESS;
  308. }