• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

llqueue.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Implementation of a simple linked list queue
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "ink_config.h"
00025 #include "ink_memory.h"
00026 
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <assert.h>
00030 #include <limits.h>
00031 
00032 #include "ink_llqueue.h"
00033 #include "errno.h"
00034 
00035 #define RECORD_CHUNK 1024
00036 
00037 // These are obviously not used anywhere, I don't know if or how they
00038 // were supposed to work, but #ifdef'ing them out of here for now.
00039 #ifdef NOT_USED_HERE
00040 static LLQrec *
00041 newrec(LLQ * Q)
00042 {
00043   LLQrec * new_val;
00044   int i;
00045 
00046   if (Q->free != NULL) {
00047     new_val = Q->free;
00048     Q->free = Q->free->next;
00049     return new_val;
00050   }
00051 
00052   Q->free = (LLQrec *)ats_malloc(RECORD_CHUNK * sizeof(LLQrec));
00053   for (i = 0; i < RECORD_CHUNK; i++)
00054     Q->free[i].next = &Q->free[i + 1];
00055 
00056   Q->free[RECORD_CHUNK - 1].next = NULL;
00057 
00058 
00059   new_val = Q->free;
00060   Q->free = Q->free->next;
00061 
00062   return new_val;
00063 }
00064 
00065 // Not used either ...
00066 static void
00067 freerec(LLQ * Q, LLQrec * rec)
00068 {
00069   rec->next = Q->free;
00070   Q->free = rec;
00071 }
00072 #endif
00073 
00074 LLQ *
00075 create_queue()
00076 {
00077   LLQ * new_val = (LLQ *)ats_malloc(sizeof(LLQ));
00078 
00079   ink_sem_init(&(new_val->sema), 0);
00080   ink_mutex_init(&(new_val->mux), "LLQ::create_queue");
00081 
00082   new_val->head = new_val->tail = new_val->free = NULL;
00083   new_val->len = new_val->highwater = 0;
00084 
00085   return new_val;
00086 }
00087 
00088 // matching delete function, only for empty queue!
00089 void
00090 delete_queue(LLQ * Q)
00091 {
00092   // There seems to have been some ideas of making sure that this queue is
00093   // actually empty ...
00094   //
00095   //    LLQrec * qrec;
00096   ink_sem_destroy(&(Q->sema));
00097   ink_mutex_destroy(&(Q->mux));
00098   ats_free(Q);
00099   return;
00100 }
00101 
00102 int
00103 enqueue(LLQ * Q, void *data)
00104 {
00105   LLQrec * new_val;
00106 
00107   ink_mutex_acquire(&(Q->mux));
00108   new_val = (LLQrec *)ats_malloc(sizeof(LLQrec));
00109   new_val->data = data;
00110   new_val->next = NULL;
00111 
00112   if (Q->tail)
00113     Q->tail->next = new_val;
00114   Q->tail = new_val;
00115 
00116   if (Q->head == NULL)
00117     Q->head = Q->tail;
00118 
00119   Q->len++;
00120   if (Q->len > Q->highwater)
00121     Q->highwater = Q->len;
00122   ink_mutex_release(&(Q->mux));
00123   ink_sem_post(&(Q->sema));
00124   return 1;
00125 }
00126 
00127 uint64_t
00128 queue_len(LLQ * Q)
00129 {
00130   uint64_t len;
00131 
00132   /* Do I really need to grab the lock here? */
00133   /* ink_mutex_acquire(&(Q->mux)); */
00134   len = Q->len;
00135   /* ink_mutex_release(&(Q->mux)); */
00136   return len;
00137 }
00138 
00139 uint64_t
00140 queue_highwater(LLQ * Q)
00141 {
00142   uint64_t highwater;
00143 
00144   /* Do I really need to grab the lock here? */
00145   /* ink_mutex_acquire(&(Q->mux)); */
00146   highwater = Q->highwater;
00147   /* ink_mutex_release(&(Q->mux)); */
00148   return highwater;
00149 }
00150 
00151 
00152 
00153 /*
00154  *---------------------------------------------------------------------------
00155  *
00156  * queue_is_empty
00157  *
00158  *  Is the queue empty?
00159  *
00160  * Results:
00161  *  nonzero if empty, zero else.
00162  *
00163  * Side Effects:
00164  *  none.
00165  *
00166  * Reentrancy:     n/a.
00167  * Thread Safety:  safe.
00168  * Mem Management: n/a.
00169  *
00170  *---------------------------------------------------------------------------
00171  */
00172 int
00173 queue_is_empty(LLQ * Q)
00174 {
00175   uint64_t len;
00176 
00177   len = queue_len(Q);
00178 
00179   if (len)
00180     return 0;
00181   else
00182     return 1;
00183 }
00184 
00185 void *
00186 dequeue(LLQ * Q)
00187 {
00188   LLQrec * rec;
00189   void *d;
00190   ink_sem_wait(&(Q->sema));
00191   ink_mutex_acquire(&(Q->mux));
00192 
00193 
00194   if (Q->head == NULL) {
00195 
00196     ink_mutex_release(&(Q->mux));
00197 
00198     return NULL;
00199   }
00200 
00201   rec = Q->head;
00202 
00203   Q->head = Q->head->next;
00204   if (Q->head == NULL)
00205     Q->tail = NULL;
00206 
00207   d = rec->data;
00208 //freerec(Q, rec);
00209   ats_free(rec);
00210 
00211   Q->len--;
00212   ink_mutex_release(&(Q->mux));
00213 
00214   return d;
00215 }
00216 
00217 
00218 
00219 #ifdef LLQUEUE_MAIN
00220 
00221 void *
00222 testfun(void *unused)
00223 {
00224   int num;
00225   LLQ *Q;
00226 
00227   Q = create_queue();
00228   assert(Q);
00229 
00230   do {
00231     scanf("%d", &num);
00232     if (num == 0) {
00233       printf("DEQUEUE: %d\n", (int) dequeue(Q));
00234     } else if (num == -1) {
00235       printf("queue_is_empty: %d\n", queue_is_empty(Q));
00236     } else {
00237       printf("enqueue: %d\n", num);
00238       enqueue(Q, (void *) num);
00239     }
00240   } while (num >= -1);
00241 
00242   return NULL;
00243 }
00244 
00245 /*
00246  * test harness-- hit Ctrl-C if it blocks or you get tired.
00247  */
00248 void
00249 main()
00250 {
00251   assert(thr_create(NULL, 0, testfun, (void *) NULL, THR_NEW_LWP, NULL) == 0);
00252   while (1) {
00253     ;
00254   }
00255 }
00256 
00257 #endif

Generated by  doxygen 1.7.1