HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
eventContainer.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_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 
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 /// \class TraceEventContainer
24 ///
25 /// Holds TraceEvent instances. This container only allows appending events at
26 /// the end and supports both forward and reverse iteration.
27 ///
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 
101 public:
102  ////////////////////////////////////////////////////////////////////////////
103  /// \class const_iterator
104  /// Bidirectional iterator of TraceEvents.
105  ///
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 
115  return *_event;
116  }
117 
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 
131  Advance();
132  return *this;
133  }
134 
136  const_iterator result(*this);
137  Advance();
138  return result;
139  }
140 
142  Reverse();
143  return *this;
144  }
145 
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 
182  /// Constructor.
184 
185  /// Move Constructor.
187 
188  /// Move Assignment.
190 
191  // No copies
192  TraceEventContainer(const TraceEventContainer&) = delete;
194 
195  TRACE_API
197 
198  /// \name Subset of stl container interface.
199  /// @{
200  template < class... 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 
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 
220  return const_reverse_iterator(end());
221  }
222 
224  return const_reverse_iterator(begin());
225  }
226 
227  bool empty() const { return begin() == end(); }
228  /// @}
229 
230  /// Append the events in \p other to the end of this container. This takes
231  /// ownership of the events that were in \p other.
232  TRACE_API void Append(TraceEventContainer&& other);
233 
234 private:
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 
246 
247 #endif // PXR_BASE_TRACE_EVENT_CONTAINER_H
TraceEventContainer()
Constructor.
bool empty() const
const_iterator end() const
**But if you need a result
Definition: thread.h:622
TraceEventContainer & operator=(TraceEventContainer &&)
Move Assignment.
struct _cl_event * event
Definition: glcorearb.h:2961
const_reverse_iterator rbegin() const
TRACE_API ~TraceEventContainer()
std::reverse_iterator< const_iterator > const_reverse_iterator
TraceEvent & emplace_back(Args &&...args)
TRACE_API void Append(TraceEventContainer &&other)
GLuint GLuint end
Definition: glcorearb.h:475
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
**If you just want to fire and args
Definition: thread.h:618
bool operator!=(const const_iterator &other) const
const_iterator begin() const
bool operator==(const const_iterator &other) const
const_reverse_iterator rend() const
std::bidirectional_iterator_tag iterator_category
#define TRACE_API
Definition: api.h:23