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