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