Home | History | Annotate | Download | only in source
      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