Click
Loading...
Searching...
No Matches
deque.cc
1/*
2 * deque.{cc,hh} -- double-ended queue template class
3 * Eddie Kohler, Douglas S. J. De Couto
4 * Based on code from Click Vector<> class (vector.{cc,hh}).
5 *
6 * Copyright (c) 2003 Massachusetts Institute of Technology
7 * Copyright (c) 2011 Eddie Kohler
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, subject to the conditions
12 * listed in the Click LICENSE file. These conditions include: you must
13 * preserve this copyright notice, and you cannot mention the copyright
14 * holders in advertising related to the Software without their permission.
15 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
16 * notice is a summary of the Click LICENSE file; the license in that file is
17 * legally binding.
18 */
19
20#ifndef CLICK_DEQUE_CC
21#define CLICK_DEQUE_CC
22#include <click/deque.hh>
23CLICK_DECLS
26template <typename AM>
27deque_memory<AM>::~deque_memory()
28{
29 size_type f = naccess(n_);
30 AM::destroy(l_ + head_, f);
31 AM::destroy(l_, n_ - f);
32 CLICK_LFREE(l_, capacity_ * sizeof(type));
33}
34
35template <typename AM>
36void deque_memory<AM>::assign(const deque_memory<AM> &x)
37{
38 if (&x != this) {
39 size_type f = naccess(n_);
40 AM::destroy(l_ + head_, f);
41 AM::destroy(l_, n_ - f);
42 n_ = head_ = 0;
43 if (reserve_and_push(x.n_, false, 0)) {
44 n_ = x.n_;
45 AM::mark_undefined(l_, n_);
46 f = x.naccess(n_);
47 AM::copy(l_, x.l_ + x.head_, f);
48 AM::copy(l_ + f, x.l_, n_ - f);
49 }
50 }
51}
52
53template <typename AM>
54void deque_memory<AM>::assign(size_type n, const type *vp)
55{
56 if (unlikely(need_argument_copy(vp))) {
57 type v_copy(*vp);
58 return assign(n, &v_copy);
59 }
60
61 resize(0, vp);
62 resize(n, vp);
63}
64
65template <typename AM>
66bool deque_memory<AM>::insert(size_type i, const type *vp)
67{
68 assert((unsigned) i <= (unsigned) n_);
69 if (unlikely(need_argument_copy(vp))) {
70 type v_copy(*vp);
71 return insert(i, &v_copy);
72 }
73
74 if (n_ == capacity_ && !reserve_and_push(-1, false, 0))
75 return false;
76 size_type srcpp, dstpp, size;
77 int delta;
78 if (i <= n_ - i) {
79 head_ = prevp(head_);
80 srcpp = head_ + 1;
81 dstpp = head_;
82 size = i;
83 delta = 1;
84 } else {
85 srcpp = head_ + n_ - 1;
86 dstpp = head_ + n_;
87 size = n_ - i;
88 delta = -1;
89 }
90 while (size) {
91 AM::mark_undefined(l_ + canonp(dstpp), 1);
92 AM::move(l_ + canonp(dstpp), l_ + canonp(srcpp), 1);
93 dstpp += delta, srcpp += delta, --size;
94 }
95 AM::mark_undefined(l_ + canonp(dstpp), 1);
96 AM::fill(l_ + canonp(dstpp), 1, vp);
97 ++n_;
98 return true;
99}
100
101template <typename AM>
102int deque_memory<AM>::erase(size_type ai, size_type bi)
103{
104 assert(ai >= bi || (ai >= 0 && (unsigned) bi <= (unsigned) n_));
105 if (ai < bi) {
106 size_type srcpp, dstpp, size;
107 int delta;
108 if (ai < n_ - bi) {
109 srcpp = head_ + ai - 1;
110 dstpp = head_ + bi - 1;
111 size = ai;
112 delta = -1;
113 head_ = canonp(head_ + bi - ai);
114 } else {
115 srcpp = head_ + bi;
116 dstpp = head_ + ai;
117 size = n_ - bi;
118 delta = 1;
119 }
120 while (size) {
121 AM::destroy(l_ + canonp(dstpp), 1);
122 AM::copy(l_ + canonp(dstpp), l_ + canonp(srcpp), 1);
123 dstpp += delta, srcpp += delta, --size;
124 }
125 for (size = bi - ai; size; --size, dstpp += delta) {
126 AM::destroy(l_ + canonp(dstpp), 1);
127 AM::mark_noaccess(l_ + canonp(dstpp), 1);
128 }
129 n_ -= bi - ai;
130 return ai;
131 } else
132 return bi;
133}
134
135template <typename AM>
136bool deque_memory<AM>::reserve_and_push(size_type want, bool isfront, const type *push_vp)
137{
138 if (unlikely(push_vp && need_argument_copy(push_vp))) {
139 type push_v_copy(*push_vp);
140 return reserve_and_push(want, isfront, &push_v_copy);
141 }
142
143 if (want < 0)
144 want = (capacity_ > 0 ? capacity_ * 2 : 4);
145
146 if (want > capacity_) {
147 type *new_l = (type *) CLICK_LALLOC(want * sizeof(type));
148 if (!new_l)
149 return false;
150 AM::mark_noaccess(new_l + n_, want - n_);
151 size_type f = naccess(n_);
152 AM::move(new_l, l_ + head_, f);
153 AM::move(new_l + f, l_, n_ - f);
154 CLICK_LFREE(l_, capacity_ * sizeof(type));
155 l_ = new_l;
156 head_ = 0;
157 capacity_ = want;
158 }
159
160 if (unlikely(push_vp))
161 (isfront ? push_front(push_vp) : push_back(push_vp));
162 return true;
163}
164
165template <typename AM>
166void deque_memory<AM>::resize(size_type n, const type *vp)
167{
168 if (unlikely(need_argument_copy(vp))) {
169 type v_copy(*vp);
170 return resize(n, &v_copy);
171 }
172
173 if (n <= capacity_ || reserve_and_push(n, false, 0)) {
174 assert(n >= 0);
175 if (n < n_)
176 for (size_type p = i2p(n), x = i2p(n_); p != x; p = nextp(p)) {
177 AM::destroy(l_ + p, 1);
178 AM::mark_noaccess(l_ + p, 1);
179 }
180 if (n_ < n)
181 for (size_type p = i2p(n_), x = i2p(n); p != x; p = nextp(p)) {
182 AM::mark_undefined(l_ + p, 1);
183 AM::fill(l_ + p, 1, vp);
184 }
185 n_ = n;
186 }
187}
188
189template <typename AM>
190void deque_memory<AM>::swap(deque_memory<AM> &x)
191{
192 type *l = l_;
193 l_ = x.l_;
194 x.l_ = l;
195
196 size_type head = head_;
197 head_ = x.head_;
198 x.head_ = head;
199
200 size_type n = n_;
201 n_ = x.n_;
202 x.n_ = n;
203
204 size_type capacity = capacity_;
205 capacity_ = x.capacity_;
206 x.capacity_ = capacity;
207}
208
210CLICK_ENDDECLS
211#endif