All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 TRACE_EVENT_CONTAINER_H
26 #define 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 
37 PXR_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 
118 public:
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
209  TraceEventContainer(const TraceEventContainer&) = delete;
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 
251 private:
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 
262 PXR_NAMESPACE_CLOSE_SCOPE
263 
264 #endif // TRACE_EVENT_CONTAINER_H
Bidirectional iterator of TraceEvents.
This represents an event recorded by a TraceCollector.
Definition: event.h:47
TraceEventContainer & operator=(TraceEventContainer &&)
Move Assignment.
TRACE_API void Append(TraceEventContainer &&other)
Append the events in other to the end of this container.
TraceEventContainer()
Constructor.
Holds TraceEvent instances.