HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
errorMark.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_ERROR_MARK_H
8 #define PXR_BASE_TF_ERROR_MARK_H
9 
10 /// \file tf/errorMark.h
11 
12 #include "pxr/pxr.h"
15 #include "pxr/base/tf/api.h"
16 
18 
19 /// \class TfErrorMark
20 /// \ingroup group_tf_TfError
21 ///
22 /// Class used to record the end of the error-list.
23 ///
24 /// See \ref page_tf_TfError for a detailed description.
25 ///
26 /// A \c TfErrorMark is used as follows:
27 /// \code
28 /// TfErrorMark m;
29 ///
30 /// m.SetMark(); // (A)
31 /// ... ;
32 /// ... ;
33 /// // (B)
34 /// if (!m.IsClean()) {
35 /// // errors occurred between (A) and (B)
36 /// }
37 /// \endcode
38 ///
39 /// Another common pattern is
40 /// \code
41 /// TfErrorMark m;
42 /// if (TF_HAS_ERRORS(m, expr)) {
43 /// // handle errors;
44 /// }
45 /// \endcode
46 ///
48 {
49  TfErrorMark(const TfErrorMark&) = delete;
50  TfErrorMark& operator=(const TfErrorMark&) = delete;
51  public:
52 
54 
55  /// Default constructor.
56  ///
57  /// The default constructor automatically calls \c SetMark() at the point
58  /// of declaration.
60 
61  /// Destroy this ErrorMark.
62  ///
63  /// If this is the last ErrorMark on this thread of execution and there
64  /// are pending errors, this will report them via the diagnostic delegate
65  /// (if one is installed) otherwise by printing to stderr.
67 
68  /// Record future errors.
69  ///
70  /// \c SetMark() arranges to record future errors in \c *this.
71  inline void SetMark() {
72  _mark = TfDiagnosticMgr::GetInstance()._nextSerial;
73  }
74 
75  /// Return true if no new errors were posted in this thread since the last
76  /// call to \c SetMark(), false otherwise.
77  ///
78  /// When no threads are issuing errors the cost of this function is an
79  /// atomic integer read and comparison. Otherwise thread-specific data is
80  /// accessed to make the determination. Thus, this function is fast when
81  /// diagnostics are not being issued.
82  inline bool IsClean() const {
84  return _mark >= mgr._nextSerial || _IsCleanImpl(mgr);
85  }
86 
87  /// Remove all errors in this mark from the error system. Return true if
88  /// any errors were cleared, false if there were no errors in this mark.
89  ///
90  /// Clear all errors contained in this mark from the error system.
91  /// Subsequently, these errors will be considered handled.
92  inline bool Clear() const {
94  auto b = GetBegin(), e = mgr.GetErrorEnd();
95  if (b != e) {
96  mgr.EraseRange(b, e);
97  return true;
98  }
99  return false;
100  }
101 
102  /// Remove all errors in this mark fom the error system and return them in
103  /// a TfErrorTransport.
104  ///
105  /// This can be used to transfer errors from one thread to another. See
106  /// TfErrorTransport for more information. As with Clear(), all the
107  /// removed errors are considered handled for this thread. See also
108  /// TransportTo().
109  inline TfErrorTransport Transport() const {
111  return TfErrorTransport(mgr._errorList.local(),
112  GetBegin(), mgr.GetErrorEnd());
113  }
114 
115  /// Remove all errors in this mark fom the error system and return them in
116  /// a TfErrorTransport.
117  ///
118  /// This is a variant of Transport(). Instead of returning a new
119  /// TfErrorTransport object it fills an existing one.
120  inline void TransportTo(TfErrorTransport &dest) const {
121  Transport().swap(dest);
122  }
123 
124  /// Return an iterator to the first error added to the error list after
125  /// \c SetMark().
126  ///
127  /// If there are no errors on the error list that were not already present
128  /// when \c SetMark() was called, the iterator returned is equal to the
129  /// iterator returned by \c TfDiagnosticMgr::GetErrorEnd(). Otherwise, the
130  /// iterator points to the earliest error added to the list since
131  /// \c SetMark() was called.
132  ///
133  /// This function takes O(n) time where n is the number of errors from the
134  /// end of the list to the mark i.e. \c GetMark() walks the list from the
135  /// end until it finds the mark and then returns an iterator to that spot.
136  ///
137  /// If \c nErrors is non-NULL, then \c *nErrors is set to the number of
138  /// errors between the returned iterator and the end of the list.
139  Iterator GetBegin(size_t *nErrors = 0) const {
140  return
141  TfDiagnosticMgr::GetInstance()._GetErrorMarkBegin(_mark, nErrors);
142  }
143 
144  /// Return an iterator past the last error in the error system.
145  ///
146  /// This iterator is always equivalent to the iterator returned by \c
147  /// TfDiagnosticMgr::GetErrorEnd().
148  Iterator GetEnd() const {
150  }
151 
152  /// Equivalent to GetBegin()
153  Iterator begin() const { return GetBegin(); }
154 
155  /// Equivalent to GetEnd()
156  Iterator end() const { return GetEnd(); }
157 
158  private:
159  friend class TfDiagnosticMgr;
160 
161  // Helper to check if the _mark identifies any errors present on the
162  // thread-local error list.
163  TF_API bool _IsCleanImpl(TfDiagnosticMgr &mgr) const;
164 
165  void _ReportErrors(TfDiagnosticMgr &mgr) const;
166 
167  size_t _mark;
168 };
169 
170 
171 /// Convenience macro to check if errors occurred.
172 ///
173 /// This macro is equivalent to
174 /// \code
175 /// (marker.SetMark(), (expr), !marker.IsClean())
176 /// \endcode
177 ///
178 /// which enables it to be used as an expression:
179 /// \code
180 /// if (TF_HAS_ERRORS(m, expr))
181 /// // cope!
182 /// \endcode
183 ///
184 /// \ingroup group_tf_TfError
185 /// \hideinitializer
186 #define TF_HAS_ERRORS(marker, expr) \
187  (marker.SetMark(), (expr), !marker.IsClean())
188 
189 /// Report current TfErrorMark instances and the stack traces that created
190 /// them to stdout for debugging purposes.
191 ///
192 /// To call this function, set _enableTfErrorMarkStackTraces in errorMark.cpp
193 /// and enable the TF_ERROR_MARK_TRACKING TfDebug code.
194 ///
195 /// \ingroup group_tf_TfError
196 TF_API
198 
200 
201 #endif // PXR_BASE_TF_ERROR_MARK_H
#define TF_API
Definition: api.h:23
TF_API ErrorIterator EraseRange(ErrorIterator first, ErrorIterator last)
void swap(TfErrorTransport &other)
Iterator end() const
Equivalent to GetEnd()
Definition: errorMark.h:156
ErrorList::iterator ErrorIterator
Definition: diagnosticMgr.h:79
static TF_API This & GetInstance()
Return the singleton instance.
TF_API void TfReportActiveErrorMarks()
Iterator GetBegin(size_t *nErrors=0) const
Definition: errorMark.h:139
TF_API ~TfErrorMark()
TfErrorTransport Transport() const
Definition: errorMark.h:109
TfDiagnosticMgr::ErrorIterator Iterator
Definition: errorMark.h:53
Iterator GetEnd() const
Definition: errorMark.h:148
bool Clear() const
Definition: errorMark.h:92
bool IsClean() const
Definition: errorMark.h:82
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
void SetMark()
Definition: errorMark.h:71
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
void TransportTo(TfErrorTransport &dest) const
Definition: errorMark.h:120
TF_API TfErrorMark()
ErrorIterator GetErrorEnd()
Return an iterator to the end of this thread's error list.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
Iterator begin() const
Equivalent to GetBegin()
Definition: errorMark.h:153