Loading...
Searching...
No Matches
eventContainer.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_EVENT_CONTAINER_H
9#define PXR_BASE_TRACE_EVENT_CONTAINER_H
10
11#include "pxr/pxr.h"
12
13#include "pxr/base/trace/api.h"
14#include "pxr/base/trace/event.h"
15
16#include <iterator>
17#include <new>
18#include <utility>
19
20PXR_NAMESPACE_OPEN_SCOPE
21
29 // Intrusively doubly-linked list node that provides contiguous storage
30 // for events. Only appending events and iterating held events is
31 // supported.
32 class _Node
33 {
34 public:
35 using const_iterator = const TraceEvent *;
36
37 // Allocate a new node that is able to hold capacity events.
38 static _Node* New(size_t capacity);
39
40 // Destroys the list starting at head, which must be the first node
41 // in its list.
42 static void DestroyList(_Node *head);
43
44 // Join the last and first nodes of two lists to form a new list.
45 static void Join(_Node *lhs, _Node *rhs);
46
47 // Returns true if the node cannot hold any more events.
48 bool IsFull() const { return _end == _sentinel; }
49
50 const_iterator begin() const {
51 const char *p = reinterpret_cast<const char *>(this);
52 p += sizeof(_Node);
53 return reinterpret_cast<const TraceEvent *>(p);
54 }
55
56 const_iterator end() const {
57 return _end;
58 }
59
60 _Node *GetPrevNode() {
61 return _prev;
62 }
63
64 const _Node *GetPrevNode() const {
65 return _prev;
66 }
67
68 _Node *GetNextNode() {
69 return _next;
70 }
71
72 const _Node *GetNextNode() const {
73 return _next;
74 }
75
76 void ClaimEventEntry() {
77 ++_end;
78 }
79
80 // Remove this node from the linked list to which it belongs.
81 void Unlink();
82
83 private:
84 _Node(TraceEvent *end, size_t capacity);
85 ~_Node();
86
87 private:
88 union {
89 struct {
90 TraceEvent *_end;
91 TraceEvent *_sentinel;
92 _Node *_prev;
93 _Node *_next;
94 };
95 // Ensure that _Node is aligned to at least the alignment of
96 // TraceEvent.
97 alignas(TraceEvent) char _unused;
98 };
99 };
100
101public:
107 public:
108 using iterator_category = std::bidirectional_iterator_tag;
109 using value_type = const TraceEvent;
110 using difference_type = int64_t;
111 using pointer = const TraceEvent*;
112 using reference = const TraceEvent&;
113
114 reference operator*() {
115 return *_event;
116 }
117
118 pointer operator->() {
119 return _event;
120 }
121
122 bool operator !=(const const_iterator& other) const {
123 return !operator==(other);
124 }
125
126 bool operator == (const const_iterator& other) const {
127 return _event == other._event;
128 }
129
130 const_iterator& operator ++() {
131 Advance();
132 return *this;
133 }
134
135 const_iterator operator ++(int) {
136 const_iterator result(*this);
137 Advance();
138 return result;
139 }
140
141 const_iterator& operator --() {
142 Reverse();
143 return *this;
144 }
145
146 const_iterator operator --(int) {
147 const_iterator result(*this);
148 Reverse();
149 return result;
150 }
151
152 private:
153 const_iterator(const _Node *node, const TraceEvent *event)
154 : _node(node)
155 , _event(event)
156 {}
157
158 void Advance() {
159 ++_event;
160 if (_event == _node->end() && _node->GetNextNode()) {
161 _node = _node->GetNextNode();
162 _event = _node->begin();
163 }
164 }
165
166 void Reverse() {
167 if (_event == _node->begin()) {
168 _node = _node->GetPrevNode();
169 _event = _node->end();
170 }
171 --_event;
172 }
173
174 const _Node *_node;
175 const TraceEvent *_event;
176
177 friend class TraceEventContainer;
178 };
179
180 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
181
184
187
190
191 // No copies
194
195 TRACE_API
197
200 template < class... Args>
201 TraceEvent& emplace_back(Args&&... args) {
202 TraceEvent *event =
203 new (_nextEvent++) TraceEvent(std::forward<Args>(args)...);
204 _back->ClaimEventEntry();
205 if (_back->IsFull()) {
206 Allocate();
207 }
208 return *event;
209 }
210
211 const_iterator begin() const {
212 return const_iterator(_front, _front ? _front->begin() : nullptr);
213 }
214
215 const_iterator end() const {
216 return const_iterator(_back, _back ? _back->end() : nullptr);
217 }
218
219 const_reverse_iterator rbegin() const {
220 return const_reverse_iterator(end());
221 }
222
223 const_reverse_iterator rend() const {
224 return const_reverse_iterator(begin());
225 }
226
227 bool empty() const { return begin() == end(); }
229
232 TRACE_API void Append(TraceEventContainer&& other);
233
234private:
235 // Allocates a new block of memory for TraceEvent items.
236 TRACE_API void Allocate();
237
238 // Points to where the next event should be constructed.
239 TraceEvent* _nextEvent;
240 _Node* _front;
241 _Node* _back;
242 size_t _blockSizeBytes;
243};
244
245PXR_NAMESPACE_CLOSE_SCOPE
246
247#endif // PXR_BASE_TRACE_EVENT_CONTAINER_H
Bidirectional iterator of TraceEvents.
Holds TraceEvent instances.
TraceEventContainer(TraceEventContainer &&)
Move Constructor.
TraceEventContainer & operator=(TraceEventContainer &&)
Move Assignment.
TraceEventContainer()
Constructor.
TRACE_API void Append(TraceEventContainer &&other)
Append the events in other to the end of this container.
This represents an event recorded by a TraceCollector.
Definition: event.h:30