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_SMARTPOINTERCONTAINER_H 00040 #define PLONK_SMARTPOINTERCONTAINER_H 00041 00042 #include "plonk_SmartPointer.h" 00043 #include "plonk_WeakPointer.h" 00044 00045 00046 #define PLONK_OBJECTARROWOPERATOR(Type) \ 00047 inline Type* operator->() throw() { return this; } \ 00048 inline const Type* operator->() const throw() { return this; } 00049 00050 00061 template<class SmartPointerType> 00062 class SmartPointerContainerBase : public PlonkBase 00063 { 00064 public: 00065 typedef AtomicValue<SmartPointerType*> AtomicPointer; 00066 00067 inline static SmartPointerType* getNullSmartPointer() throw() 00068 { 00069 return static_cast<SmartPointerType*> (0); 00070 } 00071 00072 inline SmartPointerContainerBase() throw() 00073 : internal (getNullSmartPointer()) 00074 { 00075 } 00076 00077 inline SmartPointerContainerBase (SmartPointerType* internalToUse) throw() 00078 : internal (getNullSmartPointer()) 00079 { 00080 if (internalToUse != getNullSmartPointer()) 00081 { 00082 internalToUse->incrementRefCount(); 00083 AtomicPointer temp (internalToUse); 00084 internal.swapWith (temp); 00085 } 00086 } 00087 00088 inline ~SmartPointerContainerBase() 00089 { 00090 AtomicPointer temp (getNullSmartPointer()); 00091 internal.swapWith (temp); 00092 00093 SmartPointerType* const tempPtr = temp.getPtrUnchecked(); // unchecked version is fine here 00094 00095 if (tempPtr != getNullSmartPointer()) 00096 tempPtr->decrementRefCount(); 00097 } 00098 00099 inline SmartPointerType* getInternal() const throw() 00100 { 00101 return internal.getPtr(); 00102 } 00103 00104 inline SmartPointerType* operator->() throw() 00105 { 00106 return internal.getPtr(); 00107 } 00108 00109 inline const SmartPointerType* operator->() const throw() 00110 { 00111 return internal.getPtr(); 00112 } 00113 00114 inline bool isNull() const throw() 00115 { 00116 return internal.getPtr() == getNullSmartPointer(); 00117 } 00118 00119 inline bool isNotNull() const throw() 00120 { 00121 return internal.getPtr() != getNullSmartPointer(); 00122 } 00123 00124 inline void setInternal (SmartPointerType* newInternal) throw() 00125 { 00126 SmartPointerContainerBase temp (newInternal); 00127 internal.swapWith (temp.internal); 00128 } 00129 00130 inline void swapWith (SmartPointerContainerBase& other) throw() 00131 { 00132 // is this a problem is other.internal is contended? 00133 internal.swapWith (other.internal); 00134 } 00135 00136 inline SmartPointerContainerBase (SmartPointerContainerBase const& copy) throw() 00137 : internal (getNullSmartPointer()) 00138 { 00139 SmartPointerType* copyPtr = copy.internal.getPtr(); 00140 00141 if (copyPtr != getNullSmartPointer()) 00142 { 00143 copyPtr->incrementRefCount(); 00144 AtomicPointer temp (copyPtr); 00145 internal.swapWith (temp); 00146 } 00147 } 00148 00149 inline SmartPointerContainerBase& operator= (SmartPointerContainerBase const& other) throw() 00150 { 00151 if (this != &other) 00152 this->setInternal (other.getInternal()); 00153 00154 return *this; 00155 } 00156 00157 inline bool operator== (SmartPointerContainerBase const& other) const throw() 00158 { 00159 return internal == other.internal; 00160 } 00161 00162 inline bool operator!= (SmartPointerContainerBase const& other) const throw() 00163 { 00164 return internal != other.internal; 00165 } 00166 00167 00168 private: 00169 AtomicPointer internal; 00170 }; 00171 00172 00173 template<class SmartPointerType, bool enableWeak> 00174 class SmartPointerContainer : public SmartPointerContainerBase<SmartPointerType> 00175 { 00176 public: 00177 inline SmartPointerContainer (SmartPointerType* internalToUse = 0) throw() 00178 : SmartPointerContainerBase<SmartPointerType> (internalToUse) 00179 { 00180 } 00181 00182 inline SmartPointerContainer (SmartPointerContainer const& copy) throw() 00183 : SmartPointerContainerBase<SmartPointerType> (copy) 00184 { 00185 } 00186 00187 inline SmartPointerContainer& operator= (SmartPointerContainer const& other) throw() 00188 { 00189 if (this != &other) 00190 this->setInternal (other.getInternal()); 00191 00192 return *this; 00193 } 00194 00195 }; 00196 00197 template<class SmartPointerType> 00198 class SmartPointerContainer<SmartPointerType, true> : public SmartPointerContainerBase<SmartPointerType> 00199 { 00200 public: 00201 typedef SmartPointerContainerBase<SmartPointerType> Base; 00202 00203 inline SmartPointerContainer (SmartPointerType* internalToUse = 0) throw() 00204 : SmartPointerContainerBase<SmartPointerType> (internalToUse) 00205 { 00206 } 00207 00208 inline SmartPointerContainer (SmartPointerContainer const& copy) throw() 00209 : SmartPointerContainerBase<SmartPointerType> (static_cast<Base const&> (copy)) 00210 { 00211 } 00212 00213 inline SmartPointerContainer& operator= (SmartPointerContainer const& other) throw() 00214 { 00215 if (this != &other) 00216 this->setInternal (other.getInternal()); 00217 00218 return *this; 00219 } 00220 00221 WeakPointer* getWeakPointer() const throw() 00222 { 00223 const SmartPointerType* const p = this->getInternal(); 00224 00225 if (p != Base::getNullSmartPointer()) 00226 { 00227 WeakPointer* w = static_cast<WeakPointer*> (p->getWeak()); 00228 return w; 00229 } 00230 00231 return 0; 00232 } 00233 00234 }; 00235 00236 00237 template<class SmartPointerContainerType> 00238 void swap (SmartPointerContainerType& a, 00239 SmartPointerContainerType& b) throw() 00240 { 00241 a.swapWith (b); 00242 } 00243 00244 template<class ScopedPointerType> 00245 class ScopedPointerContainer 00246 { 00247 public: 00248 typedef AtomicValue<ScopedPointerType*> AtomicPointer; 00249 00250 ScopedPointerContainer() throw() 00251 : internal (0) 00252 { 00253 } 00254 00255 ScopedPointerContainer (ScopedPointerType* const raw) throw() 00256 : internal (raw) 00257 { 00258 } 00259 00260 ~ScopedPointerContainer() 00261 { 00262 destroy (*this); 00263 } 00264 00265 inline ScopedPointerContainer (ScopedPointerContainer& copy) throw() 00266 : internal (0) 00267 { 00268 this->swapWith (copy); 00269 } 00270 00271 inline ScopedPointerContainer& operator= (ScopedPointerType* const raw) throw() 00272 { 00273 ScopedPointerContainer tmp (raw); 00274 this->swapWith (tmp); 00275 return *this; 00276 } 00277 00278 inline ScopedPointerContainer& operator= (ScopedPointerContainer& other) throw() 00279 { 00280 if (this != &other) 00281 { 00282 destroy (*this); 00283 this->swapWith (other); 00284 } 00285 00286 return *this; 00287 } 00288 00289 inline static void destroy (ScopedPointerContainer& container) throw() 00290 { 00291 AtomicPointer tmp (0); 00292 container.internal.swapWith (tmp); 00293 delete tmp.getPtrUnchecked(); // unchecked is fine here 00294 } 00295 00296 inline void swapWith (ScopedPointerContainer& other) throw() 00297 { 00298 // other might be contended 00299 internal.swapWith (other.internal); 00300 } 00301 00302 inline ScopedPointerType* getInternal() throw() 00303 { 00304 return internal.getPtr(); 00305 } 00306 00307 inline ScopedPointerType* operator->() throw() 00308 { 00309 plonk_assert(internal.getPtrUnchecked() != 0); 00310 return internal.getPtr(); 00311 } 00312 00313 inline const ScopedPointerType* operator->() const throw() 00314 { 00315 plonk_assert(internal.getPtrUnchecked() != 0); 00316 return internal.getPtr(); 00317 } 00318 00319 template<class OtherType> 00320 inline bool operator== (OtherType const& other) const throw() 00321 { 00322 return internal.getPtrUnchecked() == other; 00323 } 00324 00325 template<class OtherType> 00326 inline bool operator!= (OtherType const& other) const throw() 00327 { 00328 return internal.getPtrUnchecked() != other; 00329 } 00330 00331 private: 00332 AtomicPointer internal; 00333 }; 00334 00335 //------------------------------------------------------------------------------ 00336 00337 #define PLONKSMARTPOINTERCONTAINER_DEEPCOPY(CONTAINERTYPE,SMARTPOINTERTYPE)\ 00338 inline CONTAINERTYPE deepCopy() const throw()\ 00339 {\ 00340 SMARTPOINTERTYPE* const theCopy = static_cast<SMARTPOINTERTYPE*> (this->getInternal()->deepCopy());\ 00341 plonk_assert (theCopy != 0);\ 00342 return CONTAINERTYPE (theCopy);\ 00343 } 00344 00345 //------------------------------------------------------------------------------ 00346 00347 00348 template<class PlankSharedPtrType> class PlankWeakPtrContainer; 00349 00350 template<class PlankSharedPtrType> 00351 class PlankSharedPtrContainer : public PlonkBase 00352 { 00353 public: 00354 typedef PlankSharedPtrType Internal; 00355 typedef AtomicValue<Internal> AtomicPointer; 00356 typedef PlankWeakPtrContainer<Internal> Weak; 00357 00358 inline static Internal getNullSharedPtr() throw() 00359 { 00360 return static_cast<Internal> (0); 00361 } 00362 00363 inline static PlankSharedPtrContainer getNull() throw() 00364 { 00365 static PlankSharedPtrContainer null (getNullSharedPtr()); 00366 return null; 00367 } 00368 00369 PlankSharedPtrContainer (Internal p) throw() 00370 : internal (p ? reinterpret_cast<Internal> (pl_SharefPtr_IncrementRefCountAndGetPtr (reinterpret_cast<PlankSharedPtrRef> (p))) : getNullSharedPtr()) 00371 { 00372 } 00373 00374 PlankSharedPtrContainer (Weak const& weak) throw() 00375 : internal () 00376 { 00377 } 00378 00379 inline PlankSharedPtrContainer (PlankSharedPtrContainer const& copy) throw() 00380 : internal (getNullSharedPtr()) 00381 { 00382 Internal const copyPtr = copy.internal.getPtr(); 00383 00384 if (copyPtr != getNullSharedPtr()) 00385 { 00386 AtomicPointer temp (reinterpret_cast<Internal> (pl_SharefPtr_IncrementRefCountAndGetPtr (reinterpret_cast<PlankSharedPtrRef> (copyPtr)))); 00387 internal.swapWith (temp); 00388 } 00389 } 00390 00391 ~PlankSharedPtrContainer() 00392 { 00393 AtomicPointer temp (getNullSharedPtr()); 00394 internal.swapWith (temp); 00395 00396 Internal const tempPtr = temp.getPtrUnchecked(); // unchecked version is fine here 00397 00398 if (tempPtr != getNullSharedPtr()) 00399 pl_SharedPtr_DecrementRefCount (reinterpret_cast<PlankSharedPtrRef> (tempPtr)); 00400 } 00401 00402 inline PlankSharedPtrContainer& operator= (PlankSharedPtrContainer const& other) throw() 00403 { 00404 if (this != &other) 00405 this->setInternal (other.getInternal()); 00406 00407 return *this; 00408 } 00409 00410 inline void setInternal (Internal newInternal) throw() 00411 { 00412 PlankSharedPtrContainer temp (newInternal); 00413 internal.swapWith (temp.internal); 00414 } 00415 00416 inline void swapWith (PlankSharedPtrContainer& other) throw() 00417 { 00418 internal.swapWith (other.internal); 00419 } 00420 00421 inline Internal getInternal() throw() 00422 { 00423 return internal.getPtr(); 00424 } 00425 00426 inline Internal getInternal() const throw() 00427 { 00428 return internal.getPtr(); 00429 } 00430 00431 inline Internal operator->() throw() 00432 { 00433 return internal.getPtr(); 00434 } 00435 00436 inline const Internal operator->() const throw() 00437 { 00438 return internal.getPtr(); 00439 } 00440 00441 inline bool isNull() const throw() 00442 { 00443 return internal.getPtr() == getNullSharedPtr(); 00444 } 00445 00446 inline bool isNotNull() const throw() 00447 { 00448 return internal.getPtr() != getNullSharedPtr(); 00449 } 00450 00451 Weak getWeak() throw() 00452 { 00453 return Weak (pl_SharedPtr_GetWeakPtr (reinterpret_cast<PlankSharedPtrRef> (internal.getPtr()))); 00454 } 00455 00456 protected: 00458 template<typename InitFunction> 00459 inline void initInternalWithFunction (InitFunction initFunction) throw() 00460 { 00461 plonk_assert (internal.getPtrUnchecked() == PlankSharedPtrContainer::getNullSharedPtr()); 00462 Internal newInternal; 00463 initFunction (&newInternal); 00464 internal.getAtomicRef()->ptr = newInternal; 00465 } 00466 00467 template<typename InitFunction, typename ArgType> 00468 inline void initInternalWithFunction (InitFunction initFunction, ArgType arg) throw() 00469 { 00470 plonk_assert (internal.getPtrUnchecked() == PlankSharedPtrContainer::getNullSharedPtr()); 00471 Internal newInternal; 00472 initFunction (&newInternal, arg); 00473 internal.getAtomicRef()->ptr = newInternal; 00474 } 00475 00476 00477 private: 00478 AtomicPointer internal; 00479 }; 00480 00481 //------------------------------------------------------------------------------ 00482 00483 template<class PlankSharedPtrType> 00484 class PlankWeakPtrContainer : public PlankSharedPtrContainer<PlankWeakPtrRef> 00485 { 00486 public: 00487 typedef PlankSharedPtrContainer<PlankWeakPtrRef> Base; 00488 typedef PlankSharedPtrContainer<PlankSharedPtrType> OriginalType; 00489 00490 PlankWeakPtrContainer() throw() 00491 : Base (Base::getNullSharedPtr()) 00492 { 00493 } 00494 00495 PlankWeakPtrContainer (PlankWeakPtrRef p) throw() 00496 : Base (p) 00497 { 00498 if (p) 00499 { 00500 pl_WeakPtr_DecrementRefCount (p); 00501 } 00502 } 00503 00504 PlankWeakPtrContainer (PlankWeakPtrContainer const& copy) throw() 00505 : Base (static_cast<Base const&> (copy)) 00506 { 00507 } 00508 00509 PlankWeakPtrContainer& operator= (PlankWeakPtrContainer const& other) throw() 00510 { 00511 if (this != &other) 00512 this->setInternal (other.getInternal()); 00513 00514 return *this; 00515 } 00516 00517 OriginalType fromWeak() const throw() 00518 { 00519 PlankSharedPtrType sharedPtr = reinterpret_cast<PlankSharedPtrType> (pl_WeakPtr_GetSharedPtr (this->getInternal())); 00520 OriginalType result (sharedPtr); 00521 pl_SharedPtr_DecrementRefCount (reinterpret_cast<PlankSharedPtrRef> (sharedPtr)); 00522 return result; 00523 } 00524 00525 }; 00526 00527 //------------------------------------------------------------------------------ 00528 00529 template<class PlankSharePtrContainterType> 00530 class PlankSharedPtrArrayContainer : public PlankSharedPtrContainer<PlankSharedPtrArrayRef> 00531 { 00532 public: 00533 typedef PlankSharedPtrContainer<PlankSharedPtrArrayRef> Base; 00534 typedef PlankSharePtrContainterType ElementType; 00535 typedef typename ElementType::Internal ElementInternalType; 00536 typedef Base::Weak Weak; 00537 00538 PlankSharedPtrArrayContainer() throw() 00539 : Base (Base::getNullSharedPtr()) 00540 { 00541 initInternalWithFunction (pl_SharedPtrArray_CreateSharedPtr, 0); 00542 } 00543 00544 PlankSharedPtrArrayContainer (FourCharCode const& elementType) throw() 00545 : Base (Base::getNullSharedPtr()) 00546 { 00547 initInternalWithFunction (pl_SharedPtrArray_CreateSharedPtr, elementType); 00548 } 00549 00550 PlankSharedPtrArrayContainer (PlankSharedPtrArrayRef p) throw() 00551 : Base (p) 00552 { 00553 } 00554 00555 PlankSharedPtrArrayContainer (PlankSharedPtrArrayContainer const& copy) throw() 00556 : Base (static_cast<Base const&> (copy)) 00557 { 00558 } 00559 00560 PlankSharedPtrArrayContainer (Base const& base) throw() 00561 : Base (base) 00562 { 00563 } 00564 00565 PlankSharedPtrArrayContainer (Weak const& weak) throw() 00566 : Base (weak.fromWeak()) 00567 { 00568 } 00569 00570 PlankSharedPtrArrayContainer& operator= (PlankSharedPtrArrayContainer const& other) throw() 00571 { 00572 if (this != &other) 00573 this->setInternal (other.getInternal()); 00574 00575 return *this; 00576 } 00577 00578 void clear() throw() 00579 { 00580 Internal const internal = this->getInternal(); 00581 00582 if (internal != ElementType::getNullSharedPtr()) 00583 pl_SharedPtrArray_Clear (internal); 00584 } 00585 00586 Long length() const throw() 00587 { 00588 Internal const internal = this->getInternal(); 00589 return internal ? pl_SharedPtrArray_GetLength (internal) : 0; 00590 } 00591 00592 inline ElementType operator[] (const Long index) const throw() 00593 { 00594 Internal const internal = this->getInternal(); 00595 plonk_assert (internal != Base::getNullSharedPtr()); 00596 return internal ? ElementType (reinterpret_cast<ElementInternalType> (pl_SharedPtrArray_GetSharedPtr (internal, index))) : ElementType::getNull(); 00597 } 00598 00599 inline ElementType at (const Long index) const throw() 00600 { 00601 return at (index); 00602 } 00603 00604 inline ElementType wrapAt (const Long index) const throw() 00605 { 00606 Internal const internal = this->getInternal(); 00607 00608 if (internal == Base::getNullSharedPtr()) 00609 return ElementType::getNull(); 00610 else plonk_assertfalse; 00611 00612 UnsignedLong length = (unsigned long)this->length(); 00613 00614 if (length == 0) 00615 return ElementType::getNull(); 00616 00617 int indexToUse = index; 00618 while (indexToUse < 0) 00619 indexToUse += length; 00620 00621 return ElementType (reinterpret_cast<ElementInternalType> (pl_SharedPtrArray_GetSharedPtr (internal, 00622 (unsigned long)indexToUse % length))); 00623 00624 return this->getArray()[(unsigned long)indexToUse % (unsigned long)this->length()]; 00625 } 00626 00627 PlankSharedPtrArrayContainer& add (ElementType const& item) throw() 00628 { 00629 Internal const internal = this->getInternal(); 00630 00631 if (internal != Base::getNullSharedPtr()) 00632 pl_SharedPtrArray_AddSharedPtr (internal, reinterpret_cast<PlankSharedPtrRef> (item.getInternal())); 00633 else plonk_assertfalse; 00634 00635 return *this; 00636 } 00637 00638 PlankSharedPtrArrayContainer& remove (const Long index) throw() 00639 { 00640 Internal const internal = this->getInternal(); 00641 00642 if (internal != Base::getNullSharedPtr()) 00643 pl_SharedPtrArray_RemoveSharedPtr (internal, index); 00644 else plonk_assertfalse; 00645 00646 return *this; 00647 } 00648 00649 PlankSharedPtrArrayContainer& put (const Long index, ElementType const& item) throw() 00650 { 00651 Internal const internal = this->getInternal(); 00652 00653 if (internal != Base::getNullSharedPtr()) 00654 pl_SharedPtrArray_PutSharedPtr (internal, index, static_cast<PlankSharedPtrRef> (item.getInternal())); 00655 else plonk_assertfalse; 00656 00657 return *this; 00658 } 00659 00660 }; 00661 00662 00663 #define PLANKSHAREDPTRCONTAINER_DEFINE(NAME)\ 00664 NAME NAME::getNull() throw() { static NAME null (Base::getNullSharedPtr()); return null; }\ 00665 NAME::NAME() throw() : Base (Base::getNullSharedPtr()) { initInternalWithFunction (pl_##NAME##_CreateSharedPtr); }\ 00666 NAME::NAME (Plank##NAME##Ref p) throw() : Base (p) { }\ 00667 NAME::NAME (NAME const& copy) throw() : Base (static_cast<PlankSharedPtrContainer<Plank##NAME##Ref> const&> (copy)) { }\ 00668 NAME::NAME (Base const& base) throw() : Base (base) { }\ 00669 NAME::NAME (Weak const& weak) throw() : Base (weak.fromWeak()) { }\ 00670 NAME& NAME::operator= (NAME const &other) throw() { if (this != &other) this->setInternal (other.getInternal()); return *this; }\ 00671 Plank##NAME##Ref NAME::incrementRefCountAndGetPeer() throw() { return pl_##NAME##_IncrementRefCountAndGet (this->getInternal()); } 00672 00673 00674 #endif // PLONK_SMARTPOINTERCONTAINER_H