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 16namespace webrtc { 17ListItem::ListItem(const void* item) 18 : next_(0), 19 prev_(0), 20 item_ptr_(item), 21 item_(0) 22{ 23} 24 25ListItem::ListItem(const unsigned int item) 26 : next_(0), 27 prev_(0), 28 item_ptr_(0), 29 item_(item) 30{ 31} 32 33ListItem::~ListItem() 34{ 35} 36 37void* ListItem::GetItem() const 38{ 39 return const_cast<void*>(item_ptr_); 40} 41 42unsigned int ListItem::GetUnsignedItem() const 43{ 44 return item_; 45} 46 47ListWrapper::ListWrapper() 48 : critical_section_(CriticalSectionWrapper::CreateCriticalSection()), 49 first_(0), 50 last_(0), 51 size_(0) 52{ 53} 54 55ListWrapper::~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 69bool ListWrapper::Empty() const 70{ 71 return !first_ && !last_; 72} 73 74unsigned int ListWrapper::GetSize() const 75{ 76 return size_; 77} 78 79int 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 87int 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 95int 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 103int 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 111int ListWrapper::PopFront() 112{ 113 return Erase(first_); 114} 115 116int ListWrapper::PopBack() 117{ 118 return Erase(last_); 119} 120 121ListItem* ListWrapper::First() const 122{ 123 return first_; 124} 125 126ListItem* ListWrapper::Last() const 127{ 128 return last_; 129} 130 131ListItem* ListWrapper::Next(ListItem* item) const 132{ 133 if(!item) 134 { 135 return 0; 136 } 137 return item->next_; 138} 139 140ListItem* ListWrapper::Previous(ListItem* item) const 141{ 142 if (!item) 143 { 144 return 0; 145 } 146 return item->prev_; 147} 148 149int 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 184int 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 221int 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 258void 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 274void 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