sanitizer_list.h 3.8 KB

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