HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
concurrentList.h
Go to the documentation of this file.
1 //
2 // Copyright 2018 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 
8 #ifndef PXR_BASE_TRACE_CONCURRENT_LIST_H
9 #define PXR_BASE_TRACE_CONCURRENT_LIST_H
10 
11 #include "pxr/pxr.h"
12 
13 #include "pxr/base/arch/align.h"
14 
15 #include <tbb/cache_aligned_allocator.h>
16 
17 #include <atomic>
18 #include <iterator>
19 
21 
22 ////////////////////////////////////////////////////////////////////////////////
23 /// \class TraceConcurrentList
24 ///
25 /// This class supports thread safe insertion and iteration over a list of items.
26 ///
27 template <typename T>
29 
30  // Linked list node that is cache line aligned to prevent false sharing.
31  struct alignas(ARCH_CACHE_LINE_SIZE*2) Node {
32  T value;
33  Node* next;
34  };
35 
36 public:
37  ////////////////////////////////////////////////////////////////////////////
38  /// \class iterator
39  ///
40  /// This class provides forward iterator support to iterate over all the
41  /// items.
42  ///
43  class iterator {
44  public:
45  // iterator types
46  using iterator_category = std::forward_iterator_tag;
47  using value = T;
48  using pointer = T*;
49  using reference = T&;
50  using difference_type = ptrdiff_t;
51 
52  iterator() : _node(nullptr) {}
53 
55  return _node ? &_node->value : nullptr;
56  }
57 
59  return _node->value;
60  }
61 
63  _node = _node->next;
64  return *this;
65  }
66 
68  iterator result(*this);
69  _node = _node->next;
70  return result;
71  }
72 
73  bool operator !=(const iterator& other) const {
74  return _node != other._node;
75  }
76 
77  bool operator ==(const iterator& other) const {
78  return _node == other._node;
79  }
80 
81  private:
82  explicit iterator(Node* node) : _node(node) {}
83  Node* _node;
84  friend class TraceConcurrentList;
85  };
86 
87  /// Constructor.
88  TraceConcurrentList() : _head(nullptr) {}
89 
90  /// Destructor.
92  // Delete all nodes in the list.
93  Node* curNode = _head.load(std::memory_order_acquire);
94  while (curNode) {
95  Node* nodeToDelete = curNode;
96  curNode = curNode->next;
97  nodeToDelete->~Node();
98  _alloc.deallocate(nodeToDelete, 1);
99  }
100  }
101 
102  // No copies
103  TraceConcurrentList(const TraceConcurrentList&) = delete;
105 
106  /// \name Iterator support.
107  /// @{
108  iterator begin() { return iterator(_head.load(std::memory_order_acquire)); }
109  iterator end() { return iterator(); }
110  /// @}
111 
112  /// Inserts an item at the beginning of the list and returns an iterator to
113  /// the newly created item.
114  iterator Insert() {
115  Node* newNode = _alloc.allocate(1);
116  new(newNode) Node();
117 
118  // Add the node to the linked list in an atomic manner.
119  do {
120  newNode->next = _head.load(std::memory_order_relaxed);
121  } while (!_head.compare_exchange_weak(newNode->next, newNode));
122  return iterator(newNode);
123  }
124 
125 private:
126  std::atomic<Node*> _head;
127  tbb::cache_aligned_allocator<Node> _alloc;
128 };
129 
131 
132 #endif // PXR_BASE_TRACE_CONCURRENT_LIST_H
std::forward_iterator_tag iterator_category
Definition: Node.h:52
GLsizei const GLfloat * value
Definition: glcorearb.h:824
**But if you need a result
Definition: thread.h:622
bool operator!=(const iterator &other) const
Node(ElementPtr parent, const string &name)
Definition: Node.h:55
TraceConcurrentList & operator=(const TraceConcurrentList &)=delete
TraceConcurrentList()
Constructor.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
~TraceConcurrentList()
Destructor.
bool operator==(const iterator &other) const