pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_Collections.h
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_COLLECTIONS_H
00040 #define PLONK_COLLECTIONS_H
00041 
00042 #include "../core/plonk_CoreForwardDeclarations.h"
00043 #include "plonk_ContainerForwardDeclarations.h"
00044 #include "plonk_DynamicContainer.h"
00045 
00046 #include "../core/plonk_SmartPointer.h"
00047 #include "../core/plonk_WeakPointer.h"
00048 #include "../core/plonk_Thread.h"
00049 #include "plonk_ObjectArray.h"
00050 #include "plonk_SimpleArray.h"
00051 
00052 
00053 template<class ValueType, class KeyType>
00054 class DictionaryInternal : public SmartPointer
00055 {
00056 public:
00057     typedef Dictionary<ValueType,KeyType> Container;
00058     
00059         DictionaryInternal() throw()
00060         {
00061         }
00062         
00063     DictionaryInternal (const int initialCapacity) throw()
00064     :   values (ObjectArray<ValueType>::emptyWithAllocatedSize (initialCapacity)),
00065         keys (ObjectArray<KeyType>::emptyWithAllocatedSize (initialCapacity))
00066         {
00067         }
00068     
00069         ~DictionaryInternal()
00070         {
00071         }
00072         
00073         ObjectArray<ValueType>& getValues() throw()
00074         {
00075                 return values;
00076         }
00077         
00078         ObjectArray<KeyType>& getKeys() throw()
00079         {
00080                 return keys;
00081         }
00082         
00083         const ObjectArray<ValueType>& getValues() const throw()
00084         {
00085                 return values;
00086         }
00087         
00088         const ObjectArray<KeyType>& getKeys() const throw()
00089         {
00090                 return keys;
00091         }
00092         
00093 private:
00094         ObjectArray<ValueType> values;
00095         ObjectArray<KeyType> keys;
00096 };
00097 
00098 
00099 //------------------------------------------------------------------------------
00100 
00102 template<class ValueType, class KeyType>
00103 class KeyValuePair
00104 {
00105 public:
00106         KeyValuePair() throw()
00107         {
00108         }
00109         
00110         KeyValuePair (KeyType const& key, ValueType const& value) throw()
00111         :       v (value), 
00112         k (key)
00113         {
00114         }
00115     
00116     KeyValuePair (KeyValuePair const& copy) throw()
00117     :   v (copy.v),
00118         k (copy.k)
00119     {
00120     }
00121     
00122     KeyValuePair operator= (KeyValuePair const& other) throw()
00123     {
00124         if (this != &other)
00125         {
00126             v = other.v;
00127             k = other.k;
00128         }
00129         
00130         return *this;
00131     }
00132         
00133         const KeyType& getKey() const throw() { return k; }
00134         const ValueType& getValue() const throw() { return v; }
00135         
00136 private:
00137         ValueType v;
00138         KeyType k;
00139 };
00140 
00141 
00142 //------------------------------------------------------------------------------
00143 
00144 
00150 template<class ValueType, class KeyType>
00151 class Dictionary : public SmartPointerContainer< DictionaryInternal<ValueType,KeyType> >
00152 {
00153 public:
00154         typedef KeyValuePair<ValueType,KeyType>         KeyValuePairType;
00155         typedef ObjectArray<KeyValuePairType>           KeyValuePairArrayType;
00156 
00157     typedef DictionaryInternal<ValueType,KeyType>   Internal;
00158     typedef SmartPointerContainer<Internal>         Base;
00159     typedef WeakPointerContainer<Dictionary>        Weak;    
00160     
00162         Dictionary() throw()
00163         :       Base (new Internal())
00164         {
00165         }
00166         
00167     explicit Dictionary (const int initialCapacity) throw()
00168         :       Base (new Internal (initialCapacity))
00169         {
00170         }
00171     
00172     explicit Dictionary (Internal* internalToUse) throw() 
00173         :       Base (internalToUse)
00174         {
00175         } 
00176     
00177     Dictionary (Dictionary const& copy) throw()
00178         :       Base (static_cast<Base const&> (copy))
00179         {
00180         }        
00181     
00182     Dictionary (Dynamic const& other) throw()
00183     :   Base (other.as<Dictionary>().getInternal())
00184     {
00185     }    
00186     
00188     Dictionary& operator= (Dictionary const& other) throw()
00189         {
00190                 if (this != &other)
00191             this->setInternal (other.getInternal());//this->setInternal (other.containerCopy().getInternal());
00192         
00193         return *this;
00194         }
00195     
00199     static Dictionary fromWeak (Weak const& weak) throw()
00200     {
00201         return weak.fromWeak();
00202     }    
00203 
00204     static const Dictionary& getNull() throw()
00205         {
00206                 static Dictionary null;
00207                 return null;
00208         }                                       
00209     
00211         Dictionary (KeyValuePairArrayType const& pairs) throw()
00212         :       Base (new Internal())
00213         {
00214                 put (pairs);
00215         }
00216     
00218         const ObjectArray<ValueType>& getValues() const throw()
00219         { 
00220                 return this->getInternal()->getValues(); 
00221         }
00222         
00224         const ObjectArray<KeyType>& getKeys() const throw()
00225         {
00226                 return this->getInternal()->getKeys(); 
00227         }
00228 
00230         KeyValuePairArrayType getPairs() const throw()
00231         {
00232                 KeyValuePairArrayType pairs = KeyValuePairArrayType::withSize (length());
00233                 
00234                 for (int i = 0; i < length(); ++i)
00235                         pairs[i] = KeyValuePairType (key (i), value (i));
00236                 
00237                 return pairs;
00238         }
00239         
00244         ValueType put (KeyType const& key, ValueType const& value) throw()
00245         {
00246                 ObjectArray<ValueType>& values = this->getInternal()->getValues();
00247                 ObjectArray<KeyType>& keys = this->getInternal()->getKeys();
00248 
00249                 int index = keys.indexOf (key);
00250                 
00251                 if (index >= 0)
00252                 {
00253                         ValueType oldValue = values[index];
00254                         values.put (index, value);
00255                         return oldValue;
00256                 }
00257                 else
00258                 {
00259                         keys.add (key);
00260                         values.add (value);
00261                         return ObjectArray<ValueType>::getNullObject();
00262                 }
00263         }
00264         
00265         ValueType put (KeyValuePairType const& pair) throw()
00266         {
00267                 return put (pair.getKey(), pair.getValue());
00268         }
00269         
00270         void put (KeyValuePairArrayType const& pairs) throw()
00271         {
00272                 for (int i = 0; i < pairs.length(); ++i)
00273                         put (pairs[i]);
00274         }
00275         
00276     bool containsKey (KeyType const& key) throw()
00277         {
00278                 return this->getInternal()->getKeys().contains (key);
00279         }
00280 
00281     bool containsValue (ValueType const& value) throw()
00282         {
00283                 return this->getInternal()->getValues().contains (value);
00284         }
00285     
00288         ValueType& at (KeyType const& key) throw()
00289         {
00290                 ObjectArray<ValueType>& values = this->getInternal()->getValues();
00291                 ObjectArray<KeyType>& keys = this->getInternal()->getKeys();
00292                 
00293                 const int index = keys.indexOf (key);
00294                 return values[index];
00295         }
00296         
00299         const ValueType& at (KeyType const& key) const throw()
00300         {
00301                 ObjectArray<ValueType> const& values = getValues();
00302                 ObjectArray<KeyType> const& keys = getKeys();
00303                 
00304                 const int index = keys.indexOf (key);
00305                 return values[index];
00306         }
00307         
00308     ValueType& atIndex (const int index) throw()
00309         {
00310                 ObjectArray<ValueType>& values = this->getInternal()->getValues();              
00311                 return values[index];
00312         }    
00313     
00314     const ValueType& atIndex (const int index) const throw()
00315         {
00316                 ObjectArray<ValueType> const& values = getValues();             
00317                 return values[index];
00318         }
00319     
00320     ValueType& atIndexUnchecked (const int index) throw()
00321         {
00322                 ObjectArray<ValueType>& values = this->getInternal()->getValues();              
00323                 return values.atUnchecked (index);
00324         }    
00325     
00326     const ValueType& atIndexUnchecked (const int index) const throw()
00327         {
00328                 ObjectArray<ValueType> const& values = getValues();             
00329                 return values.atUnchecked (index);
00330         }
00331     
00334         ValueType& operator[] (KeyType const& key) throw()
00335         {
00336                 ObjectArray<ValueType>& values = this->getInternal()->getValues();
00337                 ObjectArray<KeyType>& keys = this->getInternal()->getKeys();
00338                 
00339                 const int index = keys.indexOf (key);
00340                 return values[index];
00341         }
00342         
00345         const ValueType& operator[] (KeyType const& key) const throw()
00346         {
00347                 ObjectArray<ValueType> const& values = getValues();
00348                 ObjectArray<KeyType> const& keys = getKeys();
00349                 
00350                 const int index = keys.indexOf (key);
00351                 return values[index];
00352         }
00353         
00356         ValueType remove (KeyType const& key) throw()
00357         {
00358                 ObjectArray<ValueType>& values = this->getInternal()->getValues();
00359                 ObjectArray<KeyType>& keys = this->getInternal()->getKeys();
00360                 
00361                 const int index = keys.indexOf (key);
00362                 
00363                 if (index >= 0)
00364                 {
00365                         ValueType removed = values[index];
00366                         keys.remove (index);
00367                         values.remove (index);
00368                         return removed;
00369                 }
00370                 else
00371                 {
00372                         return ObjectArray<ValueType>::getNullObject();
00373                 }
00374         }
00375 
00377         const KeyType& keyForValue (ValueType const& value) const
00378         {
00379                 ObjectArray<ValueType> const& values = getValues();
00380                 ObjectArray<KeyType> const& keys = getKeys();
00381                 
00382                 const int index = values.indexOf (value);
00383                 return keys[index];
00384         }
00385         
00387         KeyType& key (const int index) throw()
00388         {
00389                 return getKeys()[index];
00390         }
00391         
00393         ValueType& value (const int index) throw()
00394         {
00395                 return getValues()[index];
00396         }
00397         
00399         const KeyType& key (const int index) const throw()
00400         {
00401                 return getKeys()[index];
00402         }
00403         
00405         const ValueType& value (const int index) const throw()
00406         {
00407                 return getValues()[index];
00408         }
00409         
00411         int length() const throw()
00412         {
00413                 ObjectArray<ValueType> const& values = getValues();
00414                 
00415                 plonk_assert (values.length() == getKeys().length()); // these should be the same length!
00416                 
00417                 return values.length();
00418         }
00419         
00421         int size() const throw()
00422         {
00423                 ObjectArray<ValueType> const& values = getValues();
00424                 ObjectArray<KeyType> const& keys = getKeys();
00425                 
00426                 plonk_assert (values.size() == keys.size()); // these should be the same size!
00427                 
00428                 return values.size();
00429         }
00430     
00431     PLONK_OBJECTARROWOPERATOR(Dictionary);
00432 
00433 };
00434 
00436 
00438 // The SmartPointerContainer and ScopedPointerContainer are thread-safe in terms
00439 // of copying the object but not actions on the object. This class holds another
00440 // container object and ensures thread-safe manipulations on the object. 
00441 // The container must respond to the -> operator and implement copy() which
00442 // should return a deep object of the object. */
00443 //
00444 //template<class Container>
00445 //class ThreadSafeAccess
00446 //{
00447 //public:
00448 //    typedef typename Container::Internal ContainerInternal;
00449 //
00450 //    ThreadSafeAccess() throw()
00451 //    {
00452 //    }
00453 //    
00454 //    ~ThreadSafeAccess()
00455 //    {
00456 //    }
00457 //    
00458 //    explicit ThreadSafeAccess (Container const& initialValue) throw()
00459 //    :   read (initialValue.copy()), 
00460 //        write (initialValue.copy())
00461 //    {        
00462 //    }
00463 //    
00464 //    const Container& getRead() throw() 
00465 //    { 
00466 //        return read;
00467 //    }
00468 //    
00469 //    bool checkout() throw()
00470 //    {
00471 //        const Threading::ID threadID = Threading::getCurrentThreadID();
00472 //        
00473 //        if (writingThread.compareAndSwap (0, threadID))
00474 //        {
00475 //            write = read.copy();
00476 //            return true;
00477 //        }
00478 //        
00479 //        return false;
00480 //    }
00481 //        
00482 //    bool commit() throw()
00483 //    {
00484 //        const Threading::ID threadID = Threading::getCurrentThreadID();
00485 //
00486 //        if (writingThread == threadID)
00487 //        {
00488 //            read.swapWith (write);
00489 //            writingThread = 0;
00490 //            return true;
00491 //        }
00492 //        
00493 //        return false;
00494 //    }
00495 //    
00496 //    Container operator->() throw() 
00497 //    {   
00498 //        plonk_assert (writingThread == Threading::getCurrentThreadID());
00499 //        return write;
00500 //    }
00501 //    
00502 //    const Container& operator*() const throw() 
00503 //    {   
00504 //        return read;
00505 //    }
00506 //
00507 //
00508 //    
00509 //private:
00510 //    Container read;
00511 //    Container write;
00512 //    AtomicValue<Threading::ID> writingThread;
00513 //};
00514 
00515 //template<class Container, int NumThreads>
00516 //class ThreadSafeAccess
00517 //{
00518 //public:
00519 //    typedef typename Container::Internal ContainerInternal;
00520 //    typedef ObjectArray<Container> Containers;
00521 //    typedef AtomicValue<Threading::ID> AtomicThreadID;
00522 //    typedef ObjectArray<AtomicThreadID> Threads;
00523 //    
00524 //    ThreadSafeAccess() throw()
00525 //    :   containers (Containers::withSize (NumThreads)),
00526 //        threads (Threads::withSize (NumThreads))
00527 //    {
00528 //        clearThreads();
00529 //        threads.atUnchecked (0) = Threading::getCurrentThreadID();
00530 //    }
00531 //    
00532 //    ~ThreadSafeAccess()
00533 //    {
00534 //    }
00535 //    
00536 //    explicit ThreadSafeAccess (Container const& initialValue) throw()
00537 //    :   containers (Containers::withSize (NumThreads)),
00538 //        threads (Threads::withSize (NumThreads))
00539 //    {        
00540 //        for (int i = 0; i < NumThreads; ++i)
00541 //            containers.atUnchecked (i) = initialValue.copy();
00542 //        
00543 //        clearThreads();
00544 //        threads.atUnchecked (0) = Threading::getCurrentThreadID();
00545 //    }
00546 //    
00547 //    Container operator->() throw() 
00548 //    { 
00549 //        const Threading::ID threadID = Threading::getCurrentThreadID();
00550 //        
00551 //        if (threads.contains (threadID))
00552 //        {
00553 //            return containers.atUnchecked (threads.indexOf (threadID));
00554 //        }
00555 //        else 
00556 //        {
00557 //            AtomicThreadID* const ids = threads.getArray();
00558 //            
00559 //            for (int i = 0; i < NumThreads; ++i)
00560 //                if (ids[i].compareAndSwap (0, threadID))
00561 //                    return containers.atUnchecked (i);
00562 //        }
00563 //        
00564 //        plonk_assertfalse; // too many threads trying to access the data
00565 //        return Container::getNull();
00566 //    }
00567 //    
00568 //    void releaseThread() throw()
00569 //    {
00570 //        const Threading::ID threadID = Threading::getCurrentThreadID();
00571 //        AtomicThreadID* const ids = threads.getArray();
00572 //
00573 //        for (int i = 0; i < NumThreads; ++i)
00574 //            if (ids[i].compareAndSwap (threadID, 0))
00575 //                return;
00576 //    }
00577 //    
00578 //private:
00579 //    Containers containers;
00580 //    Threads threads;
00581 //    
00582 //    void clearThreads() throw()
00583 //    {
00584 //        for (int i = 0; i < NumThreads; ++i)
00585 //            threads.atUnchecked (i) = 0;
00586 //    }
00587 //};
00588 
00589 
00590 
00591 #endif // PLONK_COLLECTIONS_H
 All Classes Functions Typedefs Enumerations Enumerator Properties