Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tuple_MT_UnitTests_Decl.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 // These unit tests are used for both a Nightly version and a Basic version
11 
12 #include "General_MT_UnitTests.hpp"
13 
14 #include "Teuchos_Tuple.hpp"
17 #include <vector>
18 #include <thread>
19 
20 namespace {
21 
22 using Teuchos::Tuple;
23 using Teuchos::RCP;
24 using Teuchos::tuple;
25 using Teuchos::rcp;
26 
27 // convenience Tuple type for testing with abritrary n = 8
28 #define TUPLE_SIZE 8 // arbitrary
29 typedef Tuple<int, TUPLE_SIZE> TupleClass;
30 
31 // this class is used to test Tuple in mtTupleMultipleReads below
32 class TupleContainingClass
33 {
34  public:
35  TupleContainingClass()
36  {
37  // just set some values to match the index which we will check
38  for (int n = 0; n < TUPLE_SIZE; ++n) {
39  myTuple[n] = n;
40  }
41  }
42 
43  // this method is called by the threads and returns false if it has any
44  // trouble reading the values. The constructor simply sets the elements
45  // to be equal to the array index and here we verify they read that way.
46  // If something happened strange with the iterators or memory we would
47  // hope to trigger a problem but we did not expect this to happen and
48  // everything seems ok.
49  bool readTheTuple()
50  {
51  int sanityCheckIndex = 0;
52  for (TupleClass::iterator iter = myTuple.begin();
53  iter < myTuple.end(); ++iter) {
54  if (sanityCheckIndex != *iter) {
55  // something happened
56  return false;
57  }
58  ++sanityCheckIndex;
59  }
60  return true;
61  }
62 
63  private:
64  TupleClass myTuple; // the Tuple to be tested
65 
66 };
67 
68 // utility thread method used by mtTupleMultipleReads below
69 static void share_tuple_to_threads(RCP<TupleContainingClass> shared_tuple,
70  std::atomic<int> & countErrors) {
71  while (!ThreadTestManager::s_bAllowThreadsToRun) {}
72  for( int n = 0; n < 1000; ++n) {
73  if (!shared_tuple->readTheTuple()) {
74  ++countErrors;
75  }
76  }
77 }
78 
79 // RCP Thread Safety Unit Test: mtTupleMultipleReads
80 //
81 // Purpose:
82 // Sanity Check: Mirrors the Array test (which would fail without mutex
83 // protection) but this oen is ok because the ArrayView it uses does not
84 // have any mutable behavior - it is true const.
85 //
86 // Description:
87 // Creates a Tuple, shares it to multiple threads, and reads it with
88 // some verification that the reading is not doing anything odd.
89 //
90 // Solution to the Problem:
91 // Sanity Check
92 //
93 // Demonstration of Problem:
94 // Sanity Check
95 TEUCHOS_UNIT_TEST( Tuple, mtTupleMultipleReads )
96 {
97  const int numThreads = TEUCHOS_THREAD_SAFE_UNIT_TESTS_THREADS_USED;
98  const int numTests = NUM_TESTS_TO_RUN;
99  // threads will increment if errors occur
100  std::atomic<int> countErrors(0);
101  try {
102  for (int testCycle = 0; testCycle < numTests; ++testCycle) {
103  std::vector<std::thread> threads;
104  // note the tuple constructor makes this a type TupleClass
105  // which is Tuple<int,8>
106  RCP<TupleContainingClass> shared_tuple_rcp = rcp(
107  new TupleContainingClass());
108  // create threads all sharing access to the Tuple RCP
109  for (int i = 0; i < numThreads; ++i) {
110  threads.push_back( std::thread(share_tuple_to_threads,
111  shared_tuple_rcp, std::ref(countErrors)) );
112  }
113  ThreadTestManager::s_bAllowThreadsToRun = true; // let the threads run
114  for (unsigned int i = 0; i < threads.size(); ++i) {
115  threads[i].join();
116  }
117  convenience_log_progress(testCycle, numTests); // this is just output
118  }
119  }
120  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
121  TEST_EQUALITY(countErrors, 0 );
122 }
123 
124 } // end namespace
#define TUPLE_SIZE
RCP< T > rcp(const boost::shared_ptr< T > &sptr)
Conversion function that takes in a boost::shared_ptr object and spits out a Teuchos::RCP object...
#define TEUCHOS_THREAD_SAFE_UNIT_TESTS_THREADS_USED
#define TEST_EQUALITY(v1, v2)
Assert the equality of v1 and v2.
#define TEUCHOS_UNIT_TEST(TEST_GROUP, TEST_NAME)
Macro for defining a (non-templated) unit test.
#define NUM_TESTS_TO_RUN
Statically sized simple array (tuple) class.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
Simple macro that catches and reports standard exceptions and other exceptions.
Unit testing support.
Smart reference counting pointer class for automatic garbage collection.