File: igtlMultiThreaderTest3.cxx

package info (click to toggle)
openigtlink 3.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,080 kB
  • sloc: cpp: 20,076; ansic: 6,704; sh: 227; perl: 74; makefile: 46
file content (133 lines) | stat: -rw-r--r-- 3,428 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*=========================================================================

  Program:   OpenIGTLink Library
  Language:  C++

  Copyright (c) Insight Software Consortium. All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/


//=========================================================================
//
//  MultiThreader Test 1 --- Spawn Thread Test
//
//  This test check the behaviour of igtl::MultiThreader::SpawnThread
//  and igtl::MutexLock.
//  The test create NUM_THREAD threads from a single method that repeats:
//
//     s1 = s;
//     sleep(interval)
//     s2 = s;
//     s = s1 + s2;
//
//  for NUM_REPEAT times, where 's' is a global variable (shared by all
//  threads) initialized with 1, and 's1', 's2' and 'interval' are local
//  variables. 'interval' differs from thread to thread.
//  If the threads work correctly, and the code block above is properly
//  protected by a semaphore, 's' finally becomes 2^(NUM_REPEAT * NUM_THREAD-1).
//  
//=========================================================================


#include "igtlMultiThreader.h"
#include "igtlOSUtil.h"

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

// NOTE: (NUM_THREAD + NUM_REPEAT) < 32 on 32-bit environment
#if IGTL_MAX_THREADS > 1
  #define NUM_THREAD   5
  #define NUM_REPEAT   4
#else
  #define NUM_THREAD   1
  #define NUM_REPEAT   4
#endif


typedef struct {
  int   nloop;
  int   *sum;
  igtl::MutexLock::Pointer glock;
} ThreadData;


void* ThreadFunction(void* ptr)
{
  // Get thread information
  igtl::MultiThreader::ThreadInfo* info = 
    static_cast<igtl::MultiThreader::ThreadInfo*>(ptr);
  int id = info->ThreadID;

  // Set interval at 100 * id (ms)
  long interval = 10*id;

  ThreadData* data = static_cast<ThreadData*>(info->UserData);
  int nloop = data->nloop;
  igtl::MutexLock::Pointer glock = data->glock;

  for (int i = 0; i < nloop; i ++)
    {
    glock->Lock();
    int s1 = *(data->sum);
    igtl::Sleep(interval);
    int s2 = *(data->sum);
    *(data->sum) = s1 + s2;
    glock->Unlock();
    }

  return NULL;
}


int main(int , char * [] )
{

  igtl::MutexLock::Pointer glock = igtl::MutexLock::New();

  int sum = 1;

  ThreadData td;
  td.nloop = NUM_REPEAT;
  td.sum   = &sum;
  td.glock = glock;
  
  igtl::MultiThreader::Pointer threader = igtl::MultiThreader::New();

  int id1 = threader->SpawnThread((igtl::ThreadFunctionType) &ThreadFunction, &td);
  int id2 = threader->SpawnThread((igtl::ThreadFunctionType) &ThreadFunction, &td);
  int id3 = threader->SpawnThread((igtl::ThreadFunctionType) &ThreadFunction, &td);
  int id4 = threader->SpawnThread((igtl::ThreadFunctionType) &ThreadFunction, &td);
  int id5 = threader->SpawnThread((igtl::ThreadFunctionType) &ThreadFunction, &td);

  // wait for the threads
  threader->TerminateThread(id1);
  threader->TerminateThread(id2);
  threader->TerminateThread(id3);
  threader->TerminateThread(id4);
  threader->TerminateThread(id5);

  int answer = 0x00000001;
  answer <<= (NUM_THREAD * NUM_REPEAT);

  //std::cerr << "sum = " << sum << "  answer = " << answer << std::endl;

  if (sum == answer)
    {
    return EXIT_SUCCESS;
    }
  else
    {
    return EXIT_FAILURE;
    }
}