1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 
5 #ifndef OPENCV_TRACE_HPP
6 #define OPENCV_TRACE_HPP
7 
8 #include <opencv2/core/cvdef.h>
9 
10 namespace cv {
11 namespace utils {
12 namespace trace {
13 
14 //! @addtogroup core_logging
15 //! @{
16 
17 //! Macro to trace function
18 #define CV_TRACE_FUNCTION()
19 
20 #define CV_TRACE_FUNCTION_SKIP_NESTED()
21 
22 //! Trace code scope.
23 //! @note Dynamic names are not supported in this macro (on stack or heap). Use string literals here only, like "initialize".
24 #define CV_TRACE_REGION(name_as_static_string_literal)
25 //! mark completed of the current opened region and create new one
26 //! @note Dynamic names are not supported in this macro (on stack or heap). Use string literals here only, like "step1".
27 #define CV_TRACE_REGION_NEXT(name_as_static_string_literal)
28 
29 //! Macro to trace argument value
30 #define CV_TRACE_ARG(arg_id)
31 
32 //! Macro to trace argument value (expanded version)
33 #define CV_TRACE_ARG_VALUE(arg_id, arg_name, value)
34 
35 //! @cond IGNORED
36 #define CV_TRACE_NS cv::utils::trace
37 
38 #if !defined(OPENCV_DISABLE_TRACE) && defined(__EMSCRIPTEN__)
39 #define OPENCV_DISABLE_TRACE 1
40 #endif
41 
42 namespace details {
43 
44 #ifndef __OPENCV_TRACE
45 # if defined __OPENCV_BUILD && !defined __OPENCV_TESTS && !defined __OPENCV_APPS
46 #   define __OPENCV_TRACE 1
47 # else
48 #   define __OPENCV_TRACE 0
49 # endif
50 #endif
51 
52 #ifndef CV_TRACE_FILENAME
53 # define CV_TRACE_FILENAME __FILE__
54 #endif
55 
56 #ifndef CV__TRACE_FUNCTION
57 # if defined _MSC_VER
58 #   define CV__TRACE_FUNCTION __FUNCSIG__
59 # elif defined __GNUC__
60 #   define CV__TRACE_FUNCTION __PRETTY_FUNCTION__
61 # else
62 #   define CV__TRACE_FUNCTION "<unknown>"
63 # endif
64 #endif
65 
66 //! Thread-local instance (usually allocated on stack)
67 class CV_EXPORTS Region
68 {
69 public:
70     struct LocationExtraData;
71     struct LocationStaticStorage
72     {
73         LocationExtraData** ppExtra;   //< implementation specific data
74         const char* name;              //< region name (function name or other custom name)
75         const char* filename;          //< source code filename
76         int line;                      //< source code line
77         int flags;                     //< flags (implementation code path: Plain, IPP, OpenCL)
78     };
79 
80     Region(const LocationStaticStorage& location);
~Region()81     inline ~Region()
82     {
83         if (implFlags != 0)
84             destroy();
85         CV_DbgAssert(implFlags == 0);
86         CV_DbgAssert(pImpl == NULL);
87     }
88 
89     class Impl;
90     Impl* pImpl; // NULL if current region is not active
91     int implFlags; // see RegionFlag, 0 if region is ignored
92 
isActive() const93     bool isActive() const { return pImpl != NULL; }
94 
95     void destroy();
96 private:
97     Region(const Region&); // disabled
98     Region& operator= (const Region&); // disabled
99 };
100 
101 //! Specify region flags
102 enum RegionLocationFlag {
103     REGION_FLAG_FUNCTION = (1 << 0),             //< region is function (=1) / nested named region (=0)
104     REGION_FLAG_APP_CODE = (1 << 1),             //< region is Application code (=1) / OpenCV library code (=0)
105     REGION_FLAG_SKIP_NESTED = (1 << 2),          //< avoid processing of nested regions
106 
107     REGION_FLAG_IMPL_IPP = (1 << 16),            //< region is part of IPP code path
108     REGION_FLAG_IMPL_OPENCL = (2 << 16),         //< region is part of OpenCL code path
109     REGION_FLAG_IMPL_OPENVX = (3 << 16),         //< region is part of OpenVX code path
110 
111     REGION_FLAG_IMPL_MASK = (15 << 16),
112 
113     REGION_FLAG_REGION_FORCE = (1 << 30),
114     REGION_FLAG_REGION_NEXT = (1 << 31),         //< close previous region (see #CV_TRACE_REGION_NEXT macro)
115 
116     ENUM_REGION_FLAG_FORCE_INT = INT_MAX
117 };
118 
119 struct CV_EXPORTS TraceArg {
120 public:
121     struct ExtraData;
122     ExtraData** ppExtra;
123     const char* name;
124     int flags;
125 };
126 /** @brief Add meta information to current region (function)
127  * See CV_TRACE_ARG macro
128  * @param arg argument information structure (global static cache)
129  * @param value argument value (can by dynamic string literal in case of string, static allocation is not required)
130  */
131 CV_EXPORTS void traceArg(const TraceArg& arg, const char* value);
132 //! @overload
133 CV_EXPORTS void traceArg(const TraceArg& arg, int value);
134 //! @overload
135 CV_EXPORTS void traceArg(const TraceArg& arg, int64 value);
136 //! @overload
137 CV_EXPORTS void traceArg(const TraceArg& arg, double value);
138 
139 #define CV__TRACE_LOCATION_VARNAME(loc_id) CVAUX_CONCAT(CVAUX_CONCAT(__cv_trace_location_, loc_id), __LINE__)
140 #define CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id) CVAUX_CONCAT(CVAUX_CONCAT(__cv_trace_location_extra_, loc_id) , __LINE__)
141 
142 #define CV__TRACE_DEFINE_LOCATION_(loc_id, name, flags) \
143     static CV_TRACE_NS::details::Region::LocationExtraData* CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id) = 0; \
144     static const CV_TRACE_NS::details::Region::LocationStaticStorage \
145         CV__TRACE_LOCATION_VARNAME(loc_id) = { &(CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id)), name, CV_TRACE_FILENAME, __LINE__, flags};
146 
147 #define CV__TRACE_DEFINE_LOCATION_FN(name, flags) CV__TRACE_DEFINE_LOCATION_(fn, name, ((flags) | CV_TRACE_NS::details::REGION_FLAG_FUNCTION))
148 
149 
150 #define CV__TRACE_OPENCV_FUNCTION() \
151     CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, 0); \
152     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
153 
154 #define CV__TRACE_OPENCV_FUNCTION_NAME(name) \
155     CV__TRACE_DEFINE_LOCATION_FN(name, 0); \
156     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
157 
158 #define CV__TRACE_APP_FUNCTION() \
159     CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
160     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
161 
162 #define CV__TRACE_APP_FUNCTION_NAME(name) \
163     CV__TRACE_DEFINE_LOCATION_FN(name, CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
164     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
165 
166 
167 #define CV__TRACE_OPENCV_FUNCTION_SKIP_NESTED() \
168     CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED); \
169     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
170 
171 #define CV__TRACE_OPENCV_FUNCTION_NAME_SKIP_NESTED(name) \
172     CV__TRACE_DEFINE_LOCATION_FN(name, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED); \
173     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
174 
175 #define CV__TRACE_APP_FUNCTION_SKIP_NESTED() \
176     CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED | CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
177     const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn));
178 
179 
180 #define CV__TRACE_REGION_(name_as_static_string_literal, flags) \
181     CV__TRACE_DEFINE_LOCATION_(region, name_as_static_string_literal, flags); \
182     CV_TRACE_NS::details::Region CVAUX_CONCAT(__region_, __LINE__)(CV__TRACE_LOCATION_VARNAME(region));
183 
184 #define CV__TRACE_REGION(name_as_static_string_literal) CV__TRACE_REGION_(name_as_static_string_literal, 0)
185 #define CV__TRACE_REGION_NEXT(name_as_static_string_literal) CV__TRACE_REGION_(name_as_static_string_literal, CV_TRACE_NS::details::REGION_FLAG_REGION_NEXT)
186 
187 #define CV__TRACE_ARG_VARNAME(arg_id) CVAUX_CONCAT(__cv_trace_arg_ ## arg_id, __LINE__)
188 #define CV__TRACE_ARG_EXTRA_VARNAME(arg_id) CVAUX_CONCAT(__cv_trace_arg_extra_ ## arg_id, __LINE__)
189 
190 #define CV__TRACE_DEFINE_ARG_(arg_id, name, flags) \
191     static CV_TRACE_NS::details::TraceArg::ExtraData* CV__TRACE_ARG_EXTRA_VARNAME(arg_id) = 0; \
192     static const CV_TRACE_NS::details::TraceArg \
193         CV__TRACE_ARG_VARNAME(arg_id) = { &(CV__TRACE_ARG_EXTRA_VARNAME(arg_id)), name, flags };
194 
195 #define CV__TRACE_ARG_VALUE(arg_id, arg_name, value) \
196         CV__TRACE_DEFINE_ARG_(arg_id, arg_name, 0); \
197         CV_TRACE_NS::details::traceArg((CV__TRACE_ARG_VARNAME(arg_id)), value);
198 
199 #define CV__TRACE_ARG(arg_id) CV_TRACE_ARG_VALUE(arg_id, #arg_id, (arg_id))
200 
201 } // namespace
202 
203 #ifndef OPENCV_DISABLE_TRACE
204 #undef CV_TRACE_FUNCTION
205 #undef CV_TRACE_FUNCTION_SKIP_NESTED
206 #if __OPENCV_TRACE
207 #define CV_TRACE_FUNCTION CV__TRACE_OPENCV_FUNCTION
208 #define CV_TRACE_FUNCTION_SKIP_NESTED CV__TRACE_OPENCV_FUNCTION_SKIP_NESTED
209 #else
210 #define CV_TRACE_FUNCTION CV__TRACE_APP_FUNCTION
211 #define CV_TRACE_FUNCTION_SKIP_NESTED CV__TRACE_APP_FUNCTION_SKIP_NESTED
212 #endif
213 
214 #undef CV_TRACE_REGION
215 #define CV_TRACE_REGION CV__TRACE_REGION
216 
217 #undef CV_TRACE_REGION_NEXT
218 #define CV_TRACE_REGION_NEXT CV__TRACE_REGION_NEXT
219 
220 #undef CV_TRACE_ARG_VALUE
221 #define CV_TRACE_ARG_VALUE(arg_id, arg_name, value) \
222         if (__region_fn.isActive()) \
223         { \
224             CV__TRACE_ARG_VALUE(arg_id, arg_name, value); \
225         }
226 
227 #undef CV_TRACE_ARG
228 #define CV_TRACE_ARG CV__TRACE_ARG
229 
230 #endif // OPENCV_DISABLE_TRACE
231 
232 #ifdef OPENCV_TRACE_VERBOSE
233 #define CV_TRACE_FUNCTION_VERBOSE CV_TRACE_FUNCTION
234 #define CV_TRACE_REGION_VERBOSE CV_TRACE_REGION
235 #define CV_TRACE_REGION_NEXT_VERBOSE CV_TRACE_REGION_NEXT
236 #define CV_TRACE_ARG_VALUE_VERBOSE CV_TRACE_ARG_VALUE
237 #define CV_TRACE_ARG_VERBOSE CV_TRACE_ARG
238 #else
239 #define CV_TRACE_FUNCTION_VERBOSE(...)
240 #define CV_TRACE_REGION_VERBOSE(...)
241 #define CV_TRACE_REGION_NEXT_VERBOSE(...)
242 #define CV_TRACE_ARG_VALUE_VERBOSE(...)
243 #define CV_TRACE_ARG_VERBOSE(...)
244 #endif
245 
246 //! @endcond
247 
248 //! @}
249 
250 }}} // namespace
251 
252 #endif // OPENCV_TRACE_HPP
253