00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __JackAtomicArrayState__
00021 #define __JackAtomicArrayState__
00022
00023 #include "JackAtomic.h"
00024 #include <string.h>
00025
00026 namespace Jack
00027 {
00028
00033 struct AtomicArrayCounter
00034 {
00035 union {
00036 struct {
00037 unsigned char fByteVal[4];
00038 }
00039 scounter;
00040 UInt32 fLongVal;
00041 }info;
00042
00043 AtomicArrayCounter()
00044 {
00045 info.fLongVal = 0;
00046 }
00047
00048 AtomicArrayCounter(volatile const AtomicArrayCounter& obj)
00049 {
00050 info.fLongVal = obj.info.fLongVal;
00051 }
00052
00053 AtomicArrayCounter(volatile AtomicArrayCounter& obj)
00054 {
00055 info.fLongVal = obj.info.fLongVal;
00056 }
00057
00058 AtomicArrayCounter& operator=(volatile AtomicArrayCounter& obj)
00059 {
00060 info.fLongVal = obj.info.fLongVal;
00061 return *this;
00062 }
00063
00064 AtomicArrayCounter& operator=(AtomicArrayCounter& obj)
00065 {
00066 info.fLongVal = obj.info.fLongVal;
00067 return *this;
00068 }
00069
00070 };
00071
00072 #define Counter1(e) (e).info.fLongVal
00073 #define GetIndex1(e, state) ((e).info.scounter.fByteVal[state])
00074 #define SetIndex1(e, state, val) ((e).info.scounter.fByteVal[state] = val)
00075 #define IncIndex1(e, state) ((e).info.scounter.fByteVal[state]++)
00076 #define SwapIndex1(e, state) (((e).info.scounter.fByteVal[0] == state) ? 0 : state)
00077
00109
00110
00111 template <class T>
00112 class JackAtomicArrayState
00113 {
00114
00115 protected:
00116
00117
00118
00119
00120
00121 T fState[3];
00122 volatile AtomicArrayCounter fCounter;
00123
00124 UInt32 WriteNextStateStartAux(int state, bool* result)
00125 {
00126 AtomicArrayCounter old_val;
00127 AtomicArrayCounter new_val;
00128 UInt32 cur_index;
00129 UInt32 next_index;
00130 bool need_copy;
00131 do {
00132 old_val = fCounter;
00133 new_val = old_val;
00134 *result = GetIndex1(new_val, state);
00135 cur_index = GetIndex1(new_val, 0);
00136 next_index = SwapIndex1(fCounter, state);
00137 need_copy = (GetIndex1(new_val, state) == 0);
00138 SetIndex1(new_val, state, 0);
00139 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00140 if (need_copy)
00141 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00142 return next_index;
00143 }
00144
00145 void WriteNextStateStopAux(int state)
00146 {
00147 AtomicArrayCounter old_val;
00148 AtomicArrayCounter new_val;
00149 do {
00150 old_val = fCounter;
00151 new_val = old_val;
00152 SetIndex1(new_val, state, 1);
00153 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00154 }
00155
00156 public:
00157
00158 JackAtomicArrayState()
00159 {
00160 Counter1(fCounter) = 0;
00161 }
00162
00163 ~JackAtomicArrayState()
00164 {}
00165
00170 T* ReadCurrentState()
00171 {
00172 return &fState[GetIndex1(fCounter, 0)];
00173 }
00174
00179 UInt16 GetCurrentIndex()
00180 {
00181 return GetIndex1(fCounter, 3);
00182 }
00183
00188 T* TrySwitchState(int state)
00189 {
00190 AtomicArrayCounter old_val;
00191 AtomicArrayCounter new_val;
00192 do {
00193 old_val = fCounter;
00194 new_val = old_val;
00195 if (GetIndex1(new_val, state)) {
00196 SetIndex1(new_val, 0, SwapIndex1(new_val, state));
00197 SetIndex1(new_val, state, 0);
00198 IncIndex1(new_val, 3);
00199 }
00200 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00201 return &fState[GetIndex1(fCounter, 0)];
00202 }
00203
00208 T* TrySwitchState(int state, bool* result)
00209 {
00210 AtomicArrayCounter old_val;
00211 AtomicArrayCounter new_val;
00212 do {
00213 old_val = fCounter;
00214 new_val = old_val;
00215 if ((*result = GetIndex1(new_val, state))) {
00216 SetIndex1(new_val, 0, SwapIndex1(new_val, state));
00217 SetIndex1(new_val, state, 0);
00218 IncIndex1(new_val, 3);
00219 }
00220 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00221 return &fState[GetIndex1(fCounter, 0)];
00222 }
00223
00228 T* WriteNextStateStart(int state)
00229 {
00230 bool tmp;
00231 UInt32 index = WriteNextStateStartAux(state, &tmp);
00232 return &fState[index];
00233 }
00234
00235 T* WriteNextStateStart(int state, bool* result)
00236 {
00237 UInt32 index = WriteNextStateStartAux(state, result);
00238 return &fState[index];
00239 }
00240
00245 void WriteNextStateStop(int state)
00246 {
00247 WriteNextStateStopAux(state);
00248 }
00249
00250 };
00251
00252 }
00253
00254
00255 #endif
00256