jabberd2  2.2.16
util/pqueue.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 /* priority queues */
00022 
00023 #include "pqueue.h"
00024 
00025 #include "pool.h"
00026 
00027 #include <stdio.h>      /* to get NULL */
00028 #include <assert.h>
00029 
00030 typedef struct _pqueue_node_st  *_pqueue_node_t;
00031 struct _pqueue_node_st {
00032     void            *data;
00033 
00034     int             priority;
00035 
00036     _pqueue_node_t  next;
00037     _pqueue_node_t  prev;
00038 };
00039 
00040 struct _pqueue_st {
00041     pool_t            p;
00042     _pqueue_node_t  cache;
00043 
00044     _pqueue_node_t  front;
00045     _pqueue_node_t  back;
00046 
00047     int             size;
00048 };
00049 
00050 pqueue_t pqueue_new(pool_t p) {
00051     pqueue_t q;
00052 
00053     q = (pqueue_t) pmalloco(p, sizeof(struct _pqueue_st));
00054 
00055     q->p = p;
00056 
00057     return q;
00058 }
00059 
00060 void pqueue_push(pqueue_t q, void *data, int priority) {
00061     _pqueue_node_t qn, scan;
00062 
00063     assert((q != NULL));
00064 
00065     q->size++;
00066 
00067     /* node from the cache, or make a new one */
00068     qn = q->cache;
00069     if(qn != NULL)
00070         q->cache = qn->next;
00071     else
00072         qn = (_pqueue_node_t) pmalloc(q->p, sizeof(struct _pqueue_node_st));
00073 
00074     qn->data = data;
00075     qn->priority = priority;
00076 
00077     qn->next = NULL;
00078     qn->prev = NULL;
00079 
00080     /* first one */
00081     if(q->back == NULL && q->front == NULL) {
00082         q->back = qn;
00083         q->front = qn;
00084 
00085         return;
00086     }
00087 
00088     /* find the first node with priority <= to us */
00089     for(scan = q->back; scan != NULL && scan->priority > priority; scan = scan->next);
00090 
00091     /* didn't find one, so we have top priority - push us on the front */
00092     if(scan == NULL) {
00093         qn->prev = q->front;
00094         qn->prev->next = qn;
00095         q->front = qn;
00096 
00097         return;
00098     }
00099 
00100     /* push us in front of scan */
00101     qn->next = scan;
00102     qn->prev = scan->prev;
00103 
00104     if(scan->prev != NULL)
00105         scan->prev->next = qn;
00106     else
00107         q->back = qn;
00108 
00109     scan->prev = qn;
00110 }
00111 
00112 void *pqueue_pull(pqueue_t q) {
00113     void *data;
00114     _pqueue_node_t qn;
00115 
00116     assert((q != NULL));
00117 
00118     if(q->front == NULL)
00119         return NULL;
00120 
00121     data = q->front->data;
00122 
00123     qn = q->front;
00124 
00125     if(qn->prev != NULL)
00126         qn->prev->next = NULL;
00127     
00128     q->front = qn->prev;
00129 
00130     /* node to cache for later reuse */
00131     qn->next = q->cache;
00132     q->cache = qn;
00133 
00134     if(q->front == NULL)
00135         q->back = NULL;
00136 
00137     q->size--;
00138 
00139     return data;
00140 }
00141 
00142 int pqueue_size(pqueue_t q) {
00143     return q->size;
00144 }