sanitizer_list.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. #ifndef SANITIZER_LIST_H
  13. #define SANITIZER_LIST_H
  14. #include "sanitizer_internal_defs.h"
  15. namespace __sanitizer {
  16. // Intrusive singly-linked list with size(), push_back(), push_front()
  17. // pop_front(), append_front() and append_back().
  18. // This class should be a POD (so that it can be put into TLS)
  19. // and an object with all zero fields should represent a valid empty list.
  20. // This class does not have a CTOR, so clear() should be called on all
  21. // non-zero-initialized objects before using.
  22. template<class Item>
  23. struct IntrusiveList {
  24. friend class Iterator;
  25. void clear() {
  26. first_ = last_ = 0;
  27. size_ = 0;
  28. }
  29. bool empty() const { return size_ == 0; }
  30. uptr size() const { return size_; }
  31. void push_back(Item *x) {
  32. if (empty()) {
  33. x->next = 0;
  34. first_ = last_ = x;
  35. size_ = 1;
  36. } else {
  37. x->next = 0;
  38. last_->next = x;
  39. last_ = x;
  40. size_++;
  41. }
  42. }
  43. void push_front(Item *x) {
  44. if (empty()) {
  45. x->next = 0;
  46. first_ = last_ = x;
  47. size_ = 1;
  48. } else {
  49. x->next = first_;
  50. first_ = x;
  51. size_++;
  52. }
  53. }
  54. void pop_front() {
  55. CHECK(!empty());
  56. first_ = first_->next;
  57. if (first_ == 0)
  58. last_ = 0;
  59. size_--;
  60. }
  61. Item *front() { return first_; }
  62. Item *back() { return last_; }
  63. void append_front(IntrusiveList<Item> *l) {
  64. CHECK_NE(this, l);
  65. if (l->empty())
  66. return;
  67. if (empty()) {
  68. *this = *l;
  69. } else if (!l->empty()) {
  70. l->last_->next = first_;
  71. first_ = l->first_;
  72. size_ += l->size();
  73. }
  74. l->clear();
  75. }
  76. void append_back(IntrusiveList<Item> *l) {
  77. CHECK_NE(this, l);
  78. if (l->empty())
  79. return;
  80. if (empty()) {
  81. *this = *l;
  82. } else {
  83. last_->next = l->first_;
  84. last_ = l->last_;
  85. size_ += l->size();
  86. }
  87. l->clear();
  88. }
  89. void CheckConsistency() {
  90. if (size_ == 0) {
  91. CHECK_EQ(first_, 0);
  92. CHECK_EQ(last_, 0);
  93. } else {
  94. uptr count = 0;
  95. for (Item *i = first_; ; i = i->next) {
  96. count++;
  97. if (i == last_) break;
  98. }
  99. CHECK_EQ(size(), count);
  100. CHECK_EQ(last_->next, 0);
  101. }
  102. }
  103. class Iterator {
  104. public:
  105. explicit Iterator(IntrusiveList<Item> *list)
  106. : list_(list), current_(list->first_) { }
  107. Item *next() {
  108. Item *ret = current_;
  109. if (current_) current_ = current_->next;
  110. return ret;
  111. }
  112. bool hasNext() const { return current_ != 0; }
  113. private:
  114. IntrusiveList<Item> *list_;
  115. Item *current_;
  116. };
  117. // private, don't use directly.
  118. uptr size_;
  119. Item *first_;
  120. Item *last_;
  121. };
  122. } // namespace __sanitizer
  123. #endif // SANITIZER_LIST_H