1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <ostream>
16 
17 namespace iorap {
18 
19 // kIsDebugBuild is special.
20 // It gets to be in the 'iorap' namespace
21 // so that different modules don't need to qualify it.
22 #ifndef NDEBUG
23 static constexpr bool kIsDebugBuild = true;
24 #else
25 static constexpr bool kIsDebugBuild = false;
26 #endif
27 
28 namespace common {
29 
30 // TODO: move below code to helpers.
31 template <typename T, bool>
32 struct base_if_condition {};
33 
34 template <typename T>
35 struct base_if_condition<T, true> : public T {};
36 
37 template <typename T>
38 using base_if_debug = base_if_condition<T, kIsDebugBuild>;
39 
40 namespace detail {
41 // "if constexpr" doesn't allow us to exclude fields from a struct/class,
42 // and also "if constexpr" doesn't allow us to reference a field that does not
43 // exist.
44 // so we must move everything into a separate base class.
45 template <bool kIsDebug = kIsDebugBuild>
46 struct DebugCounterBase {
47   constexpr size_t value() const {
48     return counter;
49   }
50 
51   constexpr void set_value(size_t value) {
52     counter = value;
53   }
54 
55   size_t counter{1};  // Don't start with 0.
56 };
57 
58 template <>
59 struct DebugCounterBase<false /*kIsDebug*/> {
60   constexpr size_t value() const {
61     return 0;
62   }
63 
64   constexpr void set_value(size_t value) {
65   }
66 };
67 }  // namespace detail
68 
69 // This counter does absolutely nothing, the code compiles to no-ops
70 // when debugging is disabled.
71 struct DebugCounter : detail::DebugCounterBase<> {
72   constexpr DebugCounter& operator++() {
73     set_value(value() + 1);
74     return *this;
75   }
76 
77   constexpr DebugCounter operator++(int) {
78     DebugCounter now = *this;
79     set_value(value() + 1);
80     return now;
81   }
82 
83   constexpr operator size_t() const {
84     return value();
85   }
86 
87   friend std::ostream& operator<<(std::ostream& os, DebugCounter counter);
88 };
89 
90 inline std::ostream& operator<<(std::ostream& os, DebugCounter counter) {
91   os << counter.value();
92   return os;
93 }
94 
95 // TODO: refactor DebugCounter and base traits into their own files?
96 
97 }  // namespace common
98 }  // namespace iorap
99