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& operator=(volatile AtomicCounter& obj)
00045 {
00046 info.fLongVal = obj.info.fLongVal;
00047 return *this;
00048 }
00049
00050 };
00051
00052
00053 #define Counter(e) (e).info.fLongVal
00054 #define CurIndex(e) (e).info.scounter.fShortVal1
00055 #define NextIndex(e) (e).info.scounter.fShortVal2
00056
00057 #define CurArrayIndex(e) (CurIndex(e) & 0x0001)
00058 #define NextArrayIndex(e) ((CurIndex(e) + 1) & 0x0001)
00059
00064
00065
00066 template <class T>
00067 class JackAtomicState
00068 {
00069
00070 protected:
00071
00072 T fState[2];
00073 volatile AtomicCounter fCounter;
00074 SInt32 fCallWriteCounter;
00075
00076 UInt32 WriteNextStateStartAux()
00077 {
00078 AtomicCounter old_val;
00079 AtomicCounter new_val;
00080 UInt32 cur_index;
00081 UInt32 next_index;
00082 bool need_copy;
00083 do {
00084 old_val = fCounter;
00085 new_val = old_val;
00086 cur_index = CurArrayIndex(new_val);
00087 next_index = NextArrayIndex(new_val);
00088 need_copy = (CurIndex(new_val) == NextIndex(new_val));
00089 NextIndex(new_val) = CurIndex(new_val);
00090 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00091 if (need_copy)
00092 memcpy(&fState[next_index], &fState[cur_index], sizeof(T));
00093 return next_index;
00094 }
00095
00096 void WriteNextStateStopAux()
00097 {
00098 AtomicCounter old_val;
00099 AtomicCounter new_val;
00100 do {
00101 old_val = fCounter;
00102 new_val = old_val;
00103 NextIndex(new_val)++;
00104 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00105 }
00106
00107 public:
00108
00109 JackAtomicState()
00110 {
00111 Counter(fCounter) = 0;
00112 fCallWriteCounter = 0;
00113 }
00114
00115 ~JackAtomicState()
00116 {}
00117
00121 T* ReadCurrentState()
00122 {
00123 return &fState[CurArrayIndex(fCounter)];
00124 }
00125
00129 UInt16 GetCurrentIndex()
00130 {
00131 return CurIndex(fCounter);
00132 }
00133
00137 T* TrySwitchState()
00138 {
00139 AtomicCounter old_val;
00140 AtomicCounter new_val;
00141 do {
00142 old_val = fCounter;
00143 new_val = old_val;
00144 CurIndex(new_val) = NextIndex(new_val);
00145 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00146 return &fState[CurArrayIndex(fCounter)];
00147 }
00148
00152 T* TrySwitchState(bool* result)
00153 {
00154 AtomicCounter old_val;
00155 AtomicCounter new_val;
00156 do {
00157 old_val = fCounter;
00158 new_val = old_val;
00159 *result = (CurIndex(new_val) != NextIndex(new_val));
00160 CurIndex(new_val) = NextIndex(new_val);
00161 } while (!CAS(Counter(old_val), Counter(new_val), (UInt32*)&fCounter));
00162 return &fState[CurArrayIndex(fCounter)];
00163 }
00164
00168 T* WriteNextStateStart()
00169 {
00170 UInt32 next_index = (fCallWriteCounter++ == 0)
00171 ? WriteNextStateStartAux()
00172 : NextArrayIndex(fCounter);
00173 return &fState[next_index];
00174 }
00175
00179 void WriteNextStateStop()
00180 {
00181 if (--fCallWriteCounter == 0)
00182 WriteNextStateStopAux();
00183 }
00184
00185 bool IsPendingChange()
00186 {
00187 return CurIndex(fCounter) != NextIndex(fCounter);
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
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 #endif
00240