00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __JackAtomicState__
00021 #define __JackAtomicState__
00022
00023 #include "JackAtomic.h"
00024 #include <string.h>
00025
00026 namespace Jack
00027 {
00028
00033 struct AtomicCounter
00034 {
00035 union {
00036 struct {
00037 UInt16 fShortVal1;
00038 UInt16 fShortVal2;
00039 }
00040 scounter;
00041 UInt32 fLongVal;
00042 }info;
00043
00044 AtomicCounter()
00045 {
00046 info.fLongVal = 0;
00047 }
00048
00049 AtomicCounter(volatile const AtomicCounter& obj)
00050 {
00051 info.fLongVal = obj.info.fLongVal;
00052 }
00053
00054 AtomicCounter(volatile AtomicCounter& obj)
00055 {
00056 info.fLongVal = obj.info.fLongVal;
00057 }
00058
00059 AtomicCounter& operator=(AtomicCounter& obj)
00060 {
00061 info.fLongVal = obj.info.fLongVal;
00062 return *this;
00063 }
00064
00065 AtomicCounter& operator=(volatile AtomicCounter& obj)
00066 {
00067 info.fLongVal = obj.info.fLongVal;
00068 return *this;
00069 }
00070
00071 };
00072
00073 #define Counter(e) (e).info.fLongVal
00074 #define CurIndex(e) (e).info.scounter.fShortVal1
00075 #define NextIndex(e) (e).info.scounter.fShortVal2
00076
00077 #define CurArrayIndex(e) (CurIndex(e) & 0x0001)
00078 #define NextArrayIndex(e) ((CurIndex(e) + 1) & 0x0001)
00079
00084
00085
00086 template <class T>
00087 class JackAtomicState
00088 {
00089
00090 protected:
00091
00092 T fState[2];
00093 volatile AtomicCounter fCounter;
00094 SInt32 fCallWriteCounter;
00095
00096 UInt32 WriteNextStateStartAux()
00097 {
00098 AtomicCounter old_val;
00099 AtomicCounter new_val;
00100 UInt32 cur_index;
00101 UInt32 next_index;
00102 bool need_copy;
00103 do {
00104 old_val = fCounter;
00105 new_val = old_val;
00106 cur_index = CurArrayIndex(new_val);
00107 next_index = NextArrayIndex(new_val);
00108 need_copy = (CurIndex(new_val) == NextIndex(new_val));
00109 NextIndex(new_val) = CurIndex(new_val);
00110 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00111 if (need_copy)
00112 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00113 return next_index;
00114 }
00115
00116 void WriteNextStateStopAux()
00117 {
00118 AtomicCounter old_val;
00119 AtomicCounter new_val;
00120 do {
00121 old_val = fCounter;
00122 new_val = old_val;
00123 NextIndex(new_val)++;
00124 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00125 }
00126
00127 public:
00128
00129 JackAtomicState()
00130 {
00131 Counter(fCounter) = 0;
00132 fCallWriteCounter = 0;
00133 }
00134
00135 ~JackAtomicState()
00136 {}
00137
00141 T* ReadCurrentState()
00142 {
00143 return &fState[CurArrayIndex(fCounter)];
00144 }
00145
00149 UInt16 GetCurrentIndex()
00150 {
00151 return CurIndex(fCounter);
00152 }
00153
00157 T* TrySwitchState()
00158 {
00159 AtomicCounter old_val;
00160 AtomicCounter new_val;
00161 do {
00162 old_val = fCounter;
00163 new_val = old_val;
00164 CurIndex(new_val) = NextIndex(new_val);
00165 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00166 return &fState[CurArrayIndex(fCounter)];
00167 }
00168
00172 T* TrySwitchState(bool* result)
00173 {
00174 AtomicCounter old_val;
00175 AtomicCounter new_val;
00176 do {
00177 old_val = fCounter;
00178 new_val = old_val;
00179 *result = (CurIndex(new_val) != NextIndex(new_val));
00180 CurIndex(new_val) = NextIndex(new_val);
00181 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00182 return &fState[CurArrayIndex(fCounter)];
00183 }
00184
00188 T* WriteNextStateStart()
00189 {
00190 UInt32 next_index = (fCallWriteCounter++ == 0)
00191 ? WriteNextStateStartAux()
00192 : NextArrayIndex(fCounter);
00193 return &fState[next_index];
00194 }
00195
00199 void WriteNextStateStop()
00200 {
00201 if (--fCallWriteCounter == 0)
00202 WriteNextStateStopAux();
00203 }
00204
00205 bool IsPendingChange()
00206 {
00207 return CurIndex(fCounter) != NextIndex(fCounter);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 };
00254
00255
00256 }
00257
00258
00259 #endif
00260