1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/veciter.h,v 1.39 2017/01/12 14:44:05 masarati Exp $ */ 2 /* 3 * MBDyn (C) is a multibody analysis code. 4 * http://www.mbdyn.org 5 * 6 * Copyright (C) 1996-2017 7 * 8 * Pierangelo Masarati <masarati@aero.polimi.it> 9 * Paolo Mantegazza <mantegazza@aero.polimi.it> 10 * 11 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano 12 * via La Masa, 34 - 20156 Milano, Italy 13 * http://www.aero.polimi.it 14 * 15 * Changing this copyright notice is forbidden. 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation (version 2 of the License). 20 * 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 30 */ 31 32 /* Iteratore per vettori */ 33 34 35 #ifndef VECITER_H 36 #define VECITER_H 37 38 #ifdef USE_MULTITHREAD 39 #include <signal.h> 40 #include "ac/spinlock.h" 41 #endif /* USE_MULTITHREAD */ 42 43 #include "myassert.h" 44 45 /* GetFirst ritorna true ed assegna a TReturn il primo item del vettore. 46 * Si assume che il vettore contenga almeno un termine; 47 * GetNext ritorna true ed assegna a TReturn il termine successivo se esiste, 48 * altrimenti ritorna false e l'assegnamento a TReturn e' unpredictable. */ 49 50 51 template <class T> 52 class Iter { 53 public: ~Iter(void)54 virtual ~Iter(void) { NO_OP; }; 55 virtual bool bGetFirst(T& TReturn) const = 0; 56 virtual bool bGetNext(T& TReturn) const = 0; 57 }; 58 59 template<class T> 60 class VecIter : public Iter<T> { 61 protected: 62 mutable T* pStart; 63 mutable T* pCount; 64 unsigned iSize; 65 66 public: VecIter(void)67 VecIter(void) : pStart(0), pCount(0), iSize(0) { NO_OP; }; VecIter(const T * p,unsigned i)68 VecIter(const T* p, unsigned i) : pStart(p), pCount(p), iSize(i) 69 { 70 ASSERT(pStart != 0); 71 ASSERT(iSize > 0); 72 }; 73 ~VecIter(void)74 virtual ~VecIter(void) 75 { 76 NO_OP; 77 }; 78 Init(const T * p,unsigned i)79 void Init(const T* p, unsigned i) 80 { 81 ASSERT(p != NULL); 82 ASSERT(i > 0); 83 84 pStart = pCount = const_cast<T *>(p); 85 iSize = i; 86 }; 87 bGetFirst(T & TReturn)88 inline bool bGetFirst(T& TReturn) const 89 { 90 ASSERT(pStart != NULL); 91 ASSERT(iSize > 0); 92 93 if (pStart == NULL) { 94 return false; 95 } 96 97 pCount = pStart; 98 TReturn = *pStart; 99 100 return true; 101 }; 102 bGetCurr(T & TReturn)103 inline bool bGetCurr(T& TReturn) const 104 { 105 ASSERT(pStart != NULL); 106 ASSERT(iSize > 0); 107 ASSERT(pCount >= pStart); 108 109 if (pCount == pStart + iSize) { 110 return false; 111 } 112 113 TReturn = *pCount; 114 115 return true; 116 }; 117 bGetNext(T & TReturn)118 inline bool bGetNext(T& TReturn) const 119 { 120 ASSERT(pStart != NULL); 121 ASSERT(iSize > 0); 122 ASSERT(pCount >= pStart); 123 124 ++pCount; 125 if (pCount == pStart + iSize) { 126 return false; 127 } 128 129 TReturn = *pCount; 130 131 return true; 132 }; 133 }; 134 135 #ifdef USE_MULTITHREAD 136 /* 137 * The user's class must inherit from InUse to be used by the MT_VecIter 138 * the user must reset the inuse flag by using SetInUse() before 139 * concurrently iterating over the array; the iterator provides a 140 * helper routine for this; provide it is called only once and not 141 * concurrently. 142 */ 143 class InUse { 144 private: 145 mutable volatile AO_TS_t inuse; 146 147 public: InUse(void)148 InUse(void) : inuse(AO_TS_INITIALIZER) { NO_OP; }; ~InUse(void)149 virtual ~InUse(void) { NO_OP; }; 150 bIsInUse(void)151 inline bool bIsInUse(void) const 152 { 153 /* 154 * If inuse is... 155 * true: leave it as is; return false 156 * false: make it true; return true 157 */ 158 /* FIXME: make it portable */ 159 160 return (mbdyn_test_and_set(&inuse) == AO_TS_CLEAR); 161 }; ReSetInUse()162 inline void ReSetInUse() { AO_CLEAR(&inuse); }; 163 }; 164 165 /* #define DEBUG_VECITER */ 166 167 template<class T> 168 class MT_VecIter : public VecIter<T> { 169 protected: 170 #ifdef DEBUG_VECITER 171 mutable unsigned iCount; 172 #endif /* DEBUG_VECITER */ 173 174 public: MT_VecIter(void)175 MT_VecIter(void) : VecIter<T>() { NO_OP; }; MT_VecIter(const T * p,unsigned i)176 MT_VecIter(const T* p, unsigned i) : VecIter<T>(p, i) 177 { 178 NO_OP; 179 }; 180 ~MT_VecIter(void)181 virtual ~MT_VecIter(void) 182 { 183 NO_OP; 184 }; 185 186 /* NOTE: it must be called only once */ ResetAccessData(void)187 void ResetAccessData(void) 188 { 189 ASSERT(VecIter<T>::pStart != NULL); 190 ASSERT(VecIter<T>::iSize > 0); 191 192 for (unsigned i = 0; i < VecIter<T>::iSize; i++) { 193 VecIter<T>::pStart[i]->ReSetInUse(); 194 } 195 } 196 bGetFirst(T & TReturn)197 inline bool bGetFirst(T& TReturn) const 198 { 199 ASSERT(VecIter<T>::pStart != NULL); 200 ASSERT(VecIter<T>::iSize > 0); 201 202 #ifdef DEBUG_VECITER 203 iCount = 0; 204 #endif /* DEBUG_VECITER */ 205 206 VecIter<T>::pCount = VecIter<T>::pStart - 1; 207 208 return bGetNext(TReturn); 209 }; 210 bGetCurr(T & TReturn)211 inline bool bGetCurr(T& TReturn) const 212 { 213 ASSERT(VecIter<T>::pStart != NULL); 214 ASSERT(VecIter<T>::iSize > 0); 215 ASSERT(VecIter<T>::pCount >= VecIter<T>::pStart - 1 && 216 VecIter<T>::pCount < VecIter<T>::pStart + VecIter<T>::iSize); 217 218 if (VecIter<T>::pCount == VecIter<T>::pStart + VecIter<T>::iSize) { 219 return false; 220 } 221 222 TReturn = *VecIter<T>::pCount; 223 /* NOTE: of course, by definition it's already in use */ 224 225 return true; 226 }; 227 bGetNext(T & TReturn)228 inline bool bGetNext(T& TReturn) const 229 { 230 ASSERT(VecIter<T>::pStart != NULL); 231 ASSERT(VecIter<T>::iSize > 0); 232 ASSERT(VecIter<T>::pCount >= VecIter<T>::pStart - 1 && 233 VecIter<T>::pCount < VecIter<T>::pStart + VecIter<T>::iSize); 234 235 for (VecIter<T>::pCount++; 236 VecIter<T>::pCount < VecIter<T>::pStart + VecIter<T>::iSize; 237 VecIter<T>::pCount++) { 238 if ((*VecIter<T>::pCount)->bIsInUse()) { 239 TReturn = *VecIter<T>::pCount; 240 #ifdef DEBUG_VECITER 241 iCount++; 242 #endif /* DEBUG_VECITER */ 243 return true; 244 } 245 } 246 247 #ifdef DEBUG_VECITER 248 silent_cerr("[" << pthread_self() << "]: total=" << iCount 249 << std::endl); 250 #endif /* DEBUG_VECITER */ 251 return false; 252 }; 253 }; 254 255 #endif /* USE_MULTITHREAD */ 256 257 #endif /* VECITER_H */ 258