290 lines
5.5 KiB
C++
290 lines
5.5 KiB
C++
/*
|
|
* 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<void*>(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
|