Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_Lockless.h
Go to the documentation of this file.
1 /************************************************************************************
2 
3 PublicHeader: OVR.h
4 Filename : OVR_Lockless.h
5 Content : Lock-less classes for producer/consumer communication
6 Created : November 9, 2013
7 Authors : John Carmack
8 
9 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
10 
11 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
15 
16 You may obtain a copy of the License at
17 
18 http://www.oculusvr.com/licenses/LICENSE-3.1
19 
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
25 
26 *************************************************************************************/
27 
28 #ifndef OVR_Lockless_h
29 #define OVR_Lockless_h
30 
31 #include "OVR_Atomic.h"
32 
33 // Define this to compile-in Lockless test logic
34 //#define OVR_LOCKLESS_TEST
35 
36 namespace OVR {
37 
38 
39 // ***** LocklessUpdater
40 
41 // For single producer cases where you only care about the most recent update, not
42 // necessarily getting every one that happens (vsync timing, SensorFusion updates).
43 //
44 // This is multiple consumer safe, but is currently only used with a single consumer.
45 
46 template<class T>
48 {
49 public:
51 
52  T GetState() const
53  {
54  // Copy the state out, then retry with the alternate slot
55  // if we determine that our copy may have been partially
56  // stepped on by a new update.
57  T state;
58  int begin, end, final;
59 
60  for(;;)
61  {
62  // We are adding 0, only using these as atomic memory barriers, so it
63  // is ok to cast off the const, allowing GetState() to remain const.
64  end = UpdateEnd.ExchangeAdd_Sync(0);
65  state = Slots[ end & 1 ];
66  begin = UpdateBegin.ExchangeAdd_Sync(0);
67  if ( begin == end ) {
68  break;
69  }
70 
71  // The producer is potentially blocked while only having partially
72  // written the update, so copy out the other slot.
73  state = Slots[ (begin & 1) ^ 1 ];
75  if ( final == begin ) {
76  break;
77  }
78 
79  // The producer completed the last update and started a new one before
80  // we got it copied out, so try fetching the current buffer again.
81  }
82  return state;
83  }
84 
85  void SetState( T state )
86  {
87  const int slot = UpdateBegin.ExchangeAdd_Sync(1) & 1;
88  // Write to (slot ^ 1) because ExchangeAdd returns 'previous' value before add.
89  Slots[slot ^ 1] = state;
91  }
92 
95  T Slots[2];
96 };
97 
98 
99 #ifdef OVR_LOCKLESS_TEST
100 void StartLocklessTest();
101 #endif
102 
103 
104 } // namespace OVR
105 
106 #endif // OVR_Lockless_h
107 
T ExchangeAdd_NoSync(T val)
Definition: OVR_Atomic.h:699
AtomicInt< int > UpdateEnd
Definition: OVR_Lockless.h:94
AtomicInt< int > UpdateBegin
Definition: OVR_Lockless.h:93
void SetState(T state)
Definition: OVR_Lockless.h:85
T ExchangeAdd_Sync(T val)
Definition: OVR_Atomic.h:696