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