ovr_sdk

view LibOVR/Src/Kernel/OVR_Lockless.cpp @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
parents
children
line source
1 /************************************************************************************
3 Filename : OVR_Lockless.cpp
4 Content : Test logic for lock-less classes
5 Created : December 27, 2013
6 Authors : Michael Antonov
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 You may obtain a copy of the License at
17 http://www.oculusvr.com/licenses/LICENSE-3.2
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
25 *************************************************************************************/
27 #include "OVR_Lockless.h"
29 #ifdef OVR_LOCKLESS_TEST
31 #include "OVR_Threads.h"
32 #include "OVR_Timer.h"
33 #include "OVR_Log.h"
35 namespace OVR { namespace LocklessTest {
38 const int TestIterations = 10000000;
40 // Use volatile dummies to force compiler to do spinning.
41 volatile int Dummy1;
42 int Unused1[32];
43 volatile int Dummy2;
44 int Unused2[32];
45 volatile int Dummy3;
46 int Unused3[32];
49 // Data block out of 20 consecutive integers, should be internally consistent.
50 struct TestData
51 {
52 enum { ItemCount = 20 };
54 int Data[ItemCount];
57 void Set(int val)
58 {
59 for (int i=0; i<ItemCount; i++)
60 {
61 Data[i] = val*100 + i;
62 }
63 }
65 int ReadAndCheckConsistency(int prevValue) const
66 {
67 int val = Data[0];
69 for (int i=1; i<ItemCount; i++)
70 {
72 if (Data[i] != (val + i))
73 {
74 // Only complain once per same-value entry
75 if (prevValue != val / 100)
76 {
77 LogText("LocklessTest Fail - corruption at %d inside block %d\n",
78 i, val/100);
79 // OVR_ASSERT(Data[i] == val + i);
80 }
81 break;
82 }
83 }
85 return val / 100;
86 }
87 };
91 volatile bool FirstItemWritten = false;
92 LocklessUpdater<TestData, TestData> TestDataUpdater;
94 // Use this lock to verify that testing algorithm is otherwise correct...
95 Lock TestLock;
98 //-------------------------------------------------------------------------------------
100 // Consumer thread reads values from TestDataUpdater and
101 // ensures that each one is internally consistent.
103 class Consumer : public Thread
104 {
105 virtual int Run()
106 {
107 LogText("LocklessTest::Consumer::Run started.\n");
109 while (!FirstItemWritten)
110 {
111 // spin until producer wrote first value...
112 }
114 TestData d;
115 int oldValue = 0;
116 int newValue;
118 do
119 {
120 {
121 //Lock::Locker scope(&TestLock);
122 d = TestDataUpdater.GetState();
123 }
125 newValue = d.ReadAndCheckConsistency(oldValue);
127 // Values should increase or stay the same!
128 if (newValue < oldValue)
129 {
130 LogText("LocklessTest Fail - %d after %d; delta = %d\n",
131 newValue, oldValue, newValue - oldValue);
132 // OVR_ASSERT(0);
133 }
136 if (oldValue != newValue)
137 {
138 oldValue = newValue;
140 if (oldValue % (TestIterations/30) == 0)
141 {
142 LogText("LocklessTest::Consumer - %5.2f%% done\n",
143 100.0f * (float)oldValue/(float)TestIterations);
144 }
145 }
147 // Spin a while
148 for (int j = 0; j< 300; j++)
149 {
150 Dummy3 = j;
151 }
154 } while (oldValue < (TestIterations * 99 / 100));
156 LogText("LocklessTest::Consumer::Run exiting.\n");
157 return 0;
158 }
160 };
163 //-------------------------------------------------------------------------------------
165 class Producer : public Thread
166 {
168 virtual int Run()
169 {
170 LogText("LocklessTest::Producer::Run started.\n");
172 for (int testVal = 0; testVal < TestIterations; testVal++)
173 {
174 TestData d;
175 d.Set(testVal);
177 {
178 //Lock::Locker scope(&TestLock);
179 TestDataUpdater.SetState(d);
180 }
182 FirstItemWritten = true;
184 // Spin a bit
185 for(int j = 0; j < 1000; j++)
186 {
187 Dummy2 = j;
188 }
190 if (testVal % (TestIterations/30) == 0)
191 {
192 LogText("LocklessTest::Producer - %5.2f%% done\n",
193 100.0f * (float)testVal/(float)TestIterations);
194 }
195 }
197 LogText("LocklessTest::Producer::Run exiting.\n");
198 return 0;
199 }
200 };
203 } // namespace LocklessTest
207 void StartLocklessTest()
208 {
209 // These threads will release themselves once done
210 Ptr<LocklessTest::Producer> producerThread = *new LocklessTest::Producer;
211 Ptr<LocklessTest::Consumer> consumerThread = *new LocklessTest::Consumer;
213 producerThread->Start();
214 consumerThread->Start();
216 while (!producerThread->IsFinished() && consumerThread->IsFinished())
217 {
218 Thread::MSleep(500);
219 }
220 }
223 } // namespace OVR
225 #endif // OVR_LOCKLESS_TEST