sanitizer_list.h revision 1.1.1.4
1//===-- sanitizer_list.h ----------------------------------------*- C++ -*-===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file contains implementation of a list class to be used by
9// ThreadSanitizer, etc run-times.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef SANITIZER_LIST_H
14#define SANITIZER_LIST_H
15
16#include "sanitizer_internal_defs.h"
17
18namespace __sanitizer {
19
20// Intrusive singly-linked list with size(), push_back(), push_front()
21// pop_front(), append_front() and append_back().
22// This class should be a POD (so that it can be put into TLS)
23// and an object with all zero fields should represent a valid empty list.
24// This class does not have a CTOR, so clear() should be called on all
25// non-zero-initialized objects before using.
26template<class Item>
27struct IntrusiveList {
28  friend class Iterator;
29
30  void clear() {
31    first_ = last_ = nullptr;
32    size_ = 0;
33  }
34
35  bool empty() const { return size_ == 0; }
36  uptr size() const { return size_; }
37
38  void push_back(Item *x) {
39    if (empty()) {
40      x->next = nullptr;
41      first_ = last_ = x;
42      size_ = 1;
43    } else {
44      x->next = nullptr;
45      last_->next = x;
46      last_ = x;
47      size_++;
48    }
49  }
50
51  void push_front(Item *x) {
52    if (empty()) {
53      x->next = nullptr;
54      first_ = last_ = x;
55      size_ = 1;
56    } else {
57      x->next = first_;
58      first_ = x;
59      size_++;
60    }
61  }
62
63  void pop_front() {
64    CHECK(!empty());
65    first_ = first_->next;
66    if (!first_)
67      last_ = nullptr;
68    size_--;
69  }
70
71  Item *front() { return first_; }
72  const Item *front() const { return first_; }
73  Item *back() { return last_; }
74  const Item *back() const { return last_; }
75
76  void append_front(IntrusiveList<Item> *l) {
77    CHECK_NE(this, l);
78    if (l->empty())
79      return;
80    if (empty()) {
81      *this = *l;
82    } else if (!l->empty()) {
83      l->last_->next = first_;
84      first_ = l->first_;
85      size_ += l->size();
86    }
87    l->clear();
88  }
89
90  void append_back(IntrusiveList<Item> *l) {
91    CHECK_NE(this, l);
92    if (l->empty())
93      return;
94    if (empty()) {
95      *this = *l;
96    } else {
97      last_->next = l->first_;
98      last_ = l->last_;
99      size_ += l->size();
100    }
101    l->clear();
102  }
103
104  void CheckConsistency() {
105    if (size_ == 0) {
106      CHECK_EQ(first_, 0);
107      CHECK_EQ(last_, 0);
108    } else {
109      uptr count = 0;
110      for (Item *i = first_; ; i = i->next) {
111        count++;
112        if (i == last_) break;
113      }
114      CHECK_EQ(size(), count);
115      CHECK_EQ(last_->next, 0);
116    }
117  }
118
119  template<class ItemTy>
120  class IteratorBase {
121   public:
122    explicit IteratorBase(ItemTy *current) : current_(current) {}
123    IteratorBase &operator++() {
124      current_ = current_->next;
125      return *this;
126    }
127    bool operator!=(IteratorBase other) const {
128      return current_ != other.current_;
129    }
130    ItemTy &operator*() {
131      return *current_;
132    }
133   private:
134    ItemTy *current_;
135  };
136
137  typedef IteratorBase<Item> Iterator;
138  typedef IteratorBase<const Item> ConstIterator;
139
140  Iterator begin() { return Iterator(first_); }
141  Iterator end() { return Iterator(0); }
142
143  ConstIterator begin() const { return ConstIterator(first_); }
144  ConstIterator end() const { return ConstIterator(0); }
145
146// private, don't use directly.
147  uptr size_;
148  Item *first_;
149  Item *last_;
150};
151
152} // namespace __sanitizer
153
154#endif // SANITIZER_LIST_H
155