os161-1.99
 All Data Structures
queue.c
00001 /*
00002  * Queue of void pointers. See queue.h for details.
00003  */
00004 
00005 #include <types.h>
00006 #include <kern/errno.h>
00007 #include <lib.h>
00008 #include <queue.h>
00009 
00010 struct queue {
00011         int size;
00012         int nextwrite;  // next element to write to (was head)
00013         int nextread;     // next element to read from (was tail)
00014         void **data;
00015 };
00016 
00017 static
00018 int
00019 q_grow(struct queue *q, int targetsize)
00020 {
00021         void **olddata = q->data;
00022         int onr = q->nextread;
00023         int onw = q->nextwrite;
00024         int osize = q->size;
00025 
00026         int nsize;
00027         void **ndata;
00028 
00029         int i, result;
00030 
00031         nsize = q->size;
00032         while (nsize < targetsize) {
00033                 nsize *= 2;
00034                 /* prevent infinite loop */
00035                 KASSERT(nsize > 0);
00036         }
00037         ndata = kmalloc(nsize * sizeof(void *));
00038         if (ndata == NULL) {
00039                 return ENOMEM;
00040         }
00041         q->size = nsize;
00042         q->data = ndata;
00043         q->nextread = q->nextwrite = 0;
00044         
00045         for (i=onr; i!=onw; i = (i+1)%osize) {
00046                 result = q_addtail(q, olddata[i]);
00047                 KASSERT(result==0);
00048         }
00049         kfree(olddata);
00050         return 0;
00051 }
00052 
00053 struct queue *
00054 q_create(int size)
00055 {
00056         struct queue *q = kmalloc(sizeof(struct queue));
00057         if (q==NULL) {
00058                 return NULL;
00059         }
00060         q->size = size;
00061         q->data = kmalloc(size * sizeof(void *));
00062         if (q->data==NULL) {
00063                 kfree(q);
00064                 return NULL;
00065         }
00066         q->nextread = q->nextwrite = 0;
00067         return q;
00068 }
00069 
00070 int
00071 q_preallocate(struct queue *q, int size)
00072 {
00073         int result = 0;
00074 
00075         KASSERT(q->size > 0);
00076 
00077         if (size > q->size) {
00078                 result = q_grow(q, size);
00079         }
00080         return result;
00081 }
00082 
00083 inline
00084 int
00085 q_empty(struct queue *q)
00086 {
00087         return q->nextwrite == q->nextread;
00088 }
00089 
00090 int
00091 q_addtail(struct queue *q, void *ptr)
00092 {
00093         int nextnext, result;
00094 
00095         KASSERT(q->size > 0);
00096  
00097         nextnext = (q->nextwrite+1) % q->size;
00098         if (nextnext==q->nextread) {
00099                 result = q_grow(q, q->size+1);
00100                 if (result) {
00101                         return result;
00102                 }
00103                 nextnext = (q->nextwrite+1) % q->size;
00104         }
00105         q->data[q->nextwrite] = ptr;
00106         q->nextwrite = nextnext;
00107         return 0;
00108 }
00109 
00110 void *
00111 q_remhead(struct queue *q)
00112 {
00113         void *ret;
00114 
00115         KASSERT(q->size > 0);
00116 
00117         KASSERT(!q_empty(q));
00118         ret = q->data[q->nextread];
00119         q->nextread = (q->nextread+1)%q->size;
00120         return ret;
00121 }
00122 
00123 void
00124 q_destroy(struct queue *q)
00125 {
00126         KASSERT(q_empty(q));
00127         kfree(q->data);
00128         kfree(q);
00129 }
00130 
00131 /* These are really intended only for debugging. */
00132 int
00133 q_getstart(struct queue *q)
00134 {
00135         return q->nextread;
00136 }
00137 
00138 int
00139 q_getend(struct queue *q)
00140 {
00141         return q->nextwrite;
00142 }
00143 
00144 int
00145 q_getsize(struct queue *q)
00146 {
00147         return q->size;
00148 }
00149 
00150 void *
00151 q_getguy(struct queue *q, int index)
00152 {
00153         // note that we don't check to make sure the access isn't in the
00154         // unused part of the queue space. we probably should.
00155 
00156         KASSERT(index>=0 && index<q->size);
00157         return q->data[index];
00158 }
00159 
00160 void *
00161 q_peek(struct queue *q)
00162 {
00163         void *ret;
00164 
00165         KASSERT(q);
00166         KASSERT(q->size > 0);
00167 
00168         if (q_empty(q)) {
00169     ret = 0;
00170         } else {
00171           ret = q->data[q->nextread];
00172         }
00173         return ret;
00174 }
00175 
00176 int
00177 q_len(struct queue *theq)
00178 {
00179         int count = 0;
00180         int tmp = theq->nextread;
00181         while (tmp != theq->nextwrite) {
00182                 tmp = (tmp+1) % theq->size;
00183                 count++;
00184         }
00185         return count;
00186 }
 All Data Structures