Loading...
Searching...
No Matches
eventContainer.h
1//
2// Copyright 2018 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24
25#ifndef PXR_BASE_TRACE_EVENT_CONTAINER_H
26#define PXR_BASE_TRACE_EVENT_CONTAINER_H
27
28#include "pxr/pxr.h"
29
30#include "pxr/base/trace/api.h"
31#include "pxr/base/trace/event.h"
32
33#include <iterator>
34#include <new>
35#include <utility>
36
37PXR_NAMESPACE_OPEN_SCOPE
38
46 // Intrusively doubly-linked list node that provides contiguous storage
47 // for events. Only appending events and iterating held events is
48 // supported.
49 class _Node
50 {
51 public:
52 using const_iterator = const TraceEvent *;
53
54 // Allocate a new node that is able to hold capacity events.
55 static _Node* New(size_t capacity);
56
57 // Destroys the list starting at head, which must be the first node
58 // in its list.
59 static void DestroyList(_Node *head);
60
61 // Join the last and first nodes of two lists to form a new list.
62 static void Join(_Node *lhs, _Node *rhs);
63
64 // Returns true if the node cannot hold any more events.
65 bool IsFull() const { return _end == _sentinel; }
66
67 const_iterator begin() const {
68 const char *p = reinterpret_cast<const char *>(this);
69 p += sizeof(_Node);
70 return reinterpret_cast<const TraceEvent *>(p);
71 }
72
73 const_iterator end() const {
74 return _end;
75 }
76
77 _Node *GetPrevNode() {
78 return _prev;
79 }
80
81 const _Node *GetPrevNode() const {
82 return _prev;
83 }
84
85 _Node *GetNextNode() {
86 return _next;
87 }
88
89 const _Node *GetNextNode() const {
90 return _next;
91 }
92
93 void ClaimEventEntry() {
94 ++_end;
95 }
96
97 // Remove this node from the linked list to which it belongs.
98 void Unlink();
99
100 private:
101 _Node(TraceEvent *end, size_t capacity);
102 ~_Node();
103
104 private:
105 union {
106 struct {
107 TraceEvent *_end;
108 TraceEvent *_sentinel;
109 _Node *_prev;
110 _Node *_next;
111 };
112 // Ensure that _Node is aligned to at least the alignment of
113 // TraceEvent.
114 alignas(TraceEvent) char _unused;
115 };
116 };
117
118public:
124 public:
125 using iterator_category = std::bidirectional_iterator_tag;
126 using value_type = const TraceEvent;
127 using difference_type = int64_t;
128 using pointer = const TraceEvent*;
129 using reference = const TraceEvent&;
130
131 reference operator*() {
132 return *_event;
133 }
134
135 pointer operator->() {
136 return _event;
137 }
138
139 bool operator !=(const const_iterator& other) const {
140 return !operator==(other);
141 }
142
143 bool operator == (const const_iterator& other) const {
144 return _event == other._event;
145 }
146
147 const_iterator& operator ++() {
148 Advance();
149 return *this;
150 }
151
152 const_iterator operator ++(int) {
153 const_iterator result(*this);
154 Advance();
155 return result;
156 }
157
158 const_iterator& operator --() {
159 Reverse();
160 return *this;
161 }
162
163 const_iterator operator --(int) {
164 const_iterator result(*this);
165 Reverse();
166 return result;
167 }
168
169 private:
170 const_iterator(const _Node *node, const TraceEvent *event)
171 : _node(node)
172 , _event(event)
173 {}
174
175 void Advance() {
176 ++_event;
177 if (_event == _node->end() && _node->GetNextNode()) {
178 _node = _node->GetNextNode();
179 _event = _node->begin();
180 }
181 }
182
183 void Reverse() {
184 if (_event == _node->begin()) {
185 _node = _node->GetPrevNode();
186 _event = _node->end();
187 }
188 --_event;
189 }
190
191 const _Node *_node;
192 const TraceEvent *_event;
193
194 friend class TraceEventContainer;
195 };
196
197 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
198
201
204
207
208 // No copies
211
212 TRACE_API
214
217 template < class... Args>
218 TraceEvent& emplace_back(Args&&... args) {
219 TraceEvent *event =
220 new (_nextEvent++) TraceEvent(std::forward<Args>(args)...);
221 _back->ClaimEventEntry();
222 if (_back->IsFull()) {
223 Allocate();
224 }
225 return *event;
226 }
227
228 const_iterator begin() const {
229 return const_iterator(_front, _front ? _front->begin() : nullptr);
230 }
231
232 const_iterator end() const {
233 return const_iterator(_back, _back ? _back->end() : nullptr);
234 }
235
236 const_reverse_iterator rbegin() const {
237 return const_reverse_iterator(end());
238 }
239
240 const_reverse_iterator rend() const {
241 return const_reverse_iterator(begin());
242 }
243
244 bool empty() const { return begin() == end(); }
246
249 TRACE_API void Append(TraceEventContainer&& other);
250
251private:
252 // Allocates a new block of memory for TraceEvent items.
253 TRACE_API void Allocate();
254
255 // Points to where the next event should be constructed.
256 TraceEvent* _nextEvent;
257 _Node* _front;
258 _Node* _back;
259 size_t _blockSizeBytes;
260};
261
262PXR_NAMESPACE_CLOSE_SCOPE
263
264#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:47