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
00033 PRE_PACKED_STRUCTURE
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 PRE_PACKED_STRUCTURE
00113 template <class T>
00114 class JackAtomicArrayState
00115 {
00116
00117 protected:
00118
00119
00120
00121
00122
00123 T fState[3];
00124 volatile AtomicArrayCounter fCounter;
00125
00126 UInt32 WriteNextStateStartAux(int state, bool* result)
00127 {
00128 AtomicArrayCounter old_val;
00129 AtomicArrayCounter new_val;
00130 UInt32 cur_index;
00131 UInt32 next_index;
00132 bool need_copy;
00133 do {
00134 old_val = fCounter;
00135 new_val = old_val;
00136 *result = GetIndex1(new_val, state);
00137 cur_index = GetIndex1(new_val, 0);
00138 next_index = SwapIndex1(fCounter, state);
00139 need_copy = (GetIndex1(new_val, state) == 0);
00140 SetIndex1(new_val, state, 0);
00141 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00142 if (need_copy)
00143 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00144 return next_index;
00145 }
00146
00147 void WriteNextStateStopAux(int state)
00148 {
00149 AtomicArrayCounter old_val;
00150 AtomicArrayCounter new_val;
00151 do {
00152 old_val = fCounter;
00153 new_val = old_val;
00154 SetIndex1(new_val, state, 1);
00155 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00156 }
00157
00158 public:
00159
00160 JackAtomicArrayState()
00161 {
00162 Counter1(fCounter) = 0;
00163 }
00164
00165 ~JackAtomicArrayState()
00166 {}
00167
00172 T* ReadCurrentState()
00173 {
00174 return &fState[GetIndex1(fCounter, 0)];
00175 }
00176
00181 UInt16 GetCurrentIndex()
00182 {
00183 return GetIndex1(fCounter, 3);
00184 }
00185
00190 T* TrySwitchState(int state)
00191 {
00192 AtomicArrayCounter old_val;
00193 AtomicArrayCounter new_val;
00194 do {
00195 old_val = fCounter;
00196 new_val = old_val;
00197 if (GetIndex1(new_val, state)) {
00198 SetIndex1(new_val, 0, SwapIndex1(new_val, state));
00199 SetIndex1(new_val, state, 0);
00200 IncIndex1(new_val, 3);
00201 }
00202 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00203 return &fState[GetIndex1(fCounter, 0)];
00204 }
00205
00210 T* TrySwitchState(int state, bool* result)
00211 {
00212 AtomicArrayCounter old_val;
00213 AtomicArrayCounter new_val;
00214 do {
00215 old_val = fCounter;
00216 new_val = old_val;
00217 if ((*result = GetIndex1(new_val, state))) {
00218 SetIndex1(new_val, 0, SwapIndex1(new_val, state));
00219 SetIndex1(new_val, state, 0);
00220 IncIndex1(new_val, 3);
00221 }
00222 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00223 return &fState[GetIndex1(fCounter, 0)];
00224 }
00225
00230 T* WriteNextStateStart(int state)
00231 {
00232 bool tmp;
00233 UInt32 index = WriteNextStateStartAux(state, &tmp);
00234 return &fState[index];
00235 }
00236
00237 T* WriteNextStateStart(int state, bool* result)
00238 {
00239 UInt32 index = WriteNextStateStartAux(state, result);
00240 return &fState[index];
00241 }
00242
00247 void WriteNextStateStop(int state)
00248 {
00249 WriteNextStateStopAux(state);
00250 }
00251
00252 } POST_PACKED_STRUCTURE;
00253
00254 }
00255
00256
00257 #endif
00258