1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkLoggerThreadWrapper_h
19 #define itkLoggerThreadWrapper_h
20 
21 #include <string>
22 #include <queue>
23 #include <thread>
24 
25 #include "itkObjectFactory.h"
26 #include <mutex>
27 
28 namespace itk
29 {
30 /** \class LoggerThreadWrapper
31  *  \brief Used for providing logging service as a separate thread.
32  *
33  * \author Hee-Su Kim, Compute Science Dept. Kyungpook National University,
34  *                     ISIS Center, Georgetown University.
35  *
36  * \ingroup OSSystemObjects LoggingObjects
37  * \ingroup ITKCommon
38  */
39 
40 template< typename SimpleLoggerType >
41 class ITK_TEMPLATE_EXPORT LoggerThreadWrapper:public SimpleLoggerType
42 {
43 public:
44 
45   using Self = LoggerThreadWrapper;
46   using Superclass = SimpleLoggerType;
47   using Pointer = SmartPointer< Self >;
48   using ConstPointer = SmartPointer< const Self >;
49 
50   /** Run-time type information (and related methods). */
51   itkTypeMacro(LoggerThreadWrapper, SimpleLoggerType);
52 
53   /** New macro for creation of through a Smart Pointer */
54   itkNewMacro(Self);
55 
56   using OutputType = typename SimpleLoggerType::OutputType;
57   using PriorityLevelType = typename SimpleLoggerType::PriorityLevelType;
58   using DelayType = unsigned int;
59 
60   /** Definition of types of operations for LoggerThreadWrapper. */
61   typedef enum {
62     SET_PRIORITY_LEVEL,
63     SET_LEVEL_FOR_FLUSHING,
64     ADD_LOG_OUTPUT,
65     WRITE
66     } OperationType;
67 
68   /** Set the priority level for the current logger. Only messages that have
69    * priorities equal or greater than the one set here will be posted to the
70    * current outputs */
71   void SetPriorityLevel(PriorityLevelType level) override;
72 
73   /** Get the priority level for the current logger. Only messages that have
74    * priorities equal or greater than the one set here will be posted to the
75    * current outputs */
76   PriorityLevelType GetPriorityLevel() const override;
77 
78   void SetLevelForFlushing(PriorityLevelType level) override;
79 
80   PriorityLevelType GetLevelForFlushing() const override;
81 
82 /** Set the delay in milliseconds between checks to see if there are any
83  *  low priority messages to be processed.
84  */
85   virtual void SetDelay(DelayType delay);
86 
87 /** Get the delay in milliseconds between checks to see if there are any
88  *  low priority messages to be processed.
89  */
90   virtual DelayType GetDelay() const;
91 
92   /** Registers another output stream with the multiple output. */
93   void AddLogOutput(OutputType *output) override;
94 
95   void Write(PriorityLevelType level, std::string const & content) override;
96 
97   void Flush() override;
98 
99 protected:
100 
101   /** Constructor */
102   LoggerThreadWrapper();
103 
104   /** Destructor */
105   ~LoggerThreadWrapper() override;
106 
107   /** Print contents of a LoggerThreadWrapper */
108   void PrintSelf(std::ostream & os, Indent indent) const override;
109 
110   void ThreadFunction();
111 
112 private:
113 
114   using OperationContainerType = std::queue< OperationType >;
115 
116   using MessageContainerType = std::queue< std::string >;
117 
118   using LevelContainerType = std::queue< PriorityLevelType >;
119 
120   using OutputContainerType = std::queue< typename OutputType::Pointer >;
121 
122   std::thread m_Thread;
123 
124   bool m_TerminationRequested;
125 
126   OperationContainerType m_OperationQ;
127 
128   MessageContainerType m_MessageQ;
129 
130   LevelContainerType m_LevelQ;
131 
132   OutputContainerType m_OutputQ;
133 
134   mutable std::mutex m_Mutex;
135 
136   DelayType m_Delay;
137 
138 };  // class LoggerThreadWrapper
139 } // namespace itk
140 
141 #ifndef ITK_MANUAL_INSTANTIATION
142 #include "itkLoggerThreadWrapper.hxx"
143 #endif
144 
145 #endif  // itkLoggerThreadWrapper_h
146