blob: 034f9580d64ac7ffe0504dbab62263c484b4f32b [file] [log] [blame]
/*
Copyright 2005-2010 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
// Just the tracing portion of the harness.
//
// This header defines TRACE and TRCAENL macros, which use REPORT like syntax and
// are useful for duplicating trace output to the standard debug output on Windows.
// It is possible to add the ability of automatic extending messages with additional
// info (file, line, function, time, thread ID, ...).
//
// Macros output nothing when test app runs in non-verbose mode (default).
//
// The full "harness.h" must be included before this header.
#ifndef tbb_tests_harness_report_H
#define tbb_tests_harness_report_H
#if defined(MAX_TRACE_SIZE) && MAX_TRACE_SIZE < 1024
#undef MAX_TRACE_SIZE
#endif
#ifndef MAX_TRACE_SIZE
#define MAX_TRACE_SIZE 1024
#endif
#if __SUNPRO_CC
#include <stdio.h>
#else
#include <cstdio>
#endif
#include <cstdarg>
#if _MSC_VER
#define snprintf _snprintf
#if _MSC_VER<=1400
#define vsnprintf _vsnprintf
#endif
#endif
namespace Harness {
namespace internal {
#ifndef TbbHarnessReporter
struct TbbHarnessReporter {
void Report ( const char* msg ) {
printf( "%s", msg );
fflush(stdout);
#ifdef _WINDOWS_
OutputDebugStringA(msg);
#endif
}
}; // struct TbbHarnessReporter
#endif /* !TbbHarnessReporter */
class Tracer {
int m_flags;
const char *m_file;
const char *m_func;
size_t m_line;
TbbHarnessReporter m_reporter;
public:
enum {
prefix = 1,
need_lf = 2
};
Tracer* set_trace_info ( int flags, const char *file, size_t line, const char *func ) {
m_flags = flags;
m_line = line;
m_file = file;
m_func = func;
return this;
}
void trace ( const char* fmt, ... ) {
char msg[MAX_TRACE_SIZE];
char msg_fmt_buf[MAX_TRACE_SIZE];
const char *msg_fmt = fmt;
if ( m_flags & prefix ) {
snprintf (msg_fmt_buf, MAX_TRACE_SIZE, "[%s] %s", m_func, fmt);
msg_fmt = msg_fmt_buf;
}
std::va_list argptr;
va_start (argptr, fmt);
int len = vsnprintf (msg, MAX_TRACE_SIZE, msg_fmt, argptr);
va_end (argptr);
if ( m_flags & need_lf &&
len < MAX_TRACE_SIZE - 1 && msg_fmt[len-1] != '\n' )
{
msg[len] = '\n';
msg[len + 1] = 0;
}
m_reporter.Report(msg);
}
}; // class Tracer
static Tracer tracer;
template<int>
bool not_the_first_call () {
static bool first_call = false;
bool res = first_call;
first_call = true;
return res;
}
} // namespace internal
} // namespace Harness
#if defined(_MSC_VER) && _MSC_VER >= 1300 || defined(__GNUC__) || defined(__GNUG__)
#define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, __FUNCTION__
#else
#define HARNESS_TRACE_ORIG_INFO __FILE__, __LINE__, ""
#define __FUNCTION__ ""
#endif
//! printf style tracing macro
/** This variant of TRACE adds trailing line-feed (new line) character, if it is absent. **/
#define TRACE Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace
//! printf style tracing macro without automatic new line character adding
#define TRACENL Harness::internal::tracer.set_trace_info(0, HARNESS_TRACE_ORIG_INFO)->trace
//! printf style tracing macro with additional information prefix (e.g. current function name)
#define TRACEP Harness::internal::tracer.set_trace_info(Harness::internal::Tracer::prefix | \
Harness::internal::Tracer::need_lf, HARNESS_TRACE_ORIG_INFO)->trace
//! printf style remark macro
/** Produces output only when the test is run with the -v (verbose) option. **/
#define REMARK !Verbose ? (void)0 : TRACENL
//! printf style remark macro
/** Produces output only when invoked first time.
Only one instance of this macro is allowed per source code line. **/
#define REMARK_ONCE (!Verbose || Harness::internal::not_the_first_call<__LINE__>()) ? (void)0 : TRACE
//! printf style reporting macro
/** On heterogeneous platforms redirects its output to the host side. **/
#define REPORT TRACENL
#endif /* tbb_tests_harness_report_H */