Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #ifndef __JackAtomicArrayState__ 00021 #define __JackAtomicArrayState__ 00022 00023 #include "JackAtomic.h" 00024 #include "JackCompilerDeps.h" 00025 #include <string.h> // for memcpy 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() 00045 { 00046 info.fLongVal = 0; 00047 } 00048 00049 AtomicArrayCounter(volatile const AtomicArrayCounter& obj) 00050 { 00051 info.fLongVal = obj.info.fLongVal; 00052 } 00053 00054 AtomicArrayCounter(volatile AtomicArrayCounter& obj) 00055 { 00056 info.fLongVal = obj.info.fLongVal; 00057 } 00058 00059 AtomicArrayCounter& operator=(volatile AtomicArrayCounter& obj) 00060 { 00061 info.fLongVal = obj.info.fLongVal; 00062 return *this; 00063 } 00064 00065 AtomicArrayCounter& operator=(AtomicArrayCounter& obj) 00066 { 00067 info.fLongVal = obj.info.fLongVal; 00068 return *this; 00069 } 00070 00071 } POST_PACKED_STRUCTURE; 00072 00073 #define Counter1(e) (e).info.fLongVal 00074 #define GetIndex1(e, state) ((e).info.scounter.fByteVal[state]) 00075 #define SetIndex1(e, state, val) ((e).info.scounter.fByteVal[state] = val) 00076 #define IncIndex1(e, state) ((e).info.scounter.fByteVal[state]++) 00077 #define SwapIndex1(e, state) (((e).info.scounter.fByteVal[0] == state) ? 0 : state) 00078 00110 // CHECK livelock 00111 00112 template <class T> 00113 class JackAtomicArrayState 00114 { 00115 00116 protected: 00117 00118 // fState[0] ==> current 00119 // fState[1] ==> pending 00120 // fState[2] ==> request 00121 00122 T fState[3]; 00123 volatile AtomicArrayCounter fCounter; 00124 00125 UInt32 WriteNextStateStartAux(int state, bool* result) 00126 { 00127 AtomicArrayCounter old_val; 00128 AtomicArrayCounter new_val; 00129 UInt32 cur_index; 00130 UInt32 next_index; 00131 bool need_copy; 00132 do { 00133 old_val = fCounter; 00134 new_val = old_val; 00135 *result = GetIndex1(new_val, state); 00136 cur_index = GetIndex1(new_val, 0); 00137 next_index = SwapIndex1(fCounter, state); 00138 need_copy = (GetIndex1(new_val, state) == 0); // Written = false, switch just occured 00139 SetIndex1(new_val, state, 0); // Written = false, invalidate state 00140 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter)); 00141 if (need_copy) 00142 memcpy(&fState[next_index], &fState[cur_index], sizeof(T)); 00143 return next_index; 00144 } 00145 00146 void WriteNextStateStopAux(int state) 00147 { 00148 AtomicArrayCounter old_val; 00149 AtomicArrayCounter new_val; 00150 do { 00151 old_val = fCounter; 00152 new_val = old_val; 00153 SetIndex1(new_val, state, 1); // Written = true, state becomes "switchable" 00154 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter)); 00155 } 00156 00157 public: 00158 00159 JackAtomicArrayState() 00160 { 00161 Counter1(fCounter) = 0; 00162 } 00163 00164 ~JackAtomicArrayState() // Not virtual ?? 00165 {} 00166 00171 T* ReadCurrentState() 00172 { 00173 return &fState[GetIndex1(fCounter, 0)]; 00174 } 00175 00180 UInt16 GetCurrentIndex() 00181 { 00182 return GetIndex1(fCounter, 3); 00183 } 00184 00189 T* TrySwitchState(int state) 00190 { 00191 AtomicArrayCounter old_val; 00192 AtomicArrayCounter new_val; 00193 do { 00194 old_val = fCounter; 00195 new_val = old_val; 00196 if (GetIndex1(new_val, state)) { // If state has been written 00197 SetIndex1(new_val, 0, SwapIndex1(new_val, state)); // Prepare switch 00198 SetIndex1(new_val, state, 0); // Invalidate the state "state" 00199 IncIndex1(new_val, 3); // Inc switch 00200 } 00201 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter)); 00202 return &fState[GetIndex1(fCounter, 0)]; // Read the counter again 00203 } 00204 00209 T* TrySwitchState(int state, bool* result) 00210 { 00211 AtomicArrayCounter old_val; 00212 AtomicArrayCounter new_val; 00213 do { 00214 old_val = fCounter; 00215 new_val = old_val; 00216 if ((*result = GetIndex1(new_val, state))) { // If state has been written 00217 SetIndex1(new_val, 0, SwapIndex1(new_val, state)); // Prepare switch 00218 SetIndex1(new_val, state, 0); // Invalidate the state "state" 00219 IncIndex1(new_val, 3); // Inc switch 00220 } 00221 } while (!CAS(Counter1(old_val), Counter1(new_val), (UInt32*)&fCounter)); 00222 return &fState[GetIndex1(fCounter, 0)]; // Read the counter again 00223 } 00224 00229 T* WriteNextStateStart(int state) 00230 { 00231 bool tmp; 00232 UInt32 index = WriteNextStateStartAux(state, &tmp); 00233 return &fState[index]; 00234 } 00235 00236 T* WriteNextStateStart(int state, bool* result) 00237 { 00238 UInt32 index = WriteNextStateStartAux(state, result); 00239 return &fState[index]; 00240 } 00241 00246 void WriteNextStateStop(int state) 00247 { 00248 WriteNextStateStopAux(state); 00249 } 00250 00251 } POST_PACKED_STRUCTURE; 00252 00253 } // end of namespace 00254 00255 00256 #endif 00257