Loading...
Searching...
No Matches
concurrentList.h
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
20PXR_NAMESPACE_OPEN_SCOPE
21
27template <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
36public:
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
54 pointer operator->() {
55 return _node ? &_node->value : nullptr;
56 }
57
58 reference operator*() {
59 return _node->value;
60 }
61
62 iterator& operator++() {
63 _node = _node->next;
64 return *this;
65 }
66
67 iterator operator++(int) {
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
88 TraceConcurrentList() : _head(nullptr) {}
89
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
104 TraceConcurrentList& operator=(const TraceConcurrentList&) = delete;
105
108 iterator begin() { return iterator(_head.load(std::memory_order_acquire)); }
109 iterator end() { return iterator(); }
111
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
125private:
126 std::atomic<Node*> _head;
127 tbb::cache_aligned_allocator<Node> _alloc;
128};
129
130PXR_NAMESPACE_CLOSE_SCOPE
131
132#endif // PXR_BASE_TRACE_CONCURRENT_LIST_H
Provide architecture-specific memory-alignment information.
This class provides forward iterator support to iterate over all the items.
This class supports thread safe insertion and iteration over a list of items.
TraceConcurrentList()
Constructor.
iterator Insert()
Inserts an item at the beginning of the list and returns an iterator to the newly created item.
~TraceConcurrentList()
Destructor.