1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "list_wrapper.h"
12
13 #include "critical_section_wrapper.h"
14 #include "trace.h"
15
16 namespace webrtc {
ListItem(const void * item)17 ListItem::ListItem(const void* item)
18 : next_(0),
19 prev_(0),
20 item_ptr_(item),
21 item_(0)
22 {
23 }
24
ListItem(const unsigned int item)25 ListItem::ListItem(const unsigned int item)
26 : next_(0),
27 prev_(0),
28 item_ptr_(0),
29 item_(item)
30 {
31 }
32
~ListItem()33 ListItem::~ListItem()
34 {
35 }
36
GetItem() const37 void* ListItem::GetItem() const
38 {
39 return const_cast<void*>(item_ptr_);
40 }
41
GetUnsignedItem() const42 unsigned int ListItem::GetUnsignedItem() const
43 {
44 return item_;
45 }
46
ListWrapper()47 ListWrapper::ListWrapper()
48 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()),
49 first_(0),
50 last_(0),
51 size_(0)
52 {
53 }
54
~ListWrapper()55 ListWrapper::~ListWrapper()
56 {
57 if (!Empty())
58 {
59 // TODO (hellner) I'm not sure this loggin is useful.
60 WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1,
61 "Potential memory leak in ListWrapper");
62 // Remove all remaining list items.
63 while (Erase(First()) == 0)
64 {}
65 }
66 delete critical_section_;
67 }
68
Empty() const69 bool ListWrapper::Empty() const
70 {
71 return !first_ && !last_;
72 }
73
GetSize() const74 unsigned int ListWrapper::GetSize() const
75 {
76 return size_;
77 }
78
PushBack(const void * ptr)79 int ListWrapper::PushBack(const void* ptr)
80 {
81 ListItem* item = new ListItem(ptr);
82 CriticalSectionScoped lock(critical_section_);
83 PushBackImpl(item);
84 return 0;
85 }
86
PushBack(const unsigned int item_id)87 int ListWrapper::PushBack(const unsigned int item_id)
88 {
89 ListItem* item = new ListItem(item_id);
90 CriticalSectionScoped lock(critical_section_);
91 PushBackImpl(item);
92 return 0;
93 }
94
PushFront(const unsigned int item_id)95 int ListWrapper::PushFront(const unsigned int item_id)
96 {
97 ListItem* item = new ListItem(item_id);
98 CriticalSectionScoped lock(critical_section_);
99 PushFrontImpl(item);
100 return 0;
101 }
102
PushFront(const void * ptr)103 int ListWrapper::PushFront(const void* ptr)
104 {
105 ListItem* item = new ListItem(ptr);
106 CriticalSectionScoped lock(critical_section_);
107 PushFrontImpl(item);
108 return 0;
109 }
110
PopFront()111 int ListWrapper::PopFront()
112 {
113 return Erase(first_);
114 }
115
PopBack()116 int ListWrapper::PopBack()
117 {
118 return Erase(last_);
119 }
120
First() const121 ListItem* ListWrapper::First() const
122 {
123 return first_;
124 }
125
Last() const126 ListItem* ListWrapper::Last() const
127 {
128 return last_;
129 }
130
Next(ListItem * item) const131 ListItem* ListWrapper::Next(ListItem* item) const
132 {
133 if(!item)
134 {
135 return 0;
136 }
137 return item->next_;
138 }
139
Previous(ListItem * item) const140 ListItem* ListWrapper::Previous(ListItem* item) const
141 {
142 if (!item)
143 {
144 return 0;
145 }
146 return item->prev_;
147 }
148
Insert(ListItem * existing_previous_item,ListItem * new_item)149 int ListWrapper::Insert(ListItem* existing_previous_item, ListItem* new_item)
150 {
151 if (!new_item)
152 {
153 return -1;
154 }
155 // Allow existing_previous_item to be NULL if the list is empty.
156 // TODO (hellner) why allow this? Keep it as is for now to avoid
157 // breaking API contract.
158 if (!existing_previous_item && !Empty())
159 {
160 return -1;
161 }
162 CriticalSectionScoped lock(critical_section_);
163 if (!existing_previous_item)
164 {
165 PushBackImpl(new_item);
166 return 0;
167 }
168 ListItem* next_item = existing_previous_item->next_;
169 new_item->next_ = existing_previous_item->next_;
170 new_item->prev_ = existing_previous_item;
171 existing_previous_item->next_ = new_item;
172 if (next_item)
173 {
174 next_item->prev_ = new_item;
175 }
176 else
177 {
178 last_ = new_item;
179 }
180 size_++;
181 return 0;
182 }
183
InsertBefore(ListItem * existing_next_item,ListItem * new_item)184 int ListWrapper::InsertBefore(ListItem* existing_next_item,
185 ListItem* new_item)
186 {
187 if (!new_item)
188 {
189 return -1;
190 }
191 // Allow existing_next_item to be NULL if the list is empty.
192 // Todo: why allow this? Keep it as is for now to avoid breaking API
193 // contract.
194 if (!existing_next_item && !Empty())
195 {
196 return -1;
197 }
198 CriticalSectionScoped lock(critical_section_);
199 if (!existing_next_item)
200 {
201 PushBackImpl(new_item);
202 return 0;
203 }
204
205 ListItem* previous_item = existing_next_item->prev_;
206 new_item->next_ = existing_next_item;
207 new_item->prev_ = previous_item;
208 existing_next_item->prev_ = new_item;
209 if (previous_item)
210 {
211 previous_item->next_ = new_item;
212 }
213 else
214 {
215 first_ = new_item;
216 }
217 size_++;
218 return 0;
219 }
220
Erase(ListItem * item)221 int ListWrapper::Erase(ListItem* item)
222 {
223 if (!item)
224 {
225 return -1;
226 }
227 size_--;
228 ListItem* previous_item = item->prev_;
229 ListItem* next_item = item->next_;
230 if (!previous_item)
231 {
232 if(next_item)
233 {
234 next_item->prev_ = 0;
235 }
236 first_ = next_item;
237 }
238 else
239 {
240 previous_item->next_ = next_item;
241 }
242 if (!next_item)
243 {
244 if(previous_item)
245 {
246 previous_item->next_ = 0;
247 }
248 last_ = previous_item;
249 }
250 else
251 {
252 next_item->prev_ = previous_item;
253 }
254 delete item;
255 return 0;
256 }
257
PushBackImpl(ListItem * item)258 void ListWrapper::PushBackImpl(ListItem* item)
259 {
260 if (Empty())
261 {
262 first_ = item;
263 last_ = item;
264 size_++;
265 return;
266 }
267
268 item->prev_ = last_;
269 last_->next_ = item;
270 last_ = item;
271 size_++;
272 }
273
PushFrontImpl(ListItem * item)274 void ListWrapper::PushFrontImpl(ListItem* item)
275 {
276 if (Empty())
277 {
278 first_ = item;
279 last_ = item;
280 size_++;
281 return;
282 }
283
284 item->next_ = first_;
285 first_->prev_ = item;
286 first_ = item;
287 size_++;
288 }
289 } //namespace webrtc
290