![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
00001 /* 00002 ------------------------------------------------------------------------------- 00003 This file is part of the Plink, Plonk, Plank libraries 00004 by Martin Robinson 00005 00006 http://code.google.com/p/pl-nk/ 00007 00008 Copyright University of the West of England, Bristol 2011-14 00009 All rights reserved. 00010 00011 Redistribution and use in source and binary forms, with or without 00012 modification, are permitted provided that the following conditions are met: 00013 00014 * Redistributions of source code must retain the above copyright 00015 notice, this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright 00017 notice, this list of conditions and the following disclaimer in the 00018 documentation and/or other materials provided with the distribution. 00019 * Neither the name of University of the West of England, Bristol nor 00020 the names of its contributors may be used to endorse or promote products 00021 derived from this software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00026 DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 This software makes use of third party libraries. For more information see: 00035 doc/license.txt included in the distribution. 00036 ------------------------------------------------------------------------------- 00037 */ 00038 00039 #ifndef PLONK_LOCKFREESTACK_H 00040 #define PLONK_LOCKFREESTACK_H 00041 00042 #include "../core/plonk_CoreForwardDeclarations.h" 00043 #include "plonk_ContainerForwardDeclarations.h" 00044 00045 #include "../core/plonk_SmartPointer.h" 00046 #include "../core/plonk_WeakPointer.h" 00047 00048 template<class ValueType> 00049 class LockFreeStackInternal : public SmartPointer 00050 { 00051 public: 00052 typedef LockFreeStack<ValueType> StackType; 00053 00054 LockFreeStackInternal() throw() 00055 { 00056 initStack (liveStack); 00057 initStack (deadStack); 00058 } 00059 00060 ~LockFreeStackInternal() 00061 { 00062 deInitStack (liveStack); 00063 deInitStack (deadStack); 00064 } 00065 00066 inline void push (ValueType const& value) throw() 00067 { 00068 PlankLockFreeStackElementRef element = createElement (value); 00069 ResultCode result = pl_LockFreeStack_Push (&liveStack, element); 00070 plonk_assert (result == PlankResult_OK); 00071 #ifndef PLONK_DEBUG 00072 (void)result; 00073 #endif 00074 } 00075 00076 inline ValueType pop() throw() 00077 { 00078 ValueType value; 00079 ValueType* valuePtr = popInternal (&value); 00080 return (valuePtr == 0) ? getNullValue() : value; 00081 } 00082 00083 void clear() throw() 00084 { 00085 ValueType* valuePtr; 00086 do 00087 { 00088 valuePtr = popInternal (0); 00089 } while (valuePtr != 0); 00090 } 00091 00092 void clearCache() throw() 00093 { 00094 ResultCode result = pl_LockFreeStack_Clear (&deadStack); 00095 plonk_assert (result == PlankResult_OK); 00096 #ifndef PLONK_DEBUG 00097 (void)result; 00098 #endif 00099 } 00100 00101 void clearAll() throw() 00102 { 00103 ResultCode result = pl_LockFreeStack_Clear (&liveStack); 00104 plonk_assert (result == PlankResult_OK); 00105 00106 clearCache(); 00107 00108 #ifndef PLONK_DEBUG 00109 (void)result; 00110 #endif 00111 } 00112 00113 inline LongLong length() throw() 00114 { 00115 return pl_LockFreeStack_GetSize (&liveStack); 00116 } 00117 00118 friend class LockFreeStack<ValueType>; 00119 00120 private: 00121 PLONK_ALIGN(16) PlankLockFreeStack liveStack; 00122 PLONK_ALIGN(16) PlankLockFreeStack deadStack; 00123 00124 static void initStack (PlankLockFreeStack& stack) throw() 00125 { 00126 pl_LockFreeStack_Init (&stack); 00127 pl_LockFreeStack_SetFreeElementDataFunction (&stack, LockFreeStackInternal::freeElement); 00128 } 00129 00130 static void deInitStack (PlankLockFreeStack& stack) throw() 00131 { 00132 ResultCode result; 00133 00134 result = pl_LockFreeStack_Clear (&stack); 00135 plonk_assert (result == PlankResult_OK); 00136 00137 result = pl_LockFreeStack_DeInit (&stack); 00138 plonk_assert (result == PlankResult_OK); 00139 00140 #ifndef PLONK_DEBUG 00141 (void)result; 00142 #endif 00143 } 00144 00145 inline PlankLockFreeStackElementRef createElement (ValueType const& value) throw() 00146 { 00147 PlankLockFreeStackElementRef element; 00148 ResultCode result = pl_LockFreeStack_Pop (&deadStack, &element); 00149 plonk_assert (result == PlankResult_OK); 00150 00151 if (element != 0) 00152 { 00153 ValueType* const data = static_cast<ValueType*> (pl_LockFreeStackElement_GetData (element)); 00154 plonk_assert (data != 0); 00155 *data = value; 00156 } 00157 else 00158 { 00159 element = pl_LockFreeStackElement_CreateAndInit(); 00160 plonk_assert (element != 0); 00161 pl_LockFreeStackElement_SetData (element, new ValueType (value)); 00162 } 00163 00164 #ifndef PLONK_DEBUG 00165 (void)result; 00166 #endif 00167 00168 return element; 00169 } 00170 00171 static ResultCode freeElement (Pointer data) 00172 { 00173 delete static_cast<ValueType*> (data); 00174 return PlankResult_OK; 00175 } 00176 00177 static inline ValueType getNullValue() throw() 00178 { 00179 static ValueType null = ValueType(); 00180 return null; 00181 } 00182 00183 ValueType* popInternal (ValueType* value) throw() 00184 { 00185 ValueType* valuePtr = 0; 00186 00187 PlankLockFreeStackElementRef element; 00188 ResultCode result = pl_LockFreeStack_Pop (&liveStack, &element); 00189 plonk_assert (result == PlankResult_OK); 00190 00191 if (element != 0) 00192 { 00193 valuePtr = static_cast <ValueType*> (pl_LockFreeStackElement_GetData (element)); 00194 plonk_assert (valuePtr != 0); 00195 00196 if (value != 0) 00197 *value = *valuePtr; 00198 00199 *valuePtr = getNullValue(); 00200 00201 result = pl_LockFreeStack_Push (&deadStack, element); 00202 plonk_assert (result == PlankResult_OK); 00203 } 00204 00205 #ifndef PLONK_DEBUG 00206 (void)result; 00207 #endif 00208 00209 return valuePtr; 00210 } 00211 00212 }; 00213 00214 00215 template<class ValueType> 00216 class LockFreeStackInternal<ValueType*> : public SmartPointer 00217 { 00218 public: 00219 typedef LockFreeStack<ValueType*> StackType; 00220 00221 LockFreeStackInternal() throw() 00222 { 00223 pl_LockFreeStack_Init (&stack); 00224 } 00225 00226 ~LockFreeStackInternal() 00227 { 00228 pl_LockFreeStack_DeInit (&stack); 00229 } 00230 00231 void push (ValueType* const value) throw() 00232 { 00233 PlankLockFreeStackElementRef element = pl_LockFreeStackElement_CreateAndInit(); 00234 plonk_assert (element != 0); 00235 pl_LockFreeStackElement_SetData (element, value); 00236 ResultCode result = pl_LockFreeStack_Push (&stack, element); 00237 plonk_assert (result == PlankResult_OK); 00238 #ifndef PLONK_DEBUG 00239 (void)result; 00240 #endif 00241 } 00242 00243 ValueType* pop() throw() 00244 { 00245 ValueType* returnValue; 00246 00247 PlankLockFreeStackElementRef element; 00248 ResultCode result = pl_LockFreeStack_Pop (&stack, &element); 00249 plonk_assert (result == PlankResult_OK); 00250 00251 if (element != 0) 00252 { 00253 returnValue = static_cast <ValueType*> (pl_LockFreeStackElement_GetData (element)); 00254 result = pl_LockFreeStackElement_Destroy (element); 00255 plonk_assert (result == PlankResult_OK); 00256 } 00257 00258 #ifndef PLONK_DEBUG 00259 (void)result; 00260 #endif 00261 00262 return returnValue; 00263 } 00264 00265 void clear() throw() 00266 { 00267 ResultCode result = pl_LockFreeStack_Clear (&stack); 00268 plonk_assert (result == PlankResult_OK); 00269 #ifndef PLONK_DEBUG 00270 (void)result; 00271 #endif 00272 } 00273 00274 void clearCache() throw() 00275 { 00276 // not applicable 00277 } 00278 00279 void clearAll() throw() 00280 { 00281 clear(); 00282 } 00283 00284 LongLong length() throw() 00285 { 00286 return pl_LockFreeStack_GetSize (&stack); 00287 } 00288 00289 friend class LockFreeStack<ValueType*>; 00290 00291 private: 00292 PLONK_ALIGN(16) PlankLockFreeStack stack; 00293 }; 00294 00295 00296 00297 //------------------------------------------------------------------------------ 00298 00300 template<class ValueType> 00301 class LockFreeStack : public SmartPointerContainer<LockFreeStackInternal<ValueType> > 00302 { 00303 public: 00304 typedef LockFreeStackInternal<ValueType> Internal; 00305 typedef SmartPointerContainer<Internal> Base; 00306 typedef WeakPointerContainer<LockFreeStack> Weak; 00307 00308 inline LockFreeStack() 00309 : Base (new Internal()) 00310 { 00311 } 00312 00313 inline explicit LockFreeStack (Internal* internalToUse) throw() 00314 : Base (internalToUse) 00315 { 00316 } 00317 00321 static LockFreeStack fromWeak (Weak const& weak) throw() 00322 { 00323 return weak.fromWeak(); 00324 } 00325 00327 inline LockFreeStack (LockFreeStack const& copy) throw() 00328 : Base (static_cast<Base const&> (copy)) 00329 { 00330 } 00331 00332 inline LockFreeStack (Dynamic const& other) throw() 00333 : Base (other.as<LockFreeStack>().getInternal()) 00334 { 00335 } 00336 00338 inline LockFreeStack& operator= (LockFreeStack const& other) throw() 00339 { 00340 if (this != &other) 00341 this->setInternal (other.getInternal()); 00342 00343 return *this; 00344 } 00345 00346 inline void push (ValueType const& value) throw() 00347 { 00348 this->getInternal()->push (value); 00349 } 00350 00351 inline ValueType pop() throw() 00352 { 00353 return this->getInternal()->pop(); 00354 } 00355 00356 inline void clear() throw() 00357 { 00358 return this->getInternal()->clear(); 00359 } 00360 00361 inline void clearCache() throw() 00362 { 00363 return this->getInternal()->clearCache(); 00364 } 00365 00366 inline void clearAll() throw() 00367 { 00368 return this->getInternal()->clearAll(); 00369 } 00370 00371 inline LongLong length() throw() 00372 { 00373 return this->getInternal()->length(); 00374 } 00375 00376 PLONK_OBJECTARROWOPERATOR(LockFreeStack); 00377 }; 00378 00379 00380 #endif // PLONK_LOCKFREESTACK_H