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 "JackCompilerDeps.h"
00025 #include <string.h>
00026
00027 namespace Jack
00028 {
00029
00034 struct AtomicCounter
00035 {
00036 union {
00037 struct {
00038 UInt16 fShortVal1;
00039 UInt16 fShortVal2;
00040 }
00041 scounter;
00042 UInt32 fLongVal;
00043 }info;
00044
00045 AtomicCounter()
00046 {
00047 info.fLongVal = 0;
00048 }
00049
00050 AtomicCounter(volatile const AtomicCounter& obj)
00051 {
00052 info.fLongVal = obj.info.fLongVal;
00053 }
00054
00055 AtomicCounter(volatile AtomicCounter& obj)
00056 {
00057 info.fLongVal = obj.info.fLongVal;
00058 }
00059
00060 AtomicCounter& operator=(AtomicCounter& obj)
00061 {
00062 info.fLongVal = obj.info.fLongVal;
00063 return *this;
00064 }
00065
00066 AtomicCounter& operator=(volatile AtomicCounter& obj)
00067 {
00068 info.fLongVal = obj.info.fLongVal;
00069 return *this;
00070 }
00071
00072 } POST_PACKED_STRUCTURE;
00073
00074 #define Counter(e) (e).info.fLongVal
00075 #define CurIndex(e) (e).info.scounter.fShortVal1
00076 #define NextIndex(e) (e).info.scounter.fShortVal2
00077
00078 #define CurArrayIndex(e) (CurIndex(e) & 0x0001)
00079 #define NextArrayIndex(e) ((CurIndex(e) + 1) & 0x0001)
00080
00085
00086
00087 template <class T>
00088 class JackAtomicState
00089 {
00090
00091 protected:
00092
00093 T fState[2];
00094 volatile AtomicCounter fCounter;
00095 SInt32 fCallWriteCounter;
00096
00097 UInt32 WriteNextStateStartAux()
00098 {
00099 AtomicCounter old_val;
00100 AtomicCounter new_val;
00101 UInt32 cur_index;
00102 UInt32 next_index;
00103 bool need_copy;
00104 do {
00105 old_val = fCounter;
00106 new_val = old_val;
00107 cur_index = CurArrayIndex(new_val);
00108 next_index = NextArrayIndex(new_val);
00109 need_copy = (CurIndex(new_val) == NextIndex(new_val));
00110 NextIndex(new_val) = CurIndex(new_val);
00111 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00112 if (need_copy)
00113 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00114 return next_index;
00115 }
00116
00117 void WriteNextStateStopAux()
00118 {
00119 AtomicCounter old_val;
00120 AtomicCounter new_val;
00121 do {
00122 old_val = fCounter;
00123 new_val = old_val;
00124 NextIndex(new_val)++;
00125 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00126 }
00127
00128 public:
00129
00130 JackAtomicState()
00131 {
00132 Counter(fCounter) = 0;
00133 fCallWriteCounter = 0;
00134 }
00135
00136 ~JackAtomicState()
00137 {}
00138
00142 T* ReadCurrentState()
00143 {
00144 return &fState[CurArrayIndex(fCounter)];
00145 }
00146
00150 UInt16 GetCurrentIndex()
00151 {
00152 return CurIndex(fCounter);
00153 }
00154
00158 T* TrySwitchState()
00159 {
00160 AtomicCounter old_val;
00161 AtomicCounter new_val;
00162 do {
00163 old_val = fCounter;
00164 new_val = old_val;
00165 CurIndex(new_val) = NextIndex(new_val);
00166 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00167 return &fState[CurArrayIndex(fCounter)];
00168 }
00169
00173 T* TrySwitchState(bool* result)
00174 {
00175 AtomicCounter old_val;
00176 AtomicCounter new_val;
00177 do {
00178 old_val = fCounter;
00179 new_val = old_val;
00180 *result = (CurIndex(new_val) != NextIndex(new_val));
00181 CurIndex(new_val) = NextIndex(new_val);
00182 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00183 return &fState[CurArrayIndex(fCounter)];
00184 }
00185
00189 T* WriteNextStateStart()
00190 {
00191 UInt32 next_index = (fCallWriteCounter++ == 0)
00192 ? WriteNextStateStartAux()
00193 : NextArrayIndex(fCounter);
00194 return &fState[next_index];
00195 }
00196
00200 void WriteNextStateStop()
00201 {
00202 if (--fCallWriteCounter == 0)
00203 WriteNextStateStopAux();
00204 }
00205
00206 bool IsPendingChange()
00207 {
00208 return CurIndex(fCounter) != NextIndex(fCounter);
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 } POST_PACKED_STRUCTURE;
00256
00257 }
00258
00259 #endif
00260