1/*
2 Copyright (c) 2005-2019 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// Declarations for a class that can track operations applied to its objects.
18// This header is an optional part of the test harness.
19
20#ifndef tbb_test_harness_state_trackable_H
21#define tbb_test_harness_state_trackable_H
22
23#include <cstddef>
24#include <map>
25#include <tbb/atomic.h>
26
27#include "harness_assert.h"
28
29namespace Harness{
30 struct StateTrackableBase {
31 enum StateValue {
32 ZeroInitialized = 0,
33 DefaultInitialized = 0xDEFAUL,
34 DirectInitialized = 0xD1111,
35 CopyInitialized = 0xC0314,
36 MoveInitialized = 0xAAAAA,
37 Assigned = 0x11AED,
38 MoveAssigned = 0x22AED,
39 MovedFrom = 0xFFFFF,
40 Destroyed = 0xDEADF00,
41 Unspecified = 0xEEEEE
42 };
43
44 class State {
45 public:
46 State() __TBB_NOEXCEPT(true) : state(Unspecified) {
47 assignNewState(Unspecified);
48 }
49 State(const State& s) : state(Unspecified) {
50 assignNewState(s.state);
51 }
52 State(StateValue s) __TBB_NOEXCEPT(true) : state(Unspecified) {
53 assignNewState(s);
54 };
55 State& operator=(StateValue s) __TBB_NOEXCEPT(true) {
56 assignNewState(s);
57 return *this;
58 }
59 operator StateValue() const __TBB_NOEXCEPT(true) { return state; }
60 private:
61 void assignNewState(StateValue s) __TBB_NOEXCEPT(true);
62 StateValue state;
63 };
64 };
65
66 struct StateTrackableCounters {
67 static void reset() {
68 counters[StateTrackableBase::ZeroInitialized] = counters[StateTrackableBase::DefaultInitialized] =
69 counters[StateTrackableBase::DirectInitialized] = counters[StateTrackableBase::CopyInitialized] =
70 counters[StateTrackableBase::MoveInitialized] = counters[StateTrackableBase::Assigned] =
71 counters[StateTrackableBase::MoveAssigned] = counters[StateTrackableBase::MovedFrom] =
72 counters[StateTrackableBase::Destroyed] = counters[StateTrackableBase::Unspecified] = 0;
73 }
74
75 static bool initialize() {
76 reset();
77 return true;
78 }
79
80 typedef std::map<StateTrackableBase::StateValue, tbb::atomic<std::size_t> > counters_t;
81 static counters_t counters;
82 };
83
84 StateTrackableCounters::counters_t StateTrackableCounters::counters;
85 static const bool stateTrackableBaseStateInitialized = StateTrackableCounters::initialize();
86
87 void StateTrackableBase::State::assignNewState(StateValue s) __TBB_NOEXCEPT(true) {
88 ASSERT(stateTrackableBaseStateInitialized, "State trackable counters are not initialized");
89 ASSERT(s == StateTrackableBase::Unspecified ||
90 StateTrackableCounters::counters.find(s) != StateTrackableCounters::counters.end(), "The current state value is unknown");
91 ASSERT(state == StateTrackableBase::Unspecified ||
92 StateTrackableCounters::counters.find(state) != StateTrackableCounters::counters.end(), "The new state value is unknown");
93 state = s;
94 ++StateTrackableCounters::counters[state];
95 }
96
97 template<bool allow_zero_initialized_state = false>
98 struct StateTrackable: StateTrackableBase {
99 static const bool is_zero_initialized_state_allowed = allow_zero_initialized_state;
100 State state;
101
102 bool is_valid() const {
103 return state == DefaultInitialized || state == DirectInitialized || state == CopyInitialized
104 || state == MoveInitialized || state == Assigned || state == MoveAssigned || state == MovedFrom
105 || (allow_zero_initialized_state && state == ZeroInitialized)
106 ;
107 }
108
109 StateTrackable (intptr_t) __TBB_NOEXCEPT(true) : state (DirectInitialized){}
110 StateTrackable () __TBB_NOEXCEPT(true) : state (DefaultInitialized){}
111 StateTrackable (const StateTrackable & src) __TBB_NOEXCEPT(true) {
112 ASSERT( src.is_valid(), "bad source for copy" );
113 state = CopyInitialized;
114 }
115 #if __TBB_CPP11_RVALUE_REF_PRESENT
116 StateTrackable (StateTrackable && src) __TBB_NOEXCEPT(true) {
117 ASSERT( src.is_valid(), "bad source for move?" );
118 state = MoveInitialized;
119 src.state = MovedFrom;
120 }
121 StateTrackable & operator=(StateTrackable && src) __TBB_NOEXCEPT(true) {
122 ASSERT( src.is_valid(), "bad source for assignment" );
123 ASSERT( is_valid(), "assigning to invalid instance?" );
124
125 src.state = MovedFrom;
126 state = MoveAssigned;
127 return *this;
128 }
129 #endif
130 StateTrackable & operator=(const StateTrackable & src) __TBB_NOEXCEPT(true) {
131 ASSERT( src.is_valid(), "bad source for assignment?" );
132 ASSERT( is_valid(), "assigning to invalid instance?" );
133
134 state = Assigned;
135 return *this;
136 }
137 ~StateTrackable () __TBB_NOEXCEPT(true) {
138 ASSERT( is_valid(), "Calling destructor on invalid instance? (twice destructor call?)" );
139 state = Destroyed;
140 }
141 };
142} // Harness
143#endif // tbb_test_harness_state_trackable_H
144