Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
General_MT_UnitTests.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Teuchos: Common Tools Package
4 //
5 // Copyright 2004 NTESS and the Teuchos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TEUCHOS_GENERAL_MT_UNITTESTS_HPP
11 #define TEUCHOS_GENERAL_MT_UNITTESTS_HPP
12 
14 #include "Teuchos_ConfigDefs.hpp"
15 
16 // NUM_TOTAL_CORES_USED = 4 set in CMake
17 #define TEUCHOS_THREAD_SAFE_UNIT_TESTS_THREADS_USED 4
18 
19 #include <atomic>
20 #include <iostream>
21 
22 namespace {
23 
24 // this is a convenience function for outputting percent complete information
25 // for long tests designed to find race conditions
26 static void convenience_log_progress(int cycle, int totalCycles) {
27  if (cycle==0) {
28  std::cout << "Percent complete: "; // begin the log line
29  }
30  // log every 10% percent complete - using mod % to output at regular intervals
31  int mod = (totalCycles/10);
32  // sometimes quick testing so make sure mod is not 0
33  if((cycle % (mod == 0 ? 1 : mod) == 0) || (cycle == totalCycles-1)) {
34  std::cout <<
35  (int)( 100.0f * (float) cycle / (float) (totalCycles-1) ) << "% ";
36  // not necessary on some setups but for Xcode this would not work without
37  // the flush command - it waits for an endl
38  std::flush( std::cout );
39  }
40 }
41 
42 // This class is a utility class which tracks constructor/destructor calls
43 // (for this test) or counts times a dealloc or deallocHandle was implemented
44 // (for later tests)
45 class CatchMemoryLeak
46 {
47 public:
48  CatchMemoryLeak() { ++s_countAllocated; }
49  ~CatchMemoryLeak() { --s_countAllocated; }
50  static std::atomic<int> s_countAllocated;
51  static std::atomic<int> s_countDeallocs;
52 };
53 // counts constructor calls (+1) and destructor calls (-1) which may include
54 // double delete events
55 std::atomic<int> CatchMemoryLeak::s_countAllocated(0);
56 // counts dealloc or dellocHandle calls - used for test 4 and test 5
57 std::atomic<int> CatchMemoryLeak::s_countDeallocs(0);
58 
59 // manages a bool for spin locking unit test threads - the idea is to hold all
60 // threads until ready and then release simultaneously to maximize race
61 // condition probability.
62 class ThreadTestManager
63 {
64 public:
65  // used to spin lock the sub threads until all released simultaneously
66  static std::atomic<bool> s_bAllowThreadsToRun;
67  // this lets the sub threads know the event happened so they can quit or give
68  // errors if they don't detect something after this occurs
69  static std::atomic<bool> s_bMainThreadSetToNull;
70  // utility to tell special threads when main threads have finished work
71  static std::atomic<int> s_countCompletedThreads;
72  // utility to count how many times a working thread has run - using this to
73  // debug other threads if they are supposed to trigger an event once this
74  // thread completes a cycle
75  static std::atomic<int> s_countWritingThreadCycles;
76 };
77 std::atomic<bool> ThreadTestManager::s_bAllowThreadsToRun(false);
78 std::atomic<bool> ThreadTestManager::s_bMainThreadSetToNull(false);
79 std::atomic<int> ThreadTestManager::s_countCompletedThreads(0);
80 std::atomic<int> ThreadTestManager::s_countWritingThreadCycles(0);
81 
82 // utility define used below: -1 means it was never set
83 #define UNSET_CYCLE_INDEX -1
84 
85 // this convenience struct is used to track the various errors which can
86 // happen with the RCP classes, which uses weak references. The unit test
87 // description below describes in more detail what this test is doing.
88 struct Cycle_Index_Tracker
89 {
90  Cycle_Index_Tracker()
91  {
92  missedDanglingOnFirstCycle = UNSET_CYCLE_INDEX;
93  danglingReference = UNSET_CYCLE_INDEX;
94  scambledMemory = UNSET_CYCLE_INDEX;
95  outOfRangeError = UNSET_CYCLE_INDEX;
96  unknownError = UNSET_CYCLE_INDEX;
97  }
98  // for special test with detection designed to hit on the first cycle,
99  // this tracks if it actually missed that cycle
100  // this test has less random behavior so was useful for validation
101  int missedDanglingOnFirstCycle;
102  // tracks when a dangling reference was hit
103  int danglingReference;
104  // tracks when scrambled memory was detected
105  int scambledMemory;
106  // tracks when an out of range error was found
107  int outOfRangeError;
108  // tracks unknown exception - not expected
109  int unknownError;
110  // feedback to indicate how many times the thread has actually done a loop
111  std::atomic<int> trackCycle;
112 };
113 
114 } // end namespace
115 
116 #endif // end #ifdef TEUCHOS_GENERAL_MT_UNITTESTS_HPP
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
#define UNSET_CYCLE_INDEX