- Main Page
- Related Pages
- Classes
- Files
- Examples

- File List
- File Members

# skype-ref-list.cpp

Go to the documentation of this file.

    00001
    00002 #include "skype-ref-list.h"
    00003 #include "skype-object.h"
    00004
    00005 SEReference empty;
    00006
    00007 /** \cond INTERNAL */
    00008 class SERefList::Element
    00009 {
    00010 public:
    00011         Element();
    00012
    00013 public:
    00014         SEReference reference;
    00015         Element* next;
    00016 };
    00017
    00018 class SERefList::Data
    00019 {
    00020 public:
    00021         unsigned int ref;
    00022         Element* list;
    00023         Element* last;
    00024         bool dirty;
    00025         Element** quick_list;
    00026         size_t size;
    00027         SEMutex lock;
    00028 };
    00029
    00030 SERefList::Element::Element()
    00031                 :next(0)
    00032 {
    00033
    00034 }
    00035 /** \endcond */
    00036
    00037 SERefList::SERefList()
    00038                 :d(0)
    00039 {
    00040 }
    00041
    00042 SERefList::SERefList(const SERefList& sl)
    00043                 :d(0)
    00044 {
    00045         *this = sl;
    00046 }
    00047
    00048 SERefList::~SERefList()
    00049 {
    00050         d_unref();
    00051 }
    00052
    00053 /** \cond INTERNAL */
    00054 void SERefList::init()
    00055 {
    00056         if (d)
    00057                 return;
    00058
    00059         d = new Data();
    00060         d->ref = 1;
    00061         d->list = 0;
    00062         d->dirty = true;
    00063         d->size = 0;
    00064         d->quick_list = 0;
    00065 }
    00066 /** \endcond */
    00067
    00068 SERefList& SERefList::append(const SEReference& ref)
    00069 {
    00070         detach();
    00071
    00072         if (0 == d) {
    00073                 init();
    00074
    00075                 d->list = new Element();
    00076                 d->list->reference = ref;
    00077                 d->last = d->list;
    00078         } else {
    00079                 d->dirty = true;
    00080                 d->last->next = new Element();
    00081                 d->last->next->reference = ref;
    00082                 d->last = d->last->next;
    00083         }
    00084
    00085         return *this;
    00086 }
    00087
    00088 SEReference& SERefList::peek()
    00089 {
    00090         detach();
    00091
    00092         if (0 == d)
    00093                 return empty;
    00094
    00095         d->dirty = true;
    00096
    00097         SEReference& ret = d->list->reference;
    00098
    00099         Element* next = d->list->next;
    00100
    00101         delete d->list;
    00102
    00103         d->list = next;
    00104
    00105         if (0 == d->list) {
    00106                 delete d;
    00107                 d = 0;
    00108         }
    00109
    00110         return ret;
    00111 }
    00112
    00113 size_t SERefList::size() const
    00114 {
    00115         if (0 == d)
    00116                 return 0;
    00117
    00118         if (!d->dirty)
    00119                 return d->size;
    00120
    00121         if (d->quick_list)
    00122                 delete[] d->quick_list;
    00123
    00124         // first pass - count elements
    00125         d->size = 0;
    00126
    00127         Element* e = d->list;
    00128
    00129         do {
    00130                 d->size++;
    00131                 e = e->next;
    00132         } while (e);
    00133
    00134         // second pass - fill quick access vector
    00135         d->quick_list = new Element*[d->size];
    00136
    00137         e = d->list;
    00138         size_t n = 0;
    00139
    00140         while (e) {
    00141                 d->quick_list[n++] = e;
    00142
    00143                 e = e->next;
    00144         }
    00145
    00146         d->dirty = false;
    00147
    00148         return d->size;
    00149 }
    00150
    00151 SEReference &SERefList::operator[](size_t n) const
    00152 {
    00153         if ((0 == d) || (n >= size()))
    00154                 return const_cast<SEReference &>(empty);
    00155
    00156         return d->quick_list[n]->reference;
    00157 }
    00158
    00159 SERefList& SERefList::operator=(const SERefList& sl)
    00160 {
    00161         d_unref();
    00162
    00163         d = sl.d;
    00164
    00165         d_ref();
    00166
    00167         return *this;
    00168 }
    00169
    00170 /** \cond INTERNAL */
    00171 void SERefList::d_ref()
    00172 {
    00173         if (0 == d)
    00174                 return;
    00175
    00176         d->lock.Acquire();
    00177
    00178         d->ref++;
    00179
    00180         d->lock.Release();
    00181 }
    00182
    00183 void SERefList::d_unref()
    00184 {
    00185         if (0 == d)
    00186                 return;
    00187
    00188         SEMutex* lock = &d->lock;
    00189
    00190         lock->Acquire();
    00191
    00192         if (d->ref > 1)
    00193                 d->ref--;
    00194         else {
    00195                 Element* tmp = d->list;
    00196
    00197                 while (tmp) {
    00198                         Element* next = tmp->next;
    00199
    00200                         delete tmp;
    00201
    00202                         tmp = next;
    00203                 }
    00204
    00205                 if (d->quick_list)
    00206                         delete[] d->quick_list;
    00207
    00208         Data* keep = d;
    00209                 d = 0;
    00210
    00211                 lock->Release();
    00212                 delete keep;
    00213
    00214
    00215                 return;
    00216         }
    00217
    00218         lock->Release();
    00219 }
    00220
    00221 void SERefList::detach()
    00222 {
    00223         if (0 == d)
    00224                 return;
    00225
    00226         d->lock.Acquire();
    00227
    00228         if (1 != d->ref) {
    00229
    00230                 Data* d_new = new Data();
    00231
    00232                 d_new->ref = 1;
    00233                 d_new->dirty = true;
    00234                 d_new->quick_list = 0;
    00235
    00236                 d_new->list = new Element;
    00237                 d_new->list->reference = d->list->reference;
    00238
    00239                 Element* from = d->list->next;
    00240                 Element* to = d_new->list;
    00241
    00242                 while (from) {
    00243                         to->next = new Element;
    00244                         to->next->reference = from->reference;
    00245
    00246                         to = to->next;
    00247                         from = from->next;
    00248                 }
    00249
    00250                 d_new->last = to;
    00251
    00252                 d->lock.Release();
    00253
    00254                 d_unref();
    00255
    00256                 d = d_new;
    00257
    00258                 return;
    00259         }
    00260
    00261         d->lock.Release();
    00262 }
    00263 /** \endcond */
    00264
    00265 void SERefList::resize(const unsigned int new_size)
    00266 {
    00267         if (size() == new_size) return;
    00268         if (new_size == 0) {
    00269                 clear();
    00270                 return;
    00271         }
    00272
    00273         detach();
    00274         uint cursize = size(); //updates quick_list
    00275
    00276         if (cursize > new_size) { //shrink
    00277
    00278                 Element* elem_last = d->quick_list[new_size-1];
    00279                 elem_last->next = 0;
    00280                 d->last = elem_last;
    00281
    00282                 for (uint n = new_size; n < cursize; n++) {
    00283                         delete d->quick_list[n];
    00284                 }
    00285
    00286         } else {   //grow
    00287
    00288                 while (cursize < new_size) {
    00289                         if (0 == d) {
    00290                                 init();
    00291                                 d->list = new Element();
    00292                                 d->list->reference = SEReference();
    00293                                 d->last = d->list;
    00294                         } else {
    00295                                 d->last->next = new Element();
    00296                                 d->last->next->reference = SEReference();
    00297                                 d->last = d->last->next;
    00298                         }
    00299
    00300                         cursize++;
    00301                 }
    00302         }
    00303
    00304         d->dirty = true;
    00305 }
    00306
    00307 int SERefList::find_pos(const SEReference & val)
    00308 {
    00309         int len = size();
    00310         for (int n = 0; n < len; n++) {
    00311                 if (d->quick_list[n]->reference == val) {
    00312                         return n;
    00313                 }
    00314         }
    00315
    00316         return -1;
    00317 }
    00318
    00319 bool SERefList::contains(const SEReference & val)
    00320 {
    00321         return (find_pos(val) >= 0);
    00322 }
    00323
    00324 bool SERefList::remove_val(const SEReference & val)
    00325 {
    00326         int pos = find_pos(val);
    00327         if (pos >= 0)
    00328                 return remove_pos(pos);
    00329
    00330         return false;
    00331 }
    00332
    00333 bool SERefList::remove_pos(const unsigned int pos)
    00334 {
    00335         if (0 == d || pos >= size()) return false;
    00336
    00337         detach();
    00338         uint cursize = size();//updates quick_list
    00339
    00340         Element* elem_del = d->quick_list[pos];
    00341         Element* elem_next = elem_del->next;
    00342         Element* elem_prev = pos == 0 ? 0 : d->quick_list[pos-1];
    00343
    00344         if (pos == 0) {//first
    00345                 delete elem_del;
    00346                 d->list = elem_next;
    00347         } else if (pos == cursize -1) { //last
    00348                 delete elem_del;
    00349                 elem_prev->next = 0;
    00350                 d->last = elem_prev;
    00351         } else {
    00352                 delete elem_del;
    00353                 elem_prev->next = elem_next;
    00354         }
    00355
    00356         d->dirty = true;
    00357         if (0 == d->list) {
    00358                 delete d;
    00359                 d = 0;
    00360         }
    00361
    00362         return true;
    00363 }
    00364
    00365 void SERefList::clear()
    00366 {
    00367         if (0 == d) {
    00368                 return;
    00369         }
    00370
    00371         detach();
    00372
    00373         for (uint n = 0; n < size(); n++) {
    00374                 delete d->quick_list[n];
    00375         }
    00376
    00377         if (d->quick_list)
    00378                 delete[] d->quick_list;
    00379
    00380         delete d;
    00381
    00382         d = 0;
    00383 }

All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

(c) Skype Technologies S.A. Confidential/Proprietary

Last updated: Fri Mar 16 2012