Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArrayRCP_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_ArrayRCP.hpp"
17 #include <vector>
18 #include <thread>
19 
20 namespace {
21 
22 using Teuchos::ArrayRCP;
23 using Teuchos::RCP;
24 using Teuchos::rcp;
25 using Teuchos::null;
27 
28 // thread method used by unit test mtArrayRCPMultipleReads below
29 static void read_arrayrcp_in_thread(ArrayRCP<int> shared_arrayrcp,
30  int expectedValue, std::atomic<int> & countErrors) {
31  // spin lock all threads until released by the main thread
32  while (!ThreadTestManager::s_bAllowThreadsToRun) {}
33  for( int n = 0; n < 1000; ++n) {
34  // test the iterators
35  for (ArrayRCP<int>::const_iterator iter = shared_arrayrcp.begin();
36  iter < shared_arrayrcp.end(); ++iter) {
37  // test reading a value
38  int readAValue = shared_arrayrcp[0];
39  // make sure the value is correct and log anything wrong
40  if (readAValue != expectedValue) {
41  ++countErrors;
42  }
43  // now check using the iterator
44  int readAValueByIterator = *iter;
45  // make sure the value is correct and log anything wrong
46  if (readAValueByIterator != expectedValue) {
47  ++countErrors;
48  }
49  }
50  }
51 }
52 
53 // RCP Thread Safety Unit Test: mtArrayRCPMultipleReads
54 //
55 // Purpose:
56 // Sanity Check: Validate that the class is working - this was not expected
57 // to have any trouble once the RCP class was made thread and no issues
58 // were found.
59 //
60 // Description:
61 // Creates an ArrayRCP<int>, sets all the values to an arbitrary known value,
62 // then shares it to several threads which all read the ArrayRCP
63 // at the same time and validate the read works. This tests both using
64 // the iterators to cycle through the array and the actually reading of the
65 // elements.
66 //
67 // Solution to the Problem:
68 // Sanity Check
69 //
70 // Demonstration of Problem:
71 // Sanity Check
72 TEUCHOS_UNIT_TEST( ArrayRCP, mtArrayRCPMultipleReads )
73 {
74  const int numThreads = TEUCHOS_THREAD_SAFE_UNIT_TESTS_THREADS_USED;
75  const int numTests = NUM_TESTS_TO_RUN;
76  const int setValue = 67359487; // arbitrary
77  const int arraySize = 10; // arbitrary
78  std::atomic<int> countErrors(0); // atomic counter to log errors
79  try {
80  for (int testCycle = 0; testCycle < numTests; ++testCycle) {
81  std::vector<std::thread> threads;
82  // set up all threads to be spin locked
83  ThreadTestManager::s_bAllowThreadsToRun = false;
84  // create an ArrayRCP to share between the threads
85  ArrayRCP<int> shared_arrayrcp(arraySize, setValue); // some array
86  // Send the ArrayRCP to all the threads
87  for (int i = 0; i < numThreads; ++i) {
88  threads.push_back( std::thread(read_arrayrcp_in_thread,
89  shared_arrayrcp, setValue, std::ref(countErrors)));
90  }
91  // let the threads run
92  ThreadTestManager::s_bAllowThreadsToRun = true;
93  // join them
94  for (unsigned int i = 0; i < threads.size(); ++i) {
95  threads[i].join();
96  }
97  convenience_log_progress(testCycle, numTests); // this is just output
98  }
99  }
100  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
101  TEST_EQUALITY(countErrors, 0);
102 }
103 
104 // thread method used by unit test mtRCPofArrayRCPMultipleReads below
105 // this variant reads an RCP<ArrayRCP<int>> instrad of an ArrayRCP<int>
106 // Note the difference is the threads now directly access the same ArrayRCP<int>
107 // object rather than copies of it.
108 static void read_rcp_of_arrayrcp_in_thread(RCP<ArrayRCP<int>>
109  shared_rcp_of_arrayrcp, int expectedValue, std::atomic<int> & countErrors) {
110  while (!ThreadTestManager::s_bAllowThreadsToRun) {}
111  for( int n = 0; n < 1000; ++n) {
112  for (ArrayRCP<int>::const_iterator iter = shared_rcp_of_arrayrcp->begin();
113  iter < shared_rcp_of_arrayrcp->end(); ++iter) {
114  // test reading a value
115  int readAValue = (*shared_rcp_of_arrayrcp)[0];
116  // make sure the value is correct and log anything wrong
117  if (readAValue != expectedValue) {
118  ++countErrors;
119  }
120  // now check using the iterator
121  int readAValueByIterator = *iter;
122  // make sure the value is correct and log anything wrong
123  if (readAValueByIterator != expectedValue) {
124  ++countErrors;
125  }
126  }
127  }
128 }
129 
130 // RCP Thread Safety Unit Test: mtRCPofArrayRCPMultipleReads
131 //
132 // Purpose:
133 // Sanity Check: Similar to prior mtArrayRCPMultipleReads test.
134 //
135 // Description:
136 // Same as mtArrayRCPMultipleReads except we pass an RCP<Array<int>>
137 // instead of an Array<int>
138 //
139 // Solution to the Problem:
140 // Sanity Check
141 //
142 // Demonstration of Problem:
143 // Sanity Check
144 TEUCHOS_UNIT_TEST( ArrayRCP, mtRCPofArrayRCPMultipleReads )
145 {
146  const int numThreads = TEUCHOS_THREAD_SAFE_UNIT_TESTS_THREADS_USED;
147  const int numTests = NUM_TESTS_TO_RUN;
148  const int setValue = 67359487; // arbitrary
149  const int arraySize = 10; // arbitrary
150  std::atomic<int> countErrors(0); // atomic counter to log errors
151  try {
152  for (int testCycle = 0; testCycle < numTests; ++testCycle) {
153  std::vector<std::thread> threads;
154  // set up all threads to be spin locked
155  ThreadTestManager::s_bAllowThreadsToRun = false;
156  // create an RCP<ArrayRCP> to share between the threads
157  RCP<ArrayRCP<int>> shared_rcp_of_arrayrcp =
158  rcp(new ArrayRCP<int>(arraySize, setValue)); // some array
159  // Send the RCP<ArrayRCP<int>> to all the threads
160  for (int i = 0; i < numThreads; ++i) {
161  threads.push_back( std::thread(read_rcp_of_arrayrcp_in_thread,
162  shared_rcp_of_arrayrcp, setValue, std::ref(countErrors)) );
163  }
164  // let the threads run
165  ThreadTestManager::s_bAllowThreadsToRun = true;
166  // join them
167  for (unsigned int i = 0; i < threads.size(); ++i) {
168  threads[i].join();
169  }
170  convenience_log_progress(testCycle, numTests); // this is just output
171  }
172  }
173  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
174  TEST_EQUALITY(countErrors, 0);
175 }
176 
177 } // end namespace
Dangling reference error exception class.
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
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.
Reference-counted smart pointer for managing arrays.