1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    otherArrays.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkAtomicInt.h"
16 #include "vtkNew.h"
17 #include "vtkObjectFactory.h"
18 #include "vtkMultiThreader.h"
19 
20 static int Total = 0;
21 static vtkTypeInt64 Total64 = 0;
22 static vtkAtomicInt<vtkTypeInt32> TotalAtomic(0);
23 static vtkAtomicInt<vtkTypeInt64> TotalAtomic64(0);
24 static const int Target = 1000000;
25 static int Values32[Target+2];
26 static int Values64[Target+2];
27 static int NumThreads = 5;
28 
29 static vtkObject* AnObject;
30 
MyFunction(void *)31 VTK_THREAD_RETURN_TYPE MyFunction(void *)
32 {
33   for (int i=0; i<Target/NumThreads; i++)
34     {
35     Total++;
36     int idx = ++TotalAtomic;
37     Values32[idx] = 1;
38 
39     Total64++;
40     idx = ++TotalAtomic64;
41     Values64[idx] = 1;
42 
43     //AnObject->Register(0);
44     //AnObject->UnRegister(0);
45 
46     AnObject->Modified();
47     }
48 
49   return VTK_THREAD_RETURN_VALUE;
50 }
51 
MyFunction2(void *)52 VTK_THREAD_RETURN_TYPE MyFunction2(void *)
53 {
54   for (int i=0; i<Target/NumThreads; i++)
55     {
56     --TotalAtomic;
57 
58     --TotalAtomic64;
59     }
60 
61   return VTK_THREAD_RETURN_VALUE;
62 }
63 
MyFunction3(void *)64 VTK_THREAD_RETURN_TYPE MyFunction3(void *)
65 {
66   for (int i=0; i<Target/NumThreads; i++)
67     {
68     int idx = TotalAtomic += 1;
69     Values32[idx]++;
70 
71     idx = TotalAtomic64 += 1;
72     Values64[idx]++;
73     }
74 
75   return VTK_THREAD_RETURN_VALUE;
76 }
77 
MyFunction4(void *)78 VTK_THREAD_RETURN_TYPE MyFunction4(void *)
79 {
80   for (int i=0; i<Target/NumThreads; i++)
81     {
82     TotalAtomic++;
83     TotalAtomic += 1;
84     TotalAtomic--;
85     TotalAtomic -= 1;
86 
87     TotalAtomic64++;
88     TotalAtomic64 += 1;
89     TotalAtomic64--;
90     TotalAtomic64 -= 1;
91     }
92 
93   return VTK_THREAD_RETURN_VALUE;
94 }
95 
TestAtomic(int,char * [])96 int TestAtomic(int, char*[])
97 {
98   Total = 0;
99   TotalAtomic = 0;
100   Total64 = 0;
101   TotalAtomic64 = 0;
102 
103   AnObject = vtkObject::New();
104 
105   //cout << AnObject->GetReferenceCount() << endl;
106 
107   int beforeMTime = AnObject->GetMTime();
108 
109   for (int i=0; i<Target; i++)
110     {
111     Values32[i] = 0;
112     Values64[i] = 0;
113     }
114 
115   vtkNew<vtkMultiThreader> mt;
116   mt->SetSingleMethod(MyFunction, NULL);
117   mt->SetNumberOfThreads(NumThreads);
118   mt->SingleMethodExecute();
119 
120   mt->SetSingleMethod(MyFunction2, NULL);
121   mt->SingleMethodExecute();
122 
123   mt->SetSingleMethod(MyFunction3, NULL);
124   mt->SingleMethodExecute();
125 
126   // Making sure that atomic incr returned unique
127   // values each time. We expect all numbers from
128   // 1 to Target-1 to be 2.
129   if (Values32[0] != 0)
130     {
131       cout << "Expecting Values32[0] to be 0. Got "
132            << Values32[0] << endl;
133       return 1;
134     }
135   if (Values64[0] != 0)
136     {
137       cout << "Expecting Values64[0] to be 0. Got "
138            << Values64[0] << endl;
139       return 1;
140     }
141   for (int i=1; i<Target; i++)
142     {
143     if (Values32[i] != 2)
144       {
145       cout << "Expecting Values32[" << i << "] to be 2. Got "
146            << Values32[i] << endl;
147       return 1;
148       }
149     if (Values64[i] != 2)
150       {
151       cout << "Expecting Values64[" << i << "] to be 2. Got "
152            << Values64[i] << endl;
153       return 1;
154       }
155     }
156 
157   mt->SetSingleMethod(MyFunction4, NULL);
158   mt->SingleMethodExecute();
159 
160   cout << Total << " " << TotalAtomic.load() << endl;
161   cout << Total64 << " " << TotalAtomic64.load() << endl;
162 
163   //cout << AnObject->GetReferenceCount() << endl;
164 
165   cout << "MTime: " << AnObject->GetMTime() << endl;
166 
167   if (TotalAtomic.load() != Target)
168     {
169     return 1;
170     }
171 
172   if (TotalAtomic64.load() != Target)
173     {
174     return 1;
175     }
176 
177   if (AnObject->GetReferenceCount() != 1)
178     {
179     return 1;
180     }
181 
182   if ((int)AnObject->GetMTime() != Target + beforeMTime + 2)
183     {
184     return 1;
185     }
186 
187   AnObject->Delete();
188   return 0;
189 }
190