Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkITKThreadingTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include <itkFastMutexLock.h>
14 #include <itkMultiThreader.h>
15 #include <itkSemaphore.h>
16 
17 /*
18 int main()
19 {
20  std::cout<<"[PASSED]"<<std::endl;
21  std::cout<<"[FAILED]"<<std::endl;
22  return EXIT_FAILURE;
23  return EXIT_SUCCESS;
24 }
25 */
26 
27 // to pass some parameter to thread
28 class UserData
29 {
30 public:
31  int *intPointer;
32  itk::FastMutexLock *mutex;
33  itk::Semaphore *semaphore;
34  itk::Semaphore *mayIRun;
35 };
36 
37 // this will be executed in a thread
38 ITK_THREAD_RETURN_TYPE ThreadedFunction(void *param)
39 {
40  std::cout << "Getting thread info data... ";
41  itk::MultiThreader::ThreadInfoStruct *threadInfo = static_cast<itk::MultiThreader::ThreadInfoStruct *>(param);
42 
43  if (!threadInfo)
44  {
45  std::cout << "[FAILED]" << std::endl;
46  exit(EXIT_FAILURE);
47  }
48  std::cout << "[PASSED]" << std::endl;
49 
50  std::cout << "Getting user data from thread... ";
51  UserData *userData = static_cast<UserData *>(threadInfo->UserData);
52 
53  if (!userData)
54  {
55  std::cout << "[FAILED]" << std::endl;
56  exit(EXIT_FAILURE);
57  }
58  std::cout << "[PASSED]" << std::endl;
59 
60  // inc variable FOR main thread
61  std::cout << "generate 10000 results";
62  for (int i = 1; i <= 10000; ++i)
63  {
64  userData->mutex->Lock();
65  *(userData->intPointer) += 1; // generate one "result"
66  userData->mutex->Unlock();
67  userData->semaphore->Up(); // signal "work done"
68  }
69  std::cout << "[PASSED]" << std::endl;
70 
71  std::cout << "waiting for main thread's signal... " << std::endl;
72  ;
73  userData->mayIRun->Down(); // wait for signal
74  std::cout << "got main thread's signal... " << std::endl;
75 
76  // inc variable TOGETHER WITH main thread
77  for (int i = 1; i <= 10000; ++i)
78  {
79  userData->mutex->Lock();
80  *(userData->intPointer) += 1;
81  userData->mutex->Unlock();
82  }
83 
84  userData->semaphore->Up(); // signal "job done"
85 
86  return ITK_THREAD_RETURN_VALUE;
87 }
88 
89 int mitkITKThreadingTest(int /*argc*/, char * /*argv*/ [])
90 {
91  itk::MultiThreader::Pointer threader = itk::MultiThreader::New();
92 
93  int localInt(0); // this will be modified by both threads
94 
95  itk::Semaphore::Pointer m_ResultAvailable = itk::Semaphore::New();
96  m_ResultAvailable->Initialize(0); // no pieces left (thread has to create one)
97 
98  itk::Semaphore::Pointer m_RunThreadRun = itk::Semaphore::New();
99  m_RunThreadRun->Initialize(0); // no pieces left (thread has to create one)
100 
101  itk::FastMutexLock::Pointer m_Mutex = itk::FastMutexLock::New();
102 
103  UserData userData;
104  userData.intPointer = &localInt;
105  userData.mutex = m_Mutex.GetPointer();
106  userData.semaphore = m_ResultAvailable.GetPointer();
107  userData.mayIRun = m_RunThreadRun.GetPointer();
108 
109  itk::ThreadFunctionType pointer = &ThreadedFunction;
110  int thread_id = threader->SpawnThread(pointer, &userData);
111 
112  // let thread generate 10 results
113  for (int i = 1; i <= 10000; ++i)
114  m_ResultAvailable->Down();
115 
116  std::cout << "signaling by semaphore thread->main ";
117  if (localInt == 10000)
118  std::cout << "[PASSED]" << std::endl;
119  else
120  {
121  std::cout << "[FAILED] localInt == " << localInt << std::endl;
122  return EXIT_FAILURE;
123  }
124 
125  // increase int simultaneously with thread (coordinated by mutex)
126  localInt = 0;
127  m_RunThreadRun->Up(); // let thread work again
128  for (int i = 1; i <= 10000; ++i)
129  {
130  m_Mutex->Lock();
131  ++localInt;
132  m_Mutex->Unlock();
133  }
134 
135  std::cout << "waiting for thread's signal" << std::endl;
136  ;
137  m_ResultAvailable->Down(); // wait for thread
138  std::cout << "got thread's signal" << std::endl;
139  ;
140 
141  std::cout << "sharing a mutex protected variable among threads";
142  if (localInt == 20000)
143  std::cout << "[PASSED]" << std::endl;
144  else
145  {
146  std::cout << "[FAILED] localInt == " << localInt << std::endl;
147  return EXIT_FAILURE;
148  }
149 
150  // terminating work thread
151  std::cout << "waiting for idling thread ";
152  threader->TerminateThread(thread_id);
153  std::cout << "[PASSED]" << std::endl;
154 
155  std::cout << "Whole test [PASSED]" << std::endl;
156 
157  return EXIT_SUCCESS;
158 }
int mitkITKThreadingTest(int, char *[])
ITK_THREAD_RETURN_TYPE ThreadedFunction(void *param)