Ocean
Messenger.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_MESSENGER_H
9 #define META_OCEAN_BASE_MESSENGER_H
10 
11 #include "ocean/base/Base.h"
12 #include "ocean/base/Lock.h"
13 #include "ocean/base/Singleton.h"
14 #include "ocean/base/String.h"
15 
16 #include <fstream>
17 #include <iostream>
18 #include <queue>
19 #include <ostream>
20 
21 namespace Ocean
22 {
23 
24 /**
25  * This class implements a messenger for information, warning or error messages.
26  * Posted messages are stored in internal message queues or referred to a specified output file.<br>
27  * Therefore, applications interested in live messaging have to pop the queued messages recurrently.
28  *
29  * There different message types are supported dividing all messages related to their magnitude:
30  * Error messages hold critical informations which influence the major program progress directly.<br>
31  * Warning messages hold informations which can influence minor program progresses, however they are not critical.<br>
32  * Information messages hold interesting informations for the user only.<br>
33  * Meaning that error messages should be informed to the user immediately, instead information messages can be informed to the user.<br>
34  * Additionally, each message can provide a location specifying e.g. the sender module.
35  *
36  * Applications interested in messages use the Messenger object implemented as singleton to receive messages.
37  * Modules use the MessageObject objects to post new messages.<br>
38  * Three basic message types are defined: error, warning and info.
39  * @see SpecificMessenger.
40  *
41  * Tutorial explaining the usage on application side:
42  * @code
43  * #include "ocean/base/Messenger.h"
44  *
45  * // Function called by e.g. a timer recurrently.
46  * void timer()
47  * {
48  * if (Messenger::get().empty() == false)
49  * {
50  * // Strings which will receive the popped informations
51  * std::string message, location;
52  *
53  * // Boolean which will receive whether the information has been posted more than one time.
54  * bool isNew;
55  *
56  * // Pop all error messages
57  * while (Messenger::get().popError(location, message, isNew))
58  * {
59  * // Writes the error message to any application output window.
60  * writeToErrorOutputWindow(location, message);
61  * }
62  *
63  * // Pop all warning messages
64  * while (Messenger::get().popWarning(location, message, isNew))
65  * {
66  * // Writes the warning message to any application output window.
67  * writeToWarningOutputWindow(location, message);
68  * }
69  * }
70  * }
71  * @endcode
72  *
73  * Tutorial explaining the usage on module side:
74  * @code
75  * #include "ocean/base/Messenger.h"
76  *
77  * // Any function which will post a message.
78  * void anyFunction()
79  * {
80  * // A function calculating something
81  * int value = calculate();
82  *
83  * // suppose a resulting value of '0' is a failure
84  * if (value == 0)
85  * Log::error() << "The calculation failed.";
86  * else
87  * Log::info() << "The calculation returned \"" << value << \" which is great!";
88  * }
89  * @endcode
90  * @ingroup base
91  */
92 class OCEAN_BASE_EXPORT Messenger : public Singleton<Messenger>
93 {
94  /// Friend class
95  friend class Singleton<Messenger>;
96 
97  public:
98 
99  /**
100  * Definition of different message types.
101  */
102  enum MessageType : uint32_t
103  {
104  /// Invalid message type.
105  TYPE_UNDEFINED = 0u,
106  /// Debug message, which are not used on release builds (optimized out of the code).
108  /// Information message.
110  /// Warning message.
112  /// Error message.
113  TYPE_ERROR
114  };
115 
116  /**
117  * Definition of different message output types.
118  */
119  enum MessageOutput : uint32_t
120  {
121  /// All messages will be discarded.
122  OUTPUT_DISCARDED = 0u,
123  /// All messages are directed to the standard output immediately.
124  OUTPUT_STANDARD = 1u << 0u,
125  /// All messages are queued and must be popped from the message stack explicitly.
126  OUTPUT_QUEUED = 1u << 1u,
127  /// All messages are directed to a debug window.
128  OUTPUT_DEBUG_WINDOW = 1u << 2u,
129  /// All messages are directed to a file immediately.
130  OUTPUT_FILE = 1u << 3u,
131  /// All messages are directed to an arbitrary stream immediately.
132  OUTPUT_STREAM = 1u << 4u,
133  /// All messages are directed to the maintenance manager.
134  OUTPUT_MAINTENANCE = 1u << 5u
135  };
136 
137  protected:
138 
139  /**
140  * Definition of a message.
141  */
142  typedef std::pair<std::string, std::string> Message;
143 
144  /**
145  * Definition of a message queue.
146  */
147  typedef std::queue<Message> MessageQueue;
148 
149  public:
150 
151  /**
152  * Pushes a new message into the message queue.
153  * @param type The type of the message
154  * @param location The location of the message
155  * @param message The text message
156  */
157  void push(const MessageType type, std::string&& location, std::string&& message);
158 
159  /**
160  * Pops the first debug message from the message queue.
161  * @param location The resulting location of the message
162  * @param message The resulting text message
163  * @param isNew Optional returning flag determining whether this message is not identical to the last one
164  * @return True, if a message could be popped
165  */
166  bool popDebug(std::string& location, std::string& message, bool* isNew = nullptr);
167 
168  /**
169  * Pops the first information message from the message queue.
170  * @param location The resulting location of the message
171  * @param message The resulting text message
172  * @param isNew Optional returning flag determining whether this message is not identical to the last one
173  * @return True, if a message could be popped
174  */
175  bool popInformation(std::string& location, std::string& message, bool* isNew = nullptr);
176 
177  /**
178  * Pops the first warning message from the message queue.
179  * @param location The resulting location of the message
180  * @param message The resulting test message
181  * @param isNew Returning flag determining whether this message is not identical to the last one
182  * @return True, if a message could be popped
183  */
184  bool popWarning(std::string& location, std::string& message, bool* isNew = nullptr);
185 
186  /**
187  * Pops the first error message from the message queue.
188  * @param location The resulting location of the message
189  * @param message The resulting text message
190  * @param isNew Returning flag determining whether this message is not identical to the last one
191  * @return True, if a message could be popped
192  */
193  bool popError(std::string& location, std::string& message, bool* isNew = nullptr);
194 
195  /**
196  * Pops any first message available of a given type or of any type.<br>
197  * If several messages with different types are available and an undefined type is defined the pop order is: errors, warnings, informations.
198  * @param type The type of the message to pop, may be TYPE_UNDEFINED to return any message while 'type' will be set to the type of the message which is returned
199  * @param location The resulting location of the message
200  * @param message The resulting text message
201  * @param isNew Optional returning flag determining whether this message is not identical to the previous one
202  * @return True, if a message existed
203  */
204  bool popMessage(MessageType& type, std::string& location, std::string& message, bool* isNew = nullptr);
205 
206  /**
207  * Pops the oldest message available of a specified type.
208  * @param type The type of the message to return, TYPE_UNDEFINED to return a message with any type
209  * @param isNew Optional resulting state determining whether the message is not identical to the previous one
210  * @return The resulting message with format "Type: Location, Message", an empty string if no message is available
211  */
212  std::string popMessage(const MessageType type = TYPE_UNDEFINED, bool* isNew = nullptr);
213 
214  /**
215  * Sets the output type of the messenger.
216  * @param type Output type to set
217  * @return True, if succeeded
218  * @see setFileOutput(), setOutputStream().
219  */
220  bool setOutputType(const MessageOutput type);
221 
222  /**
223  * Sets the message output to a file.
224  * All messages will be redirected to the specified file instead of inserted into the message queue.
225  * @param filename Name of the output file, use an empty filename to disable file output
226  * @return True, if succeeded
227  * @see setOutputType().
228  */
229  bool setFileOutput(const std::string& filename);
230 
231  /**
232  * Sets the message output to an output stream.
233  * All messages will be redirected to the specified output stream instead of inserted into the message queue.
234  * @param stream Output stream
235  * @return True, if succeeded
236  * @see setOutputType().
237  */
238  bool setOutputStream(std::ostream& stream);
239 
240  /**
241  * Enables or disables the integration of local date/time information into the location information of messages.
242  * @param state True, to enable the integration of the date/time information
243  * @see integrateDateTime().
244  */
245  void setIntegrateDateTime(const bool state);
246 
247  /**
248  * Flushes the current message stack to a given output stream, the output type is unchanged.
249  * @param stream Output stream
250  */
251  void flush(std::ostream& stream);
252 
253  /**
254  * Clears all message queues.
255  */
256  void clear();
257 
258  /**
259  * Clears the information message queue.
260  */
262 
263  /**
264  * Clears the warning message queue.
265  */
267 
268  /**
269  * Clears the error message queue.
270  */
271  void clearErrors();
272 
273  /**
274  * Returns the output type of the messenger.
275  * @return Current output type
276  */
277  inline MessageOutput outputType() const;
278 
279  /**
280  * Returns the number of waiting information messages.
281  * @return Number of messages
282  */
283  inline size_t informations() const;
284 
285  /**
286  * Returns the number of waiting information messages.
287  * @return Number of messages
288  */
289  inline size_t warnings() const;
290 
291  /**
292  * Returns the number of waiting information messages.
293  * @return Number of messages
294  */
295  inline size_t errors() const;
296 
297  /**
298  * Returns whether the date/time integration is activated.
299  * By default the date time integration is deactivated.
300  * @return True, if so
301  * @see setIntegrateDateTime().
302  */
303  inline bool integrateDateTime() const;
304 
305  /**
306  * Returns whether no message exists.
307  * @return True, if so
308  */
309  inline bool empty() const;
310 
311  /**
312  * Writes a message to the most suitable debug output of the current platform.
313  * This function is just a simple way to create a debug message without needing to configure the Messenger.
314  * @param message The message to write
315  */
316  static void writeToDebugOutput(const std::string& message);
317 
318  /**
319  * Returns whether the messenger is active on this build.
320  * @return True, if so; False, to strip away every message related information in the binary
321  */
322  static constexpr bool isActive();
323 
324  /**
325  * Returns whether the messenger is used on a debug build.
326  * @return True, if so
327  */
328  static constexpr bool isDebugBuild();
329 
330  protected:
331 
332  /**
333  * Creates a new messenger object queuing all messages as default.
334  */
336 
337  /**
338  * Destructs a messenger object.
339  */
341 
342  protected:
343 
344  /// Message output type.
345  MessageOutput outputType_ = OUTPUT_STANDARD;
346 
347 #ifdef OCEAN_DEBUG
348  /// Debug message queue.
350 
351  /// Last debug message.
352  std::string lastDebugMessage_;
353 #endif
354 
355  /// Information message queue.
357 
358  /// Warning message queue.
360 
361  /// Error message queue.
363 
364  /// Last information message.
366 
367  /// Last warning message.
368  std::string lastWarningMessage_;
369 
370  /// Last error message.
371  std::string lastErrorMessage_;
372 
373  /// File output stream
374  std::ofstream fileOutputStream_;
375 
376  /// Explicit output stream, if any
377  std::ostream* outputStream_ = nullptr;
378 
379  /// Date and time integration state.
380  bool integrateDateTime_ = false;
381 
382  /// Messenger lock.
383  mutable Lock lock_;
384 
385  /// Maximum number of messages.
386  static constexpr unsigned int maxMessages_ = 5000u;
387 
388 #if defined(__APPLE__)
389 
390  /**
391  * Write message to Apple-specific log facility.
392  * @sa push()
393  * @param message The message to be written into NSLog
394  */
395  static void writeMessageToDebugWindowApple(const std::string& message);
396 
397 #endif // defined(__APPLE__)
398 };
399 
400 constexpr bool Messenger::isActive()
401 {
402 #ifdef OCEAN_DEACTIVATED_MESSENGER
403  return false;
404 #else
405  return true;
406 #endif
407 }
408 
409 constexpr bool Messenger::isDebugBuild()
410 {
411 #ifdef OCEAN_DEBUG
412  return true;
413 #else
414  return false;
415 #endif
416 }
417 
418 /**
419  * Messenger object, one object for each message.
420  * This class is a helper class only, therefore there is no need to use it directly.<br>
421  * @tparam tActive True, if the message object is active; False, e.g., on builds in which messages must not appear in binary files
422  * @see Messenger.
423  * @ingroup base
424  */
425 template <bool tActive>
427 {
428  public:
429 
430  /**
431  * Re-definition of MessageType
432  */
434 
435  public:
436 
437  /**
438  * Creates a new message object.
439  * @param type The type of the message object
440  */
441  inline explicit MessageObject(const MessageType type);
442 
443  /**
444  * Creates a new message object.
445  * @param type The type of the message object
446  * @param location The location of the message
447  */
448  inline MessageObject(const MessageType type, std::string&& location);
449 
450  /**
451  * Copy-constructs a new message object.
452  * @param messageObject Another instance that will be used to create this instance, must be valid
453  */
454  MessageObject(const MessageObject& messageObject) = default;
455 
456  /**
457  * Destructs a message object.
458  */
459  inline ~MessageObject();
460 
461  /**
462  * Adds a new line to this message object if a specified condition holds.
463  * @param condition True, to add the line; False, to do nothing
464  * @return Reference to this object
465  */
466  inline MessageObject& newLine(const bool condition = true);
467 
468  /**
469  * Pushes another information message.
470  * @param message The message to push
471  * @return Reference to this object
472  */
473  inline MessageObject& operator<<(std::string&& message);
474 
475  /**
476  * Pushes another information message.
477  * @param message The message to push
478  * @return Reference to this object
479  */
480  inline MessageObject& operator<<(const std::string& message);
481 
482  /**
483  * Pushes another information message.
484  * @param message The message to push
485  * @return Reference to this object
486  */
487  inline MessageObject& operator<<(const char* message);
488 
489  /**
490  * Pushes another information message.
491  * @param message The message to push
492  * @return Reference to this object
493  */
494  inline MessageObject& operator<<(const double message);
495 
496  /**
497  * Pushes another information message.
498  * @param message The message to push
499  * @return Reference to this object
500  */
501  inline MessageObject& operator<<(const float message);
502 
503  /**
504  * Pushes another information message.
505  * @param message The message to push
506  * @return Reference to this object
507  */
508  inline MessageObject& operator<<(const int message);
509 
510  /**
511  * Pushes another information message.
512  * @param message The message to push
513  * @return Reference to this object
514  */
515  inline MessageObject& operator<<(const unsigned int message);
516 
517  /**
518  * Pushes another information message.
519  * @param message The message to push
520  * @return Reference to this object
521  */
522  inline MessageObject& operator<<(const long message);
523 
524  /**
525  * Pushes another information message.
526  * @param message The message to push
527  * @return Reference to this object
528  */
529  inline MessageObject& operator<<(const long long message);
530 
531  /**
532  * Pushes another information message.
533  * @param message The message to push
534  * @return Reference to this object
535  */
536  inline MessageObject& operator<<(const unsigned long long message);
537 
538  /**
539  * Pushes another information message.
540  * @param message The message to push
541  * @return Reference to this object
542  */
543  inline MessageObject& operator<<(const long unsigned int message);
544 
545  /**
546  * Pushes another information message.
547  * @param message The message to push
548  */
549  inline void operator<<(const MessageObject& message);
550 
551  /**
552  * Assign operator
553  * @param messageObject Another instance that will assigned to this instance, must be valid
554  */
555  MessageObject& operator=(const MessageObject& messageObject) = default;
556 
557  protected:
558 
559  /**
560  * Creates a new message object.
561  * @param type The type of the message object
562  * @param location The location of the message object
563  * @param message The message of the object
564  */
565  inline MessageObject(const MessageType type, std::string&& location, std::string&& message);
566 
567  protected:
568 
569  /// Entire message.
570  std::string message_;
571 
572  /// Location of the message.
573  std::string location_;
574 
575  /// Type of this messenger.
577 };
578 
579 /**
580  * Specialization of MessageObject.
581  * Inactive messenger object to strip away any messenger related information in binary.
582  * @see Messenger.
583  * @ingroup base
584  */
585 template <>
586 class MessageObject<false>
587 {
588  public:
589 
590  /**
591  * Re-definition of MessageType
592  */
594 
595  public:
596 
597  /**
598  * Creates a new message object.
599  */
600  explicit inline MessageObject(const MessageType /*type*/)
601  {
602  // nothing to do here
603  }
604 
605  /**
606  * Creates a new message object.
607  */
608  inline MessageObject(const MessageType /*type*/, std::string&& /*location*/)
609  {
610  // nothing to do here
611  }
612 
613  /**
614  * Copy-constructs a new message object.
615  * @param messageObject Another instance that will be used to create this instance, must be valid
616  */
617  MessageObject(const MessageObject& messageObject) = default;
618 
619  /**
620  * Destructs a message object.
621  */
622  ~MessageObject() = default;
623 
624  /**
625  * Adds a new line to this message object if a specified condition holds.
626  * @return Reference to this object
627  */
629  {
630  return *this;
631  }
632 
633  /**
634  * Adds a new line to this message object if a specified condition holds.
635  * @return Reference to this object
636  */
637  inline MessageObject& newLine(const bool /*condition*/)
638  {
639  return *this;
640  }
641 
642  /**
643  * Pushes another information message.
644  * @return Reference to this object
645  */
646  inline MessageObject& operator<<(std::string&& /*message*/)
647  {
648  return *this;
649  }
650 
651  /**
652  * Pushes another information message.
653  * @return Reference to this object
654  */
655  inline MessageObject& operator<<(const std::string& /*message*/)
656  {
657  return *this;
658  }
659 
660  /**
661  * Pushes another information message.
662  * @return Reference to this object
663  */
664  inline MessageObject& operator<<(const char* /*message*/)
665  {
666  return *this;
667  }
668 
669  /**
670  * Pushes another information message.
671  * @return Reference to this object
672  */
673  inline MessageObject& operator<<(const double /*message*/)
674  {
675  return *this;
676  }
677 
678  /**
679  * Pushes another information message.
680  * @return Reference to this object
681  */
682  inline MessageObject& operator<<(const float /*message*/)
683  {
684  return *this;
685  }
686 
687  /**
688  * Pushes another information message.
689  * @return Reference to this object
690  */
691  inline MessageObject& operator<<(const int /*message*/)
692  {
693  return *this;
694  }
695 
696  /**
697  * Pushes another information message.
698  * @return Reference to this object
699  */
700  inline MessageObject& operator<<(const unsigned int /*message*/)
701  {
702  return *this;
703  }
704 
705  /**
706  * Pushes another information message.
707  * @return Reference to this object
708  */
709  inline MessageObject& operator<<(const long /*message*/)
710  {
711  return *this;
712  }
713 
714  /**
715  * Pushes another information message.
716  * @return Reference to this object
717  */
718  inline MessageObject& operator<<(const long long /*message*/)
719  {
720  return *this;
721  }
722 
723  /**
724  * Pushes another information message.
725  * @return Reference to this object
726  */
727  inline MessageObject& operator<<(const unsigned long long /*message*/)
728  {
729  return *this;
730  }
731 
732  /**
733  * Pushes another information message.
734  * @return Reference to this object
735  */
736  inline MessageObject& operator<<(const long unsigned int /*message*/)
737  {
738  return *this;
739  }
740 
741  /**
742  * Pushes another information message.
743  */
744  inline void operator<<(const MessageObject& /*message*/)
745  {
746  // nothing to do here
747  }
748 
749  /**
750  * Assign operator
751  * @param messageObject Another instance that will assigned to this instance, must be valid
752  */
753  MessageObject& operator=(const MessageObject& messageObject) = default;
754 
755  protected:
756 
757  /**
758  * Creates a new message object.
759  */
760  inline MessageObject(const MessageType /*type*/, std::string&& /*location*/, std::string&& /*message*/)
761  {
762  // nothing to do here
763  }
764 };
765 
766 /**
767  * This class provides access to three different Message objects, e.g., for regular information, warnings, or errors.
768  * @ingroup base
769  */
770 class OCEAN_BASE_EXPORT Log
771 {
772  public:
773 
774  /**
775  * Definition of a default message object, only active if `Messenger::isActive() == true`.
776  */
778 
779  /**
780  * Definition of a debug message object, only active on debug builds and if `Messenger::isActive() == true`.
781  */
783 
784  protected:
785 
786  /**
787  * Helper class allowing to specify a specific message object or stream type.
788  * @tparam TStream The data type of the message object (or stream) to be checked
789  */
790  template <typename TStream>
792  {
793  /**
794  * Helper class to check whether a message object or a stream provides a shift operator for an object with specific data type.
795  * @tparam TObject The data type to check
796  */
797  template <typename TObject, typename = void>
799  {
800  /// False, if the message object or stream does not provide a shift operator for the data type 'TObject'.
801  static constexpr bool value = false;
802  };
803 
804  /**
805  * Helper class to check whether a message object or a stream provides a shift operator for an object with specific data type.
806  * Specialization of ShiftOperatorChecker.
807  * @tparam TObject The data type to check
808  */
809  template <typename TObject>
810  struct ShiftOperatorChecker<TObject, std::void_t<decltype( std::declval<TStream&>() << std::declval<TObject>())>>
811  {
812  /// True, if the message object or stream does provides a shift operator for the data type 'TObject'.
813  static constexpr bool value = true;
814  };
815  };
816 
817  public:
818 
819  /**
820  * Returns the message for debug messages.
821  * Debug messages do not show up on release builds.<br>
822  * The debug log is intended to simplify code like this:
823  * @code
824  * #ifdef OCEAN_DEBUG
825  * info() << "<debug> This message shows up on debug builds only."
826  * #endif
827  * @endcode
828  * @return The message object that will be stripped away on release builds
829  */
830  static inline DebugMessageObject debug();
831 
832  /**
833  * Returns the message for information messages.
834  * @return The message object
835  */
836  static inline MessageObject info();
837 
838  /**
839  * Returns the message for warning messages.
840  * @return The message object
841  */
842  static inline MessageObject warning();
843 
844  /**
845  * Returns the message for error messages.
846  * @return The message object
847  */
848  static inline MessageObject error();
849 
850  /**
851  * Returns whether a specific data type can be written to a message object (or an arbitrary stream).
852  * The function returns whether the shift operator of MessageObject (or of an arbitrary stream) supports the specified data type.
853  * Usage:
854  * @code
855  * void function()
856  * {
857  * int value = 9;
858  *
859  * if constexpr (Log::isSupported<int>())
860  * {
861  * Log::info() << "Value is: " << value;
862  * }
863  * else
864  * {
865  * Log::info() << "Value cannot be written to log.";
866  * }
867  * }
868  * @endcode
869  * @return True, if so
870  * @tparam T The data type to be checked
871  * @tparam TStream The data type of the message object (or stream) to be checked
872  */
873  template <typename T, typename TStream = MessageObject>
874  static constexpr bool isSupported();
875 };
876 
877 inline Messenger::MessageOutput Messenger::outputType() const
878 {
879  const ScopedLock scopedLock(lock_);
880  return outputType_;
881 }
882 
883 inline size_t Messenger::informations() const
884 {
885  const ScopedLock scopedLock(lock_);
886  return informationMessageQueue_.size();
887 }
888 
889 inline size_t Messenger::warnings() const
890 {
891  const ScopedLock scopedLock(lock_);
892  return warningMessageQueue_.size();
893 }
894 
895 inline size_t Messenger::errors() const
896 {
897  const ScopedLock scopedLock(lock_);
898  return errorMessageQueue_.size();
899 }
900 
901 inline bool Messenger::integrateDateTime() const
902 {
903  const ScopedLock scopedLock(lock_);
904  return integrateDateTime_;
905 }
906 
907 inline bool Messenger::empty() const
908 {
909  const ScopedLock scopedLock(lock_);
910  return informationMessageQueue_.empty() && warningMessageQueue_.empty() && errorMessageQueue_.empty();
911 }
912 
913 template <bool tActive>
914 inline MessageObject<tActive>::MessageObject(const MessageType type) :
915  type_(type)
916 {
917  // nothing to do here
918 }
919 
920 template <bool tActive>
921 inline MessageObject<tActive>::MessageObject(const MessageType type, std::string&& location) :
922  location_(std::move(location)),
923  type_(type)
924 {
925  // nothing to do here
926 }
927 
928 template <bool tActive>
929 inline MessageObject<tActive>::MessageObject(const MessageType type, std::string&& location, std::string&& message) :
930  message_(std::move(message)),
931  location_(std::move(location)),
932  type_(type)
933 {
934  // nothing to do here
935 }
936 
937 template <bool tActive>
938 inline MessageObject<tActive>::~MessageObject()
939 {
940  if (!message_.empty())
941  {
942  Messenger::get().push(type_, std::move(location_), std::move(message_));
943  }
944 }
945 
946 template <bool tActive>
947 inline MessageObject<tActive>& MessageObject<tActive>::newLine(const bool condition)
948 {
949  if (condition)
950  {
951  message_ += "\n";
952  }
953 
954  return *this;
955 }
956 
957 template <bool tActive>
958 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(std::string&& message)
959 {
960  if (message_.empty())
961  {
962  message_ = std::move(message);
963  }
964  else
965  {
966  message_ += message;
967  }
968 
969  return *this;
970 }
971 
972 template <bool tActive>
973 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const std::string& message)
974 {
975  message_ += message;
976  return *this;
977 }
978 
979 template <bool tActive>
980 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const char* message)
981 {
982  if (message != nullptr)
983  {
984  message_ += std::string(message);
985  }
986 
987  return *this;
988 }
989 
990 template <bool tActive>
991 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const double message)
992 {
993  message_ += String::toAString(message);
994  return *this;
995 }
996 
997 template <bool tActive>
998 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const float message)
999 {
1000  message_ += String::toAString(message);
1001  return *this;
1002 }
1003 
1004 template <bool tActive>
1005 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const int message)
1006 {
1007  message_ += String::toAString(message);
1008  return *this;
1009 }
1010 
1011 template <bool tActive>
1012 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const unsigned int message)
1013 {
1014  message_ += String::toAString(message);
1015  return *this;
1016 }
1017 
1018 template <bool tActive>
1019 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const long message)
1020 {
1021  message_ += String::toAString(message);
1022  return *this;
1023 }
1024 
1025 template <bool tActive>
1026 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const long long message)
1027 {
1028  message_ += String::toAString(message);
1029  return *this;
1030 }
1031 
1032 template <bool tActive>
1033 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const unsigned long long message)
1034 {
1035  message_ += String::toAString(message);
1036  return *this;
1037 }
1038 
1039 template <bool tActive>
1040 inline MessageObject<tActive>& MessageObject<tActive>::operator<<(const long unsigned int message)
1041 {
1042  message_ += String::toAString(message);
1043  return *this;
1044 }
1045 
1046 template <bool tActive>
1047 inline void MessageObject<tActive>::operator<<(const MessageObject<tActive>& messageObject)
1048 {
1049  ocean_assert_and_suppress_unused(messageObject.type_ == Messenger::TYPE_UNDEFINED, messageObject);
1050 
1051  if (!message_.empty())
1052  {
1053  Messenger::get().push(type_, std::string(location_), std::move(message_));
1054  }
1055 
1056  message_.clear();
1057 }
1058 
1059 inline Log::DebugMessageObject Log::debug()
1060 {
1061  return DebugMessageObject(Messenger::TYPE_DEBUG);
1062 }
1063 
1064 inline Log::MessageObject Log::info()
1065 {
1066  return MessageObject(Messenger::TYPE_INFORMATION);
1067 }
1068 
1069 inline Log::MessageObject Log::warning()
1070 {
1071  return MessageObject(Messenger::TYPE_WARNING);
1072 }
1073 
1074 inline Log::MessageObject Log::error()
1075 {
1076  return MessageObject(Messenger::TYPE_ERROR);
1077 }
1078 
1079 template <typename T, typename TStream>
1080 constexpr bool Log::isSupported()
1081 {
1082  return StreamHelper<TStream>::template ShiftOperatorChecker<T>::value;
1083 }
1084 
1085 }
1086 
1087 #endif // META_OCEAN_BASE_MESSENGER_H
This class implements a recursive lock object.
Definition: Lock.h:31
This class provides access to three different Message objects, e.g., for regular information,...
Definition: Messenger.h:771
Ocean::MessageObject< Messenger::isActive() &&Messenger::isDebugBuild()> DebugMessageObject
Definition of a debug message object, only active on debug builds and if Messenger::isActive() == tru...
Definition: Messenger.h:782
Ocean::MessageObject< Messenger::isActive()> MessageObject
Definition of a default message object, only active if Messenger::isActive() == true.
Definition: Messenger.h:777
MessageObject & operator<<(const long)
Pushes another information message.
Definition: Messenger.h:709
MessageObject(const MessageObject &messageObject)=default
Copy-constructs a new message object.
MessageObject & operator<<(std::string &&)
Pushes another information message.
Definition: Messenger.h:646
MessageObject & operator<<(const long unsigned int)
Pushes another information message.
Definition: Messenger.h:736
MessageObject(const MessageType)
Creates a new message object.
Definition: Messenger.h:600
MessageObject & operator<<(const std::string &)
Pushes another information message.
Definition: Messenger.h:655
MessageObject & operator<<(const float)
Pushes another information message.
Definition: Messenger.h:682
void operator<<(const MessageObject &)
Pushes another information message.
Definition: Messenger.h:744
MessageObject & newLine(const bool)
Adds a new line to this message object if a specified condition holds.
Definition: Messenger.h:637
MessageObject & operator<<(const double)
Pushes another information message.
Definition: Messenger.h:673
MessageObject & operator<<(const unsigned int)
Pushes another information message.
Definition: Messenger.h:700
MessageObject & operator<<(const unsigned long long)
Pushes another information message.
Definition: Messenger.h:727
MessageObject & operator<<(const int)
Pushes another information message.
Definition: Messenger.h:691
MessageObject & operator<<(const char *)
Pushes another information message.
Definition: Messenger.h:664
~MessageObject()=default
Destructs a message object.
MessageObject(const MessageType, std::string &&)
Creates a new message object.
Definition: Messenger.h:608
MessageObject(const MessageType, std::string &&, std::string &&)
Creates a new message object.
Definition: Messenger.h:760
MessageObject & operator<<(const long long)
Pushes another information message.
Definition: Messenger.h:718
MessageObject & newLine()
Adds a new line to this message object if a specified condition holds.
Definition: Messenger.h:628
MessageObject & operator=(const MessageObject &messageObject)=default
Assign operator.
Messenger object, one object for each message.
Definition: Messenger.h:427
MessageObject & operator=(const MessageObject &messageObject)=default
Assign operator.
std::string message_
Entire message.
Definition: Messenger.h:570
std::string location_
Location of the message.
Definition: Messenger.h:573
MessageObject & newLine(const bool condition=true)
Adds a new line to this message object if a specified condition holds.
Definition: Messenger.h:947
MessageObject & operator<<(std::string &&message)
Pushes another information message.
Definition: Messenger.h:958
MessageObject(const MessageObject &messageObject)=default
Copy-constructs a new message object.
MessageObject(const MessageType type)
Creates a new message object.
Definition: Messenger.h:914
~MessageObject()
Destructs a message object.
Definition: Messenger.h:938
Messenger::MessageType type_
Type of this messenger.
Definition: Messenger.h:576
This class implements a messenger for information, warning or error messages.
Definition: Messenger.h:93
static constexpr bool isActive()
Returns whether the messenger is active on this build.
Definition: Messenger.h:400
std::string lastErrorMessage_
Last error message.
Definition: Messenger.h:371
static constexpr bool isDebugBuild()
Returns whether the messenger is used on a debug build.
Definition: Messenger.h:409
MessageQueue informationMessageQueue_
Information message queue.
Definition: Messenger.h:356
bool popMessage(MessageType &type, std::string &location, std::string &message, bool *isNew=nullptr)
Pops any first message available of a given type or of any type.
Lock lock_
Messenger lock.
Definition: Messenger.h:383
std::queue< Message > MessageQueue
Definition of a message queue.
Definition: Messenger.h:147
MessageQueue errorMessageQueue_
Error message queue.
Definition: Messenger.h:362
void setIntegrateDateTime(const bool state)
Enables or disables the integration of local date/time information into the location information of m...
void clearInformations()
Clears the information message queue.
void clearWarnings()
Clears the warning message queue.
bool popDebug(std::string &location, std::string &message, bool *isNew=nullptr)
Pops the first debug message from the message queue.
MessageOutput
Definition of different message output types.
Definition: Messenger.h:120
std::string lastWarningMessage_
Last warning message.
Definition: Messenger.h:368
bool setOutputStream(std::ostream &stream)
Sets the message output to an output stream.
void clear()
Clears all message queues.
std::ofstream fileOutputStream_
File output stream.
Definition: Messenger.h:374
MessageQueue debugMessageQueue_
Debug message queue.
Definition: Messenger.h:349
static void writeToDebugOutput(const std::string &message)
Writes a message to the most suitable debug output of the current platform.
std::pair< std::string, std::string > Message
Definition of a message.
Definition: Messenger.h:142
MessageQueue warningMessageQueue_
Warning message queue.
Definition: Messenger.h:359
MessageType
Definition of different message types.
Definition: Messenger.h:103
@ TYPE_INFORMATION
Information message.
Definition: Messenger.h:109
@ TYPE_WARNING
Warning message.
Definition: Messenger.h:111
@ TYPE_DEBUG
Debug message, which are not used on release builds (optimized out of the code).
Definition: Messenger.h:107
@ TYPE_UNDEFINED
Invalid message type.
Definition: Messenger.h:105
std::string popMessage(const MessageType type=TYPE_UNDEFINED, bool *isNew=nullptr)
Pops the oldest message available of a specified type.
~Messenger()
Destructs a messenger object.
std::string lastDebugMessage_
Last debug message.
Definition: Messenger.h:352
static void writeMessageToDebugWindowApple(const std::string &message)
Write message to Apple-specific log facility.
void flush(std::ostream &stream)
Flushes the current message stack to a given output stream, the output type is unchanged.
void push(const MessageType type, std::string &&location, std::string &&message)
Pushes a new message into the message queue.
bool setOutputType(const MessageOutput type)
Sets the output type of the messenger.
bool popWarning(std::string &location, std::string &message, bool *isNew=nullptr)
Pops the first warning message from the message queue.
bool setFileOutput(const std::string &filename)
Sets the message output to a file.
void clearErrors()
Clears the error message queue.
Messenger()
Creates a new messenger object queuing all messages as default.
std::string lastInformationMessage_
Last information message.
Definition: Messenger.h:365
bool popInformation(std::string &location, std::string &message, bool *isNew=nullptr)
Pops the first information message from the message queue.
bool popError(std::string &location, std::string &message, bool *isNew=nullptr)
Pops the first error message from the message queue.
This template class is the base class for all singleton objects.
Definition: Singleton.h:71
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15
Helper class to check whether a message object or a stream provides a shift operator for an object wi...
Definition: Messenger.h:799
Helper class allowing to specify a specific message object or stream type.
Definition: Messenger.h:792