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 "JackError.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& operator=(volatile AtomicArrayCounter& obj)
00045 {
00046 info.fLongVal = obj.info.fLongVal;
00047 return *this;
00048 }
00049 };
00050
00051 #define Counter1(e) (e).info.fLongVal
00052 #define GetIndex1(e, state) ((e).info.scounter.fByteVal[state])
00053 #define SetIndex1(e, state, val) ((e).info.scounter.fByteVal[state] = val)
00054 #define IncIndex1(e, state) ((e).info.scounter.fByteVal[state]++)
00055 #define SwapIndex1(e, state) (((e).info.scounter.fByteVal[0] == state) ? 0 : state)
00056
00088
00089
00090 template <class T>
00091 class JackAtomicArrayState
00092 {
00093
00094 protected:
00095
00096
00097
00098
00099
00100 T fState[3];
00101 volatile AtomicArrayCounter fCounter;
00102
00103 UInt32 WriteNextStateStartAux(int state, bool* result)
00104 {
00105 AtomicArrayCounter old_val;
00106 AtomicArrayCounter new_val;
00107 UInt32 cur_index;
00108 UInt32 next_index;
00109 bool need_copy;
00110 do {
00111 old_val = fCounter;
00112 new_val = old_val;
00113 *result = GetIndex1(new_val, state);
00114 cur_index = GetIndex1(new_val, 0);
00115 next_index = SwapIndex1(fCounter, state);
00116 need_copy = (GetIndex1(new_val, state) == 0);
00117 SetIndex1(new_val, state, 0);
00118 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00119 if (need_copy)
00120 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00121 return next_index;
00122 }
00123
00124 void WriteNextStateStopAux(int state)
00125 {
00126 AtomicArrayCounter old_val;
00127 AtomicArrayCounter new_val;
00128 do {
00129 old_val = fCounter;
00130 new_val = old_val;
00131 SetIndex1(new_val, state, 1);
00132 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00133 }
00134
00135 public:
00136
00137 JackAtomicArrayState()
00138 {
00139 JackLog("JackAtomicArrayState constructor\n");
00140 Counter1(fCounter) = 0;
00141 }
00142
00143 ~JackAtomicArrayState()
00144 {}
00145
00150 T* ReadCurrentState()
00151 {
00152 return &fState[GetIndex1(fCounter, 0)];
00153 }
00154
00159 UInt16 GetCurrentIndex()
00160 {
00161 return GetIndex1(fCounter, 3);
00162 }
00163
00168 T* TrySwitchState(int state)
00169 {
00170 AtomicArrayCounter old_val;
00171 AtomicArrayCounter new_val;
00172 do {
00173 old_val = fCounter;
00174 new_val = old_val;
00175 if (GetIndex1(new_val, state)) {
00176 SetIndex1(new_val, 0, SwapIndex1(new_val, state));
00177 SetIndex1(new_val, state, 0);
00178 IncIndex1(new_val, 3);
00179 }
00180 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter));
00181 return &fState[GetIndex1(fCounter, 0)];
00182 }
00183
00188 T* TrySwitchState(int state, bool* result)
00189 {
00190 AtomicArrayCounter old_val;
00191 AtomicArrayCounter new_val;
00192 do {
00193 old_val = fCounter;
00194 new_val = old_val;
00195 if ((*result = 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* WriteNextStateStart(int state)
00209 {
00210 bool tmp;
00211 UInt32 index = WriteNextStateStartAux(state, &tmp);
00212 return &fState[index];
00213 }
00214
00215 T* WriteNextStateStart(int state, bool* result)
00216 {
00217 UInt32 index = WriteNextStateStartAux(state, result);
00218 return &fState[index];
00219 }
00220
00224 void WriteNextStateStop(int state)
00225 {
00226 WriteNextStateStopAux(state);
00227 }
00228
00229 };
00230
00231 }
00232
00233
00234 #endif
00235