📄 dequeue.cc
字号:
/* * dequeue.{cc,hh} -- double-ended queue template class * Douglas S. J. De Couto * Based on code from Click Vector<> class (vector.{cc,hh}). * * Copyright (c) 2003 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#ifndef CLICK_DEQUEUE_CC#define CLICK_DEQUEUE_CCCLICK_ENDDECLS#include <click/dequeue.hh>CLICK_DECLS#if defined(USE_VMALLOC) && defined(CLICK_LINUXMODULE)extern "C" {# include <linux/vmalloc.h>}#endiftemplate <class T>DEQueue<T>::DEQueue(const DEQueue<T> &o) : _l(0), _n(0), _cap(0), _head(0), _tail(0)#if defined(USE_VMALLOC) && defined(CLICK_LINUXMODULE) , _vmalloc(false)#endif{ *this = o;}template <class T>DEQueue<T>::~DEQueue(){ for (int i = _head, j = 0; j < _n; i = next_i(i), j++) _l[i].~T();#if defined(USE_VMALLOC) && defined(CLICK_LINUXMODULE) if (_vmalloc) vfree(_l); else delete[] (unsigned char *)_l;#else delete[] (unsigned char *)_l;#endif}template <class T> DEQueue<T> &DEQueue<T>::operator=(const DEQueue<T> &o){ if (&o != this) { for (int i = _head, j = 0; j < _n; i = next_i(i), j++) _l[i].~T(); _n = 0; _head = 0; _tail = 0; if (reserve(o._n)) { _n = o._n; for (int i = 0, j = o._head; i < _n; i++, j = o.next_i(j)) new(velt(i)) T(o._l[j]); _tail = _n; } } return *this;}template <class T> DEQueue<T> &DEQueue<T>::assign(int n, const T &e){ resize(0, e); resize(n, e); return *this;}template <class T> boolDEQueue<T>::reserve(int want){ if (want < 0) want = _cap > 0 ? _cap * 2 : 4; if (want <= _cap) return true;#if defined(USE_VMALLOC) && defined(CLICK_LINUXMODULE) // skank hack to allocate more than 128k // may not work at interrupt time, since vmalloc uses GFP_KERNEL# define MAX_KMALLOC 131072 bool old_vmalloc = _vmalloc; T *new_l = 0; int need = want * sizeof(T); if (need <= MAX_KMALLOC) { new_l = (T *)new unsigned char[sizeof(T) * want]; _vmalloc = false; } else { static bool did_warn = false; if (!did_warn) { click_chatter("DEQueue: WARNING using vmalloc(), be careful of re-entry"); did_warn = true; } void *v = vmalloc(need); if (!v) return false; new_l = (T *) v; _vmalloc = true; }#else T *new_l = (T *)new unsigned char[sizeof(T) * want];#endif if (!new_l) return false; for (int i = _head, j = 0; j < _n; j++, i = next_i(i)) { new(velt(new_l, j)) T(_l[i]); _l[i].~T(); }#if defined(USE_VMALLOC) && defined(CLICK_LINUXMODULE) if (old_vmalloc) vfree(_l); else delete[] (unsigned char *)_l;#else delete[] (unsigned char *)_l;#endif _l = new_l; _cap = want; _head = 0; _tail = _n; return true;}template <class T> voidDEQueue<T>::shrink(int nn){ // delete els from back of queue if (nn < _n) { int num_to_del = _n - nn; for ( ; num_to_del > 0; _tail = prev_i(_tail), num_to_del--) _l[prev_i(_tail)].~T(); _n = nn; }}template <class T> voidDEQueue<T>::resize(int nn, const T &e){ // extra/excess els are added/removed to/from back of queue if (nn <= _cap || reserve(nn)) { // construct new els for ( ; _n < nn; _tail = next_i(_tail), _n++) new(velt(_tail)) T(e); // delete excess els for ( ; nn < _n; _tail = prev_i(_tail), _n--) _l[prev_i(_tail)].~T(); }}template <class T> voidDEQueue<T>::swap(DEQueue<T> &o){ T *l = _l; int n = _n; int cap = _cap; int head = _head; int tail = _tail; _l = o._l; _n = o._n; _cap = o._cap; _head = o._head; _tail = o._tail; o._l = l; o._n = n; o._cap = cap; o._head = head; o._tail = tail;}template <class T> inline voidDEQueue<T>::check_rep(){ // pushes go on to back (tail), pops come from front (head). // elements closer to the tail have larger indices in the array // (modulo total size). // _head is index of front // _tail is 1 + index of back, i.e. where next push goes if (!_l) { assert(_n == 0); assert(_cap == 0); assert(_head == 0); assert(_tail == 0); } else { assert(_head >= 0); assert(_head < _cap); assert(_tail >= 0); assert(_tail < _cap); if (_n == _cap) assert(_head == _tail); else assert(_n == (_tail >= _head ? _tail - _head : _cap - _head + _tail)); } }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -