/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "list_wrapper.h" #include "critical_section_wrapper.h" #include "trace.h" namespace webrtc { ListItem::ListItem(const void* item) : next_(0), prev_(0), item_ptr_(item), item_(0) { } ListItem::ListItem(const unsigned int item) : next_(0), prev_(0), item_ptr_(0), item_(item) { } ListItem::~ListItem() { } void* ListItem::GetItem() const { return const_cast(item_ptr_); } unsigned int ListItem::GetUnsignedItem() const { return item_; } ListWrapper::ListWrapper() : critical_section_(CriticalSectionWrapper::CreateCriticalSection()), first_(0), last_(0), size_(0) { } ListWrapper::~ListWrapper() { if (!Empty()) { // TODO (hellner) I'm not sure this loggin is useful. WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1, "Potential memory leak in ListWrapper"); // Remove all remaining list items. while (Erase(First()) == 0) {} } delete critical_section_; } bool ListWrapper::Empty() const { return !first_ && !last_; } unsigned int ListWrapper::GetSize() const { return size_; } int ListWrapper::PushBack(const void* ptr) { ListItem* item = new ListItem(ptr); CriticalSectionScoped lock(*critical_section_); PushBackImpl(item); return 0; } int ListWrapper::PushBack(const unsigned int item_id) { ListItem* item = new ListItem(item_id); CriticalSectionScoped lock(*critical_section_); PushBackImpl(item); return 0; } int ListWrapper::PushFront(const unsigned int item_id) { ListItem* item = new ListItem(item_id); CriticalSectionScoped lock(*critical_section_); PushFrontImpl(item); return 0; } int ListWrapper::PushFront(const void* ptr) { ListItem* item = new ListItem(ptr); CriticalSectionScoped lock(*critical_section_); PushFrontImpl(item); return 0; } int ListWrapper::PopFront() { return Erase(first_); } int ListWrapper::PopBack() { return Erase(last_); } ListItem* ListWrapper::First() const { return first_; } ListItem* ListWrapper::Last() const { return last_; } ListItem* ListWrapper::Next(ListItem* item) const { if(!item) { return 0; } return item->next_; } ListItem* ListWrapper::Previous(ListItem* item) const { if (!item) { return 0; } return item->prev_; } int ListWrapper::Insert(ListItem* existing_previous_item, ListItem* new_item) { if (!new_item) { return -1; } // Allow existing_previous_item to be NULL if the list is empty. // TODO (hellner) why allow this? Keep it as is for now to avoid // breaking API contract. if (!existing_previous_item && !Empty()) { return -1; } CriticalSectionScoped lock(*critical_section_); if (!existing_previous_item) { PushBackImpl(new_item); return 0; } ListItem* next_item = existing_previous_item->next_; new_item->next_ = existing_previous_item->next_; new_item->prev_ = existing_previous_item; existing_previous_item->next_ = new_item; if (next_item) { next_item->prev_ = new_item; } else { last_ = new_item; } size_++; return 0; } int ListWrapper::InsertBefore(ListItem* existing_next_item, ListItem* new_item) { if (!new_item) { return -1; } // Allow existing_next_item to be NULL if the list is empty. // Todo: why allow this? Keep it as is for now to avoid breaking API // contract. if (!existing_next_item && !Empty()) { return -1; } CriticalSectionScoped lock(*critical_section_); if (!existing_next_item) { PushBackImpl(new_item); return 0; } ListItem* previous_item = existing_next_item->prev_; new_item->next_ = existing_next_item; new_item->prev_ = previous_item; existing_next_item->prev_ = new_item; if (previous_item) { previous_item->next_ = new_item; } else { first_ = new_item; } size_++; return 0; } int ListWrapper::Erase(ListItem* item) { if (!item) { return -1; } size_--; ListItem* previous_item = item->prev_; ListItem* next_item = item->next_; if (!previous_item) { if(next_item) { next_item->prev_ = 0; } first_ = next_item; } else { previous_item->next_ = next_item; } if (!next_item) { if(previous_item) { previous_item->next_ = 0; } last_ = previous_item; } else { next_item->prev_ = previous_item; } delete item; return 0; } void ListWrapper::PushBackImpl(ListItem* item) { if (Empty()) { first_ = item; last_ = item; size_++; return; } item->prev_ = last_; last_->next_ = item; last_ = item; size_++; } void ListWrapper::PushFrontImpl(ListItem* item) { if (Empty()) { first_ = item; last_ = item; size_++; return; } item->next_ = first_; first_->prev_ = item; first_ = item; size_++; } } //namespace webrtc