xref: /third_party/benchmark/src/log.h (revision a8c51b3f)
1#ifndef BENCHMARK_LOG_H_
2#define BENCHMARK_LOG_H_
3
4#include <iostream>
5#include <ostream>
6
7// NOTE: this is also defined in benchmark.h but we're trying to avoid a
8// dependency.
9// The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer.
10#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
11#define BENCHMARK_HAS_CXX11
12#endif
13
14namespace benchmark {
15namespace internal {
16
17typedef std::basic_ostream<char>&(EndLType)(std::basic_ostream<char>&);
18
19class LogType {
20  friend LogType& GetNullLogInstance();
21  friend LogType& GetErrorLogInstance();
22
23  // FIXME: Add locking to output.
24  template <class Tp>
25  friend LogType& operator<<(LogType&, Tp const&);
26  friend LogType& operator<<(LogType&, EndLType*);
27
28 private:
29  LogType(std::ostream* out) : out_(out) {}
30  std::ostream* out_;
31
32  // NOTE: we could use BENCHMARK_DISALLOW_COPY_AND_ASSIGN but we shouldn't have
33  // a dependency on benchmark.h from here.
34#ifndef BENCHMARK_HAS_CXX11
35  LogType(const LogType&);
36  LogType& operator=(const LogType&);
37#else
38  LogType(const LogType&) = delete;
39  LogType& operator=(const LogType&) = delete;
40#endif
41};
42
43template <class Tp>
44LogType& operator<<(LogType& log, Tp const& value) {
45  if (log.out_) {
46    *log.out_ << value;
47  }
48  return log;
49}
50
51inline LogType& operator<<(LogType& log, EndLType* m) {
52  if (log.out_) {
53    *log.out_ << m;
54  }
55  return log;
56}
57
58inline int& LogLevel() {
59  static int log_level = 0;
60  return log_level;
61}
62
63inline LogType& GetNullLogInstance() {
64  static LogType null_log(static_cast<std::ostream*>(nullptr));
65  return null_log;
66}
67
68inline LogType& GetErrorLogInstance() {
69  static LogType error_log(&std::clog);
70  return error_log;
71}
72
73inline LogType& GetLogInstanceForLevel(int level) {
74  if (level <= LogLevel()) {
75    return GetErrorLogInstance();
76  }
77  return GetNullLogInstance();
78}
79
80}  // end namespace internal
81}  // end namespace benchmark
82
83// clang-format off
84#define BM_VLOG(x)                                                               \
85  (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
86                                                                         " ")
87// clang-format on
88#endif
89