AGX Dynamics 2.41.3.2
Loading...
Searching...
No Matches
Notify.h
Go to the documentation of this file.
1/*
2Copyright 2007-2025. Algoryx Simulation AB.
3
4All AGX source code, intellectual property, documentation, sample code,
5tutorials, scene files and technical white papers, are copyrighted, proprietary
6and confidential material of Algoryx Simulation AB. You may not download, read,
7store, distribute, publish, copy or otherwise disseminate, use or expose this
8material unless having a written signed agreement with Algoryx Simulation AB, or having been
9advised so by Algoryx Simulation AB for a time limited evaluation, or having purchased a
10valid commercial license from Algoryx Simulation AB.
11
12Algoryx Simulation AB disclaims all responsibilities for loss or damage caused
13from using this software, unless otherwise stated in written agreements with
14Algoryx Simulation AB.
15*/
16
17#pragma once
18
19
20#ifdef _MSC_VER
21# pragma warning(push)
22# pragma warning(disable: 4355) // No warnings about using this in member initializer list
23#endif
24
25#include <agx/agx.h>
26#include <iostream>
27#include <agx/Vector.h>
28#include <sstream>
29#include <agx/HashTable.h>
30#include <agx/Singleton.h>
31#include <agx/LogStream.h>
32
33#define THREAD_SAFE_NOTIFY 1
34
35#if THREAD_SAFE_NOTIFY
37#endif
38
39namespace agx
40{
41
43 class Thread;
44 class Notify;
45 class ThreadDataHolder;
47
48
50 {
51 public:
53 virtual ~NotifyCallback();
54
56 virtual void message( const agx::String& msg, int notifyLevel) = 0;
57
58 protected:
59
60 };
61
64 {
65 public:
66
67 enum NotifyLevel { NOTIFY_DEBUG = 1 << 0,
68 NOTIFY_INFO = 1 << 1,
69 NOTIFY_WARNING = 1 << 2,
70 NOTIFY_ERROR = 1 << 3,
71 NOTIFY_END = 1 << 4,
72 NOTIFY_CLEAR = 1 << 5,
73 NOTIFY_PUSH = 1 << 6,
74 NOTIFY_LOGONLY = 1 << 7
75 };
76
78 PRINT_NONE = 0, // Print nothing
79 PRINT_FILE = 1, // Print the filename
80 PRINT_TAG = 2, // Print the tag (ERROR, WARNING, INFO, DEBUG
81 PRINT_LINE = 4, // Print the linenumber
82 PRINT_FUNCTION = 8, // Print the functionname
83 PRINT_SELECTION_END = 8,
84 PRINT_DEFAULT = PRINT_TAG | PRINT_FUNCTION,
85 PRINT_ALL = PRINT_FILE | PRINT_TAG | PRINT_LINE | PRINT_FUNCTION
86 };
87
92 Notify( std::ostream& out_stream = std::cerr);
93
95 static Notify* instance();
96
99
101 const agx::LogStream& logStream() const;
102
105
108
110 bool openLog( const agx::String& filename );
111
114
116 bool getThrowOnError() const;
117
119 void setThrowOnError( bool v );
120
130 void setBreakOnError( bool f );
131
133 bool getBreakOnError() const;
134
135
138
144
150
152 void addStream( std::ostream* stream, NotifyLevel l );
153
158 bool removeStream( std::ostream* stream );
159
164 bool setNotifyLevel( std::ostream* stream, NotifyLevel l );
165
168
171
173 bool getToLogOnly() const;
174
176 void setToLogOnly( bool f );
177
178 std::ostream& outStream();
179
180 private:
181
182 template <class A, A val >
183 class Mode
184 {
185 public:
186#ifdef __APPLE__
187 // Hm, some weird bug in Apples gcc doesn't like the original constructor
188 Mode( Notify* notify ) : m_notify( notify ), m_level( val ) {}
189#else
190 Mode( Notify* notify, A l = val ) : m_notify( notify ), m_level( l ) {}
191#endif
192 Mode( const Mode& m ) : m_notify( m.m_notify ), m_level( m.m_level ) {}
193
194 Notify::NotifyLevel getLevel() const {
195 return m_level;
196 }
197 Notify* getNotify() {
198 return m_notify;
199 }
200 const Notify* getNotify() const {
201 return m_notify;
202 }
203 private:
204 Notify* m_notify;
205 Notify::NotifyLevel m_level;
206 Mode() {}
207 };
208
210
211
212 template <class A>
213 class Modifier
214 {
215 public:
216 Modifier( Notify* notify ) : m_notify( notify ), m_value( A( 0 ) ) {}
217 Modifier( const Modifier& m ) : m_notify( m.m_notify ), m_value( m.m_value ) {}
218 A getValue() {
219 return m_value;
220 }
221 Modifier& setValue( A val ) {
222 m_value = val;
223 return *this;
224 }
225
226 Notify* getNotify() {
227 return m_notify;
228 }
229 const Notify* getNotify() const {
230 return m_notify;
231 }
232
233 private:
234 Notify* m_notify;
235 A m_value;
236 Modifier() {}
237 };
239
240
241 class AGXCORE_EXPORT PrintSelection
242 {
243 public:
244 PrintSelection( int mask );
245
246 PrintSelection();
247
248 PrintSelection( const PrintSelection& p );
249 PrintSelection& operator=( const PrintSelection& p );
250
251 ~PrintSelection();
252
253 void clear();
254
256 void setMask( int f );
257
259 void setMask( int f, bool val );
260
261 bool isSet( int s ) const;
262
263 bool isNoneSet() const;
264
265 private:
266 int m_selection_mask;
267 };
268 public:
269
271
272 typedef Mode<Notify::NotifyLevel, Notify::NOTIFY_END> End;
273 typedef Mode<Notify::NotifyLevel, Notify::NOTIFY_CLEAR> Clear;
274 typedef Mode<Notify::NotifyLevel, Notify::NOTIFY_LOGONLY> LogOnly;
275 typedef Modifier<int> Push;
276
277 SINGLETON_CLASSNAME_METHOD();
278
279 template<typename T>
280 Notify& operator<<(const T& rhs) {
281 getThreadStringStream() << rhs;
282 return *this;
283 }
284
285 typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
286 typedef CoutType& (*StandardEndLine)(CoutType&);
287
289 Notify& operator<<(StandardEndLine manip);
290
291 operator std::ostream&() { return getThreadStringStream(); }
292
293 Notify& operator<<( Notify::Clear& /*mode*/ ) {
294 std::ostringstream& str = getThreadStringStream();
295 str.str( "" );
296 str.clear();
297 return *this;
298 }
299
300 Notify& operator<<( Notify::End& modifier );
301 Notify& operator<<( Notify::Push& modifier );
302 Notify& operator<<( Notify::LogOnly& modifier );
303
304 std::ios_base::fmtflags setf(std::ios_base::fmtflags newFormatFlags);
305
306
307 Clear& clearString() ;
308
309 End& end();
310
311 Push& push();
312
313 LogOnly& logOnly();
314
315
316 void debug( const char* function, int line, const char* file, const agx::String& msg );
317 void info( const char* function, int line, const char* file, const agx::String& msg );
318 void warning( const char* function, int line, const char* file, const agx::String& msg );
319 void error( const char* function, int line, const char* file, const agx::String& msg );
320
321 void debug( const agx::String& msg );
322 void info( const agx::String& msg );
323 void warning( const agx::String& msg );
324 void error( const agx::String& msg );
325
327 void pushPrintSelection( const PrintSelection& p, NotifyLevel l );
328
329 void pushPrintSelection( const PrintSelection& p );
330
331 // Get the current print selection stack
332 PrintSelection& getPrintSelection( NotifyLevel l );
333
334 PrintSelection& getPrintSelection();
335
337 bool popPrintSelection( NotifyLevel l );
338
339 bool popPrintSelection();
340
342
343
344 agx::String buildString( );
345 agx::String setDebugStrings( NotifyLevel l, const char* function, int line, const char* file );
346
347 virtual ~Notify();
348
349 void shutdown() override;
350
351 protected:
352
353 friend void agxCore::init();
354 friend class agx::Thread;
355 friend void agx::setNumThreads(size_t numThreads);
356 friend class ThreadDataHolder;
357
358 std::string str() const;
359
360 void str( const std::string& text );
361
362 void clear();
363
364 End m_end;
365 Clear m_clear;
366 Push m_push;
367 LogOnly m_log;
368
369 private:
370
371 typedef agx::HashTable<std::ostream*, NotifyLevel > StreamMap;
372 StreamMap m_streams;
373
375 CallbackMap m_callbacks;
376
377 std::ostringstream& getThreadStringStream();
378 const std::ostringstream& getThreadStringStream() const;
379
380 typedef Vector<PrintSelection> PrintSelectionStack;
381 AGX_DECLARE_POINTER_TYPES(ThreadData);
382 class ThreadData : public agx::Referenced {
383 public:
384 ThreadData();
385 NotifyLevel output_mode;
386 agx::String tag;
387 int line;
388 agx::String function;
389 agx::String file;
390 std::ostringstream stream;
391 NotifyLevel notify_level;
392
393 Vector<PrintSelectionStack> selection_stack;
394
395 protected:
396 virtual ~ThreadData();
397 };
398
399 ThreadData* getThreadData();
400 const ThreadData* getThreadData() const;
401
402 agx::LogStream m_logStream;
403
404 bool m_to_log_only;
405 bool m_throw_on_error;
406 bool m_break_on_error;
407
408 static Notify* s_instance;
409 std::ostream& m_outStream;
410 mutable agx::ReentrantMutex m_mutex;
411
412 };
413
414
415} // agx
416
417
418#define ADD_NOTIFY_FUNCTIONALITY_TO_CLASS() \
419 public:\
420 void debug( const agx::String& msg ) { Notify::instance()->debug(msg); };\
421 void info( const agx::String& msg ) { Notify::instance()->info(msg); };\
422 void warning( const agx::String& msg ) { Notify::instance()->warning(msg); };\
423 void error( const agx::String& msg ) { Notify::instance()->error(msg); };\
424 protected:\
425 void debug( const char* function, int line, const char* file, const agx::String& msg ) { Notify::instance()->debug(function,line,file,msg); };\
426 void info( const char* function, int line, const char* file, const agx::String& msg ) { Notify::instance()->info(function,line,file,msg); };\
427 void warning( const char* function, int line, const char* file, const agx::String& msg ) { Notify::instance()->warning(function,line,file,msg); };\
428 void error( const char* function, int line, const char* file, const agx::String& msg ) { Notify::instance()->error(function,line,file,msg); };\
429 ::agx::Notify::Push push() { return Notify::instance()->push(); };\
430 ::agx::Notify::End end() { return Notify::instance()->end(); };\
431 agx::String setDebugStrings( ::agx::Notify::NotifyLevel l, const char* function, int line, const char* file ) { return Notify::instance()->setDebugStrings(l,function,line,file); };\
432 public:\
433 ::agx::Notify& getNotify() {\
434 ::agx::Notify* n = Notify::instance();\
435 return *n;\
436 } \
437 const ::agx::Notify& getNotify() const {\
438 ::agx::Notify* n = Notify::instance();\
439 return *n;\
440}
441
442
443#ifdef AGX_DEBUG
444#define NOTIFY_POS_ARGS __FUNCTION__,__LINE__,__FILE__
445#else
446#define NOTIFY_POS_ARGS "",-1,""
447#endif
448
449#define NOTIFY() getNotify()
450#define NOTIFY_DEBUG() setDebugStrings(::agx::Notify::NOTIFY_DEBUG, NOTIFY_POS_ARGS)
451#define NOTIFY_INFO() setDebugStrings(::agx::Notify::NOTIFY_INFO, NOTIFY_POS_ARGS)
452#define NOTIFY_WARNING() setDebugStrings(::agx::Notify::NOTIFY_WARNING, NOTIFY_POS_ARGS)
453#define NOTIFY_ERROR() setDebugStrings(::agx::Notify::NOTIFY_ERROR, NOTIFY_POS_ARGS)
454#define NOTIFY_LOG() logOnly()
455#define NOTIFY_END() end()
456#define NOTIFY_CLEAR() clear()
457#define NOTIFY_STATE(X) push().setValue(X)
458
459
460#define NOTIFY_WARNING_IF_nullptr(X,Y) if ( Y == nullptr ) { X << X.NOTIFY_WARNING() << " nullptr pointer: " << #Y << std::endl << X.NOTIFY_END(); }
461#define NOTIFY_WARNING_IF_FALSE(X,Y) if ( !Y ) { X << X.NOTIFY_WARNING() << " Test false: " << #Y <<std::endl << X.NOTIFY_END(); }
462#define NOTIFY_WARNING_IF_TRUE(X,Y) if ( Y ) { X << X.NOTIFY_WARNING() << " Test true: " << #Y <<std::endl << X.NOTIFY_END(); }
463
464#define NOTIFY_ERROR_IF_nullptr(X,Y) if ( Y == nullptr ) { X << X.NOTIFY_STATE(::agx::Notify::PRINT_ALL) << X.NOTIFY_ERROR() << " nullptr pointer: " << #Y <<std::endl << X.NOTIFY_END(); }
465#define NOTIFY_ERROR_IF_FALSE(X,Y) if ( !Y ) { X << X.NOTIFY_STATE(::agx::Notify::PRINT_ALL) << X.NOTIFY_ERROR() << " Test false: " << #Y <<std::endl << X.NOTIFY_END(); }
466#define NOTIFY_ERROR_IF_TRUE(X,Y) if ( Y ) { X << X.NOTIFY_STATE(::agx::Notify::PRINT_ALL) << X.NOTIFY_ERROR() << " Test true: " << #Y <<std::endl << X.NOTIFY_END(); }
467
468
469#define NOTIFY_INSTANCE() ::agx::Notify::instance()
470
471
472
473#ifdef _MSC_VER
474# pragma warning(pop)
475#endif
476
#define NOTIFY_INFO()
Definition: Notify.h:451
#define NOTIFY_ERROR()
Definition: Notify.h:453
#define NOTIFY_CLEAR()
Definition: Notify.h:456
#define NOTIFY_DEBUG()
Definition: Notify.h:450
#define NOTIFY_WARNING()
Definition: Notify.h:452
#define NOTIFY_END()
Definition: Notify.h:455
#define AGX_DECLARE_POINTER_TYPES(type)
Definition: Referenced.h:254
std::ostream & operator<<(std::ostream &o, const agx::Vec6 &v)
Definition: Vec6.h:230
#define AGXCORE_EXPORT
Inheritance with partial specialization due to bug with ref_ptr containers.
Class for printing out messages to console, file, virtual method and or a callback function.
Definition: LogStream.h:45
Callback class, derive from this and Register to the notify singleton to get callbacks.
Definition: Notify.h:50
virtual ~NotifyCallback()
virtual void message(const agx::String &msg, int notifyLevel)=0
Virtual method called whenever there is a message ready.
Class for handling logging of messages.
Definition: Notify.h:64
static Notify * instance()
bool getToLogOnly() const
bool setNotifyLevel(NotifyCallback *callback, NotifyLevel l)
Set the notify level for a specific callback.
void addStream(std::ostream *stream, NotifyLevel l)
Add a stream that will be printed to if the notify level less or equal to l, the memory will NOT be m...
agx::LogStream & logStream()
void setLogNotifyLevel(NotifyLevel l)
Set the notify level for the LogStream.
NotifyLevel getNotifyLevel() const
NotifySelection
Definition: Notify.h:77
std::ostream & outStream()
void setBreakOnError(bool f)
WIN32 specific: If set to true, a breakpoint will be set in debug build.
bool getBreakOnError() const
bool removeCallback(NotifyCallback *callback)
Remove a callback from list of callbacks to report messages to.
bool setNotifyLevel(std::ostream *stream, NotifyLevel l)
Set the notify level for a specific stream.
const agx::LogStream & logStream() const
bool openLog(const agx::String &filename)
Open a log file (in the LogStream)
void setToLogOnly(bool f)
If f==true, logging will occur only to the LogStream, not to any of the associated ostreams.
NotifyLevel getOutputMode() const
void addCallback(NotifyCallback *callback, NotifyLevel l)
Add a callback class that will be printed to if the notify level less or equal to l.
void setNotifyLevel(NotifyLevel level)
Set the current notify level.
bool removeStream(std::ostream *stream)
Remove a stream from list of streams to report messages to.
void setThrowOnError(bool v)
Specify whether we should Throw an exception upon calling error?
Notify(std::ostream &out_stream=std::cerr)
Constructor.
bool getThrowOnError() const
void setOutputMode(NotifyLevel l)
Set the current output mode, do not use! (used internally)
Base class providing referencing counted objects.
Definition: Referenced.h:120
Base class for Singletons that should have its shutdown called explicitly before exit of the applicat...
Definition: Singleton.h:31
agx::Thread is a representation of an OS specific implementation of a computational thread.
Definition: Thread.h:200
Templated vector class.
Definition: agx/Vector.h:53
Smart pointer for handling referenced counted objects.
Definition: ref_ptr.h:30
#define DOXYGEN_END_INTERNAL_BLOCK()
Definition: macros.h:89
#define DOXYGEN_START_INTERNAL_BLOCK()
Definition: macros.h:88
Contains function for initialization and shutdown of agxCore library when agxPhysics is not used.
AGXTERRAIN_EXPORT void clear()
The agx namespace contains the dynamics/math part of the AGX Dynamics API.
LinearProbingHashSetImplementation< KeyT, HashT >::iterator end(LinearProbingHashSetImplementation< KeyT, HashT > &set)
std::recursive_mutex ReentrantMutex
Definition: Object.h:48
STL namespace.