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

List.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
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 /****************************************************************************
00025 
00026   List.h
00027 
00028   This file implements singly and doubly linked list templates for
00029   homomorphic lists.
00030 
00031   There are two main data structures defined for each list, a link cell
00032   and a list descriptor.  Both are parameterized by template object class.
00033   The link cell and list descriptor are named as follows:
00034 
00035   list type             1-linked list   2-linked list   queue
00036   ---------             -------------   -------------   -----
00037   link cell             SLink<C>        Link<C>         Link<C>
00038   list descriptor       SLL<C>          DLL<C>          Queue<C>
00039 
00040   The list descriptor contains state about the lists (for example: head and
00041   tail pointers) and supports list manipulation methods.
00042 
00043   The link cell strings objects together in the list, and is normally part
00044   of the object itself.  An SLink only points to the next object.  A Link
00045   points both to the previous and the next object in a list.
00046 
00047   The link() method can help find the location of the location of the link
00048   cell within an object, given the location of the link cell in another
00049   object.  This is useful when iterating along lists.
00050 
00051 
00052  ****************************************************************************/
00053 
00054 #ifndef _List_h_
00055 #define _List_h_
00056 
00057 #include <stdint.h>
00058 
00059 #include "ink_assert.h"
00060 #include "ink_queue.h"
00061 #include "Compatability.h"
00062 #include "defalloc.h"
00063 
00064 //
00065 //      Link cell for singly-linked list of objects of type C.
00066 //
00067 template <class C> class SLink {
00068  public:
00069   C *next;
00070   SLink() : next(NULL) {};
00071 };
00072 #define SLINK(_c,_f) class Link##_##_f : public SLink<_c> { public:    \
00073     static _c *& next_link(_c *c) { return c->_f.next; }                \
00074     static const _c * next_link(const _c *c) { return c->_f.next; } \
00075   }; SLink<_c> _f
00076 #define SLINKM(_c,_m,_f) class Link##_##_m##_##_f : public SLink<_c> { public: \
00077     static _c *& next_link(_c *c) { return c->_m._f.next; }             \
00078   };
00079 
00080 //
00081 //      Link cell for doubly-linked list of objects of type C.
00082 //
00083 template <class C> struct Link : public SLink<C> {
00084   C *prev;
00085   Link() : prev(NULL) {}
00086 };
00087 #define LINK(_c,_f) class Link##_##_f : public Link<_c> { public:       \
00088     static _c *& next_link(_c *c) { return c->_f.next; }                \
00089     static _c *& prev_link(_c *c) { return c->_f.prev; }                \
00090     static const _c * next_link(const _c *c) { return c->_f.next; }     \
00091     static const _c * prev_link(const _c *c) { return c->_f.prev; }     \
00092   }; Link<_c> _f
00093 #define LINKM(_c,_m,_f) class Link##_##_m##_##_f : public Link<_c> { public:  \
00094     static _c *& next_link(_c *c) { return c->_m._f.next; }             \
00095     static _c *& prev_link(_c *c) { return c->_m._f.prev; }             \
00096   };
00097 #define LINK_FORWARD_DECLARATION(_c,_f) class Link##_##_c##_##_f : public Link<_c> { public:     \
00098     static _c *& next_link(_c *c);                                      \
00099     static _c *& prev_link(_c *c);                                      \
00100   };
00101 #define LINK_DEFINITION(_c,_f)  \
00102   inline _c *& Link##_##_c##_##_f::next_link(_c *c) { return c->_f.next; } \
00103   inline _c *& Link##_##_c##_##_f::prev_link(_c *c) { return c->_f.prev; } \
00104 
00105 //
00106 //      List descriptor for singly-linked list of objects of type C.
00107 //
00108 template <class C, class L = typename C::Link_link> class SLL {
00109  public:
00110   C *head;
00111   bool empty() const { return head == NULL; }
00112   void push(C *e);
00113   C *pop();
00114   void clear() { head = NULL; }
00115   C *& next(C *e) { return L::next_link(e); }
00116   const C * next(const C *e) const { return L::next_link(e); }
00117 
00118   SLL() : head(NULL) {}
00119   SLL(C *c) : head(c) {}
00120 };
00121 #define SList(_c, _f)  SLL<_c, _c::Link##_##_f>
00122 #define SListM(_c, _m, _ml, _l) SLL<_c, _c::Link##_##_ml##_##_l>
00123 #define forl_LL(_c, _p, _l) for (_c *_p = (_l).head; _p; _p = (_l).next(_p))
00124 
00125 template <class C, class L> inline void
00126 SLL<C,L>::push(C *e) {
00127   next(e) = head;
00128   head = e;
00129 }
00130 
00131 template <class C, class L> inline C *
00132 SLL<C,L>::pop() {
00133   C *ret = head;
00134   if (ret) {
00135     head = next(ret);
00136     next(ret) = NULL;
00137   }
00138   return ret;
00139 }
00140 
00141 //
00142 //      List descriptor for doubly-linked list of objects of type C.
00143 //
00144 template <class C, class L = typename C::Link_link> struct DLL {
00145   C *head;
00146   bool empty() const { return head == NULL; }
00147   void push(C *e);
00148   C *pop();
00149   void remove(C *e);
00150   void insert(C *e, C *after);
00151   bool in(C *e) { return head == e || next(e) || prev(e); }
00152   void clear() { head = NULL; }
00153   static C *&next(C *e) { return reinterpret_cast<C*&>(L::next_link(e)); }
00154   static C *&prev(C *e) { return reinterpret_cast<C*&>(L::prev_link(e)); }
00155   static C const* next(const C *e) { return L::next_link(e); }
00156   static C const* prev(const C *e) { return L::prev_link(e); }
00157 
00158   DLL() : head(NULL) {}
00159 };
00160 #define DList(_c, _f)  DLL<_c, _c::Link##_##_f>
00161 #define DListM(_c, _m, _ml, _l) DLL<_c, _c::Link##_##_ml##_##_l>
00162 
00163 template <class C, class L> inline void
00164 DLL<C,L>::push(C *e) {
00165   if (head)
00166     prev(head) = e;
00167   next(e) = head;
00168   head = e;
00169 }
00170 
00171 template <class C, class L> inline void
00172 DLL<C,L>::remove(C *e) {
00173   if (!head) return;
00174   if (e == head) head = next(e);
00175   if (prev(e)) next(prev(e)) = next(e);
00176   if (next(e)) prev(next(e)) = prev(e);
00177   prev(e) = NULL;
00178   next(e) = NULL;
00179 }
00180 
00181 template <class C, class L> inline C *
00182 DLL<C,L>::pop() {
00183   C *ret = head;
00184   if (ret) {
00185     head = next(ret);
00186     if (head)
00187       prev(head) = NULL;
00188     next(ret) = NULL;
00189     return ret;
00190   } else
00191     return NULL;
00192 }
00193 
00194 template <class C, class L> inline void
00195 DLL<C,L>::insert(C *e, C *after) {
00196   if (!after) { push(e); return; }
00197   prev(e) = after;
00198   next(e) = next(after);
00199   next(after) = e;
00200   if (next(e)) prev(next(e)) = e;
00201 }
00202 
00203 //
00204 //      List descriptor for queue of objects of type C.
00205 //
00206 template <class C, class L = typename C::Link_link> class Queue : public DLL<C,L> {
00207  public:
00208   using DLL<C,L>::head;
00209   C *tail;
00210   void push(C *e);
00211   C *pop();
00212   void enqueue(C *e);
00213   void in_or_enqueue(C *e);
00214   C *dequeue();
00215   void remove(C *e);
00216   void insert(C *e, C *after);
00217   void append(Queue<C,L> q);
00218   void append(DLL<C,L> q);
00219   void clear() { head = NULL; tail = NULL; }
00220   bool empty() const { return head == NULL; }
00221 
00222   Queue() : tail(NULL) {}
00223 };
00224 #define Que(_c, _f) Queue<_c, _c::Link##_##_f>
00225 #define QueM(_c, _m, _mf, _f) Queue<_c, _c::Link##_##_mf##_##_f>
00226 
00227 template <class C, class L> inline void
00228 Queue<C,L>::push(C *e) {
00229   DLL<C,L>::push(e);
00230   if (!tail) tail = head;
00231 }
00232 
00233 template <class C, class L> inline C *
00234 Queue<C,L>::pop() {
00235   C *ret = DLL<C,L>::pop();
00236   if (!head) tail = NULL;
00237   return ret;
00238 }
00239 
00240 template <class C, class L> inline void
00241 Queue<C,L>::insert(C *e, C *after) {
00242   DLL<C,L>::insert(e, after);
00243   if (!tail)
00244     tail = head;
00245   else if (tail == after)
00246     tail = e;
00247 }
00248 
00249 template <class C, class L> inline void
00250 Queue<C,L>::remove(C *e) {
00251   if (tail == e)
00252     tail = (C*)this->prev(e);
00253   DLL<C,L>::remove(e);
00254 }
00255 
00256 template <class C, class L> inline void
00257 Queue<C,L>::append(DLL<C,L> q) {
00258   C *qtail = q.head;
00259   if (qtail)
00260     while (this->next(qtail))
00261       qtail = this->next(qtail);
00262   if (!head) {
00263     head = q.head;
00264     tail = qtail;
00265   } else {
00266     if (q.head) {
00267       this->next(tail) = q.head;
00268       this->prev(q.head) = tail;
00269       tail = qtail;
00270     }
00271   }
00272 }
00273 
00274 template <class C, class L> inline void
00275 Queue<C,L>::append(Queue<C,L> q) {
00276   if (!head) {
00277     head = q.head;
00278     tail = q.tail;
00279   } else {
00280     if (q.head) {
00281       this->next(tail) = q.head;
00282       this->prev(q.head) = tail;
00283       tail = q.tail;
00284     }
00285   }
00286 }
00287 
00288 template <class C, class L> inline void
00289 Queue<C,L>::enqueue(C *e) {
00290   if (tail)
00291     insert(e, tail);
00292   else
00293     push(e);
00294 }
00295 
00296 template <class C, class L> inline void
00297 Queue<C,L>::in_or_enqueue(C *e) {
00298   if (!this->in(e)) enqueue(e);
00299 }
00300 
00301 template <class C, class L> inline C *
00302 Queue<C,L>::dequeue() {
00303   return pop();
00304 }
00305 
00306 //
00307 // Adds sorting, but requires that elements implement <
00308 //
00309 
00310 template<class C, class L = typename C::Link_link> struct SortableQueue: public Queue<C,L>
00311 {
00312   using DLL<C,L>::head;
00313   using Queue<C,L>::tail;
00314   void sort() {
00315     if (!head) return;
00316     bool clean = false;
00317     while (!clean) {
00318       clean = true;
00319       C *v = head;
00320       C *n = this->next(head);
00321       while (n) {
00322         C *f = this->next(n);
00323         if (*n < *v) {
00324           clean = false;
00325           // swap 'em
00326           if (head == v)
00327             head = n;
00328           if (tail == n)
00329             tail = v;
00330           // fix prev (p)
00331           C *p = this->prev(v);
00332           if (p) {
00333             this->next(p) = n;
00334             this->prev(n) = p;
00335           } else
00336             this->prev(n) = NULL;
00337           // fix follow (f)
00338           if (f) {
00339             this->prev(f) = v;
00340             this->next(v) = f;
00341           } else
00342             this->next(v) = NULL;
00343           // fix interior
00344           this->prev(v) = n;
00345           this->next(n) = v;
00346         } else
00347           v = n;
00348         n = f;
00349       }
00350     }
00351   }
00352 };
00353 #define SortableQue(_c, _l) SortableQueue<_c, _c::Link##_##_f>
00354 
00355 //
00356 // Adds counting to the Queue
00357 //
00358 
00359 template <class C, class L = typename C::Link_link> struct CountQueue : public Queue<C,L> {
00360   int size;
00361   inline CountQueue(void) : size(0) {}
00362   inline void push(C *e);
00363   inline C *pop();
00364   inline void enqueue(C *e);
00365   inline C *dequeue();
00366   inline void remove(C *e);
00367   inline void insert(C *e, C *after);
00368   inline void append(CountQueue<C,L> &q);
00369   inline void append_clear(CountQueue<C,L> &q);
00370 };
00371 #define CountQue(_c, _f) CountQueue<_c, _c::Link##_##_f>
00372 #define CountQueM(_c, _m, _mf, _f) CountQueue<_c, _c::Link##_##_mf##_##_f>
00373 
00374 template <class C, class L> inline void
00375 CountQueue<C,L>::push(C *e) {
00376   Queue<C,L>::push(e);
00377   size++;
00378 }
00379 
00380 template <class C, class L> inline C *
00381 CountQueue<C,L>::pop() {
00382   C *ret = Queue<C,L>::pop();
00383   if (ret)
00384     size--;
00385   return ret;
00386 }
00387 
00388 template <class C, class L> inline void
00389 CountQueue<C,L>::remove(C *e) {
00390   Queue<C,L>::remove(e);
00391   size--;
00392 }
00393 
00394 template <class C, class L> inline void
00395 CountQueue<C,L>::enqueue(C *e) {
00396   Queue<C,L>::enqueue(e);
00397   size++;
00398 }
00399 
00400 template <class C, class L> inline C *
00401 CountQueue<C,L>::dequeue() {
00402   return pop();
00403 }
00404 
00405 template <class C, class L> inline void
00406 CountQueue<C,L>::insert(C *e, C *after) {
00407   Queue<C,L>::insert(e, after);
00408   size++;
00409 }
00410 
00411 template <class C, class L> inline void
00412 CountQueue<C,L>::append(CountQueue<C,L> &q) {
00413   Queue<C,L>::append(q);
00414   size += q.size;
00415 }
00416 
00417 template <class C, class L> inline void
00418 CountQueue<C,L>::append_clear(CountQueue<C,L> &q) {
00419   append(q);
00420   q.head = q.tail = 0;
00421   q.size = 0;
00422 }
00423 
00424 //
00425 // List using cons cells
00426 //
00427 
00428 template <class C, class A = DefaultAlloc>
00429 struct ConsCell {
00430   C             car;
00431   ConsCell      *cdr;
00432   ConsCell(C acar, ConsCell *acdr) : car(acar), cdr(acdr) {}
00433   ConsCell(C acar) : car(acar), cdr(NULL) {}
00434   ConsCell(ConsCell *acdr) : cdr(acdr) {}
00435   static void *operator new(size_t size) { return A::alloc(size); }
00436   static void operator delete(void *p, size_t /* size ATS_UNUSED */) { A::free(p); }
00437 };
00438 
00439 template <class C, class A = DefaultAlloc>
00440 struct List {
00441   ConsCell<C,A> *head;
00442   C first() { if (head) return head->car; else return 0; }
00443   C car() { return first(); }
00444   ConsCell<C,A> *rest() { if (head) return head->cdr; else return 0; }
00445   ConsCell<C,A> *cdr() { return rest(); }
00446   void push(C a) { head = new ConsCell<C,A>(a, head); }
00447   void push() { head = new ConsCell<C,A>(head); }
00448   C pop() { C a = car(); head = cdr(); return a; }
00449   void clear() { head = NULL; }
00450   void reverse();
00451   List(C acar) : head(new ConsCell<C,A>(acar)) {}
00452   List(C a, C b) : head(new ConsCell<C,A>(a, new ConsCell<C,A>(b))) {}
00453   List(C a, C b, C c) : head(new ConsCell<C,A>(a, new ConsCell<C,A>(b, new ConsCell<C,A>(c)))) {}
00454   List() : head(0) {}
00455 };
00456 #define forc_List(_c, _p, _l) if ((_l).head) for (_c *_p  = (_l).head; _p; _p = _p->cdr)
00457 
00458 template <class C,class A> void
00459 List<C,A>::reverse() {
00460   ConsCell<C,A> *n, *t;
00461   for (ConsCell<C,A> *p = head; p; p = n) {
00462     n = p->cdr;
00463     p->cdr = t;
00464     t = p;
00465   }
00466   head = t;
00467 }
00468 
00469 //
00470 // Atomic lists
00471 // 
00472 
00473 template<class C, class L = typename C::Link_link> struct AtomicSLL
00474 {
00475   void push(C * c) { ink_atomiclist_push(&al, c); }
00476   C *pop() { return (C *) ink_atomiclist_pop(&al); }
00477   C *popall() { return (C *) ink_atomiclist_popall(&al); }
00478   bool empty() { return INK_ATOMICLIST_EMPTY(al); }
00479 
00480   /*
00481    * WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00482    * only if only one thread is doing pops it is possible to have a "remove"
00483    * which only that thread can use as well.
00484    * WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00485    */
00486   C *remove(C * c) { return (C *) ink_atomiclist_remove(&al, c); }
00487   C *head() { return (C *) TO_PTR(FREELIST_POINTER(al.head)); }
00488   C *next(C * c) { return (C *) TO_PTR(c); }
00489 
00490   InkAtomicList al;
00491 
00492   AtomicSLL();
00493 };
00494 
00495 #define ASLL(_c, _l) AtomicSLL<_c, _c::Link##_##_l>
00496 #define ASLLM(_c, _m, _ml, _l) AtomicSLL<_c, _c::Link##_##_ml##_##_l>
00497 
00498 template<class C, class L> inline AtomicSLL<C,L>::AtomicSLL() {
00499   ink_atomiclist_init(&al, "AtomicSLL", (uint32_t)(uintptr_t)&L::next_link((C*)0));
00500 }
00501 
00502 #endif  /*_List_h_*/

Generated by  doxygen 1.7.1