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