xref: /oneTBB/test/common/checktype.h (revision 478de5b1)
1 /*
2     Copyright (c) 2005-2021 Intel Corporation
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8         http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15 */
16 
17 #ifndef __TBB_test_common_checktype_H
18 #define __TBB_test_common_checktype_H
19 
20 #include "config.h"
21 
22 #include <atomic>
23 
24 // Type that checks that there are no operations with the destroyed object
25 class DestroyedTracker {
26 protected:
27     enum StateType {
28         LIVE = 0x56781234,
29         DEAD = 0xDEADBEEF
30     };
31     StateType my_state;
32 public:
DestroyedTracker()33     DestroyedTracker() : my_state(LIVE) {}
DestroyedTracker(const DestroyedTracker & src)34     DestroyedTracker( const DestroyedTracker& src ) : my_state(LIVE) {
35         CHECK_FAST_MESSAGE(src.is_alive(), "Constructing from the dead source");
36     }
37 
~DestroyedTracker()38     ~DestroyedTracker() {
39         CHECK_FAST_MESSAGE(is_alive(), "Destructing the dead object");
40         my_state = DEAD;
41     }
42 
43     DestroyedTracker& operator=( const DestroyedTracker& src ) {
44         CHECK_FAST_MESSAGE(is_alive(), "Assignment to the dead object");
45         CHECK_FAST_MESSAGE(src.is_alive(), "Assignment from the dead source");
46         return *this;
47     }
48 
is_alive()49     bool is_alive() const {
50         return my_state == LIVE;
51     }
52 }; // class DestroyedTracker
53 
54 // Type that checks construction and destruction
55 template <typename Counter>
56 class CheckType : DestroyedTracker {
57 public:
58     static std::atomic<int> check_type_counter;
59 
my_id(n)60     CheckType( Counter n = 0 ) : my_id(n), am_ready(false) {
61         ++check_type_counter;
62     }
63 
CheckType(const CheckType & other)64     CheckType( const CheckType& other ) : DestroyedTracker(other) {
65         CHECK_FAST(is_alive());
66         CHECK_FAST(other.is_alive());
67         my_id = other.my_id;
68         am_ready = other.am_ready;
69         ++check_type_counter;
70     }
71 
72     operator int() const { return int(my_id); }
73     CheckType& operator++() {
74         ++my_id;
75         return *this;
76     }
77 
78     CheckType& operator=( const CheckType& other ) {
79         CHECK_FAST(is_alive());
80         CHECK_FAST(other.is_alive());
81         my_id = other.my_id;
82         am_ready = other.am_ready;
83         return *this;
84     }
85 
~CheckType()86     ~CheckType() {
87         CHECK_FAST(is_alive());
88         --check_type_counter;
89         CHECK_FAST_MESSAGE(check_type_counter >= 0, "Too many destructions");
90     }
91 
id()92     Counter id() const {
93         CHECK_FAST(is_alive());
94         return my_id;
95     }
96 
is_ready()97     bool is_ready() {
98         CHECK_FAST(is_alive());
99         return am_ready;
100     }
101 
get_ready()102     void get_ready() {
103         CHECK_FAST(is_alive());
104         if (my_id == Counter(0)) {
105             my_id = Counter(1);
106             am_ready = true;
107         }
108     }
109 
110 private:
111     Counter my_id;
112     bool am_ready;
113 }; // class CheckType
114 
115 namespace std {
116 template <typename Counter>
117 struct hash<CheckType<Counter>> {
118     std::size_t operator()( const CheckType<Counter>& obj ) const {
119         return std::size_t(obj.id());
120     }
121 };
122 
123 }
124 
125 template <typename Counter>
126 std::atomic<int> CheckType<Counter>::check_type_counter;
127 
128 // A dummy class
129 template <typename T>
130 struct Checker {
131     Checker() {} // do nothing
132     ~Checker() {} // do nothing
133 };
134 
135 // A specialization for CheckType that initialize a counter on creation
136 // and checks that the constructions and destructions of CheckType match
137 template <typename Counter>
138 struct Checker<CheckType<Counter>> {
139     Checker() { CheckType<Counter>::check_type_counter = 0; }
140     ~Checker() {
141         CHECK_MESSAGE(CheckType<Counter>::check_type_counter == 0,
142                         "CheckType constructions and destructions don't match");
143     }
144 }; // struct Checker
145 
146 #endif // __TBB_test_common_checktype_H
147