LCOV - code coverage report
Current view: top level - ugbase/lib_grid/attachments - attachment_pipe.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 40.0 % 50 20
Test Date: 2025-09-21 23:31:46 Functions: 8.3 % 653 54

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __UTIL__ATTACHMENT_PIPE__
      34              : #define __UTIL__ATTACHMENT_PIPE__
      35              : 
      36              : #include <list>
      37              : #include <vector>
      38              : #include <stack>
      39              : #include <cassert>
      40              : #include "common/static_assert.h"
      41              : #include "common/types.h"
      42              : #include "common/util/uid.h"
      43              : #include "common/util/hash.h"
      44              : #include "common/ug_config.h"
      45              : #include "page_container.h"
      46              : 
      47              : namespace ug
      48              : {
      49              : 
      50              : // PREDECLARATIONS
      51              : class IAttachment;
      52              : class IAttachmentDataContainer;
      53              : 
      54              : 
      55              : // CONSTANTS
      56              : enum ATTACHMENT_CONSTANTS
      57              : {
      58              :         INVALID_ATTACHMENT_INDEX = 0xFFFFFFFF
      59              : };
      60              : 
      61              : 
      62              : ////////////////////////////////////////////////////////////////////////////////////////////////
      63              : //      IAttachedDataContainer
      64              : ///     the interface for an attachment-data-container.
      65              : /** In order to use an attachment-data-container you have to supply several Typedefs.
      66              : * Take a look at the derived generic class AttachmentDataContainer<T> to see which
      67              : * typedefs and operations have to be supplied in addition to the interface-methods.
      68              : * if possible you should always use the derived generic class AttachmentDataContainer<T>
      69              : * instead creating inheriting your own version of IAttachedDataContainer.
      70              : */
      71              : class UG_API IAttachmentDataContainer
      72              : {
      73              :         public:
      74              :                 virtual ~IAttachmentDataContainer()             {}
      75              : 
      76              :                 virtual void resize(size_t iSize) = 0;///< resize the data array
      77              :                 virtual size_t size() = 0;///< returns the size of the data-array.
      78              :                 virtual void copy_data(size_t indFrom, size_t indTo) = 0;///< copy data from entry indFrom to entry indTo.
      79              :                 virtual void reset_entry(size_t index) = 0;///< resets the entry to its default value.
      80              :                 
      81              :         /**     copies entries from the this-container to the specified target container.
      82              :          * For the i-th entry in the destination-container, pIndexMap has to contain
      83              :          * the index of the associated source entry in this container.
      84              :          * num specifies the number of entries to be copied.
      85              :          * Make sure, that pDest can hold 'num' elements.
      86              :          *
      87              :          * pDestCon has to have the same or a derived dynamic type as the container
      88              :          * on which this method is called.*/
      89              :                 virtual void copy_to_container(IAttachmentDataContainer* pDestCon,
      90              :                                                                            int* indexMap, int num) const = 0;
      91              :                 
      92              :         /** defragment should clear the containers data from unused entries.
      93              :          * pNewIndices should be an array of indices, wich holds a new index for each
      94              :          * entry in IAttachedDataContainer. pNewIndices has thus to hold as many indices
      95              :          * as there are entries in IAttachedDataContainer. If an entry shall not appear
      96              :          * in the defragmented container, its new index has to be set to INVALID_ATTACHMENT_INDEX.
      97              :          * numValidElements has to specify the size of the defragmented container -
      98              :          * it thus has to equal the number of valid indices in pNewIndices.*/
      99              :                 virtual void defragment(size_t* pNewIndices, size_t numValidElements) = 0;
     100              : 
     101              :         ///     returns the size in bytes, which the container occupies
     102              :         /** Mainly for debugging purposes.*/
     103              :                 virtual size_t occupied_memory() = 0;
     104              : };
     105              : 
     106              : ////////////////////////////////////////////////////////////////////////////////////////////////
     107              : ///     define reference and const reference types for attachment values.
     108              : /**     The default traits should be fine in all cases. A specialization for bool exists.
     109              :  */
     110              : template <class TValue>
     111              : struct attachment_value_traits{
     112              :         typedef TValue&                     reference;
     113              :         typedef const TValue&       const_reference;
     114              : };
     115              : 
     116              : ///     specialization of attachment_value_traits for the bool type
     117              : template <>
     118              : struct attachment_value_traits<bool>{
     119              :         typedef std::vector<bool>::reference              reference;
     120              :         typedef const std::vector<bool>::reference        const_reference;
     121              : };
     122              : 
     123              : /* THOUGHTS
     124              : *       AttachmentDataContainer<T> should probably be defined in another header, since it is somehow specialised for libGrid.
     125              : *       same goes for Attachment<T>
     126              : */
     127              : ////////////////////////////////////////////////////////////////////////////////////////////////
     128              : //      AttachedDataContainer
     129              : ///     A generic specialization of IAttachedDataContainer.
     130              : /** This template-class not only simplifies the creation of custom containers,
     131              :  * it also defines some types, operators and values, which are essential to use an AttachmentDataContainer with libGrid.
     132              :  * In particular libGrids AttachmentAccessors require these definitions.
     133              :  */
     134              : template <class T> class UG_API AttachmentDataContainer : public IAttachmentDataContainer
     135              : {
     136              :         private:
     137              :                 typedef AttachmentDataContainer<T>        ClassType;
     138              :                 //typedef PageContainer<T>                        DataContainer;
     139              :                 typedef std::vector<T>                            DataContainer;
     140              :                 typedef typename attachment_value_traits<T>::reference                    TRef;
     141              :                 typedef typename attachment_value_traits<T>::const_reference      TConstRef;
     142              : 
     143              :         public:
     144              :                 typedef T       ValueType;
     145              : 
     146           11 :                 AttachmentDataContainer(const T& defaultValue = T())        : m_defaultValue(defaultValue)  {}
     147              : 
     148           27 :                 virtual ~AttachmentDataContainer()                      {m_vData.clear();}
     149              : 
     150           27 :                 virtual void resize(size_t iSize)
     151              :                         {
     152           27 :                                 if(iSize > 0)
     153           20 :                                         m_vData.resize(iSize, m_defaultValue);
     154              :                                 else
     155              :                                         m_vData.clear();
     156           27 :                         }
     157              : 
     158            0 :                 virtual size_t size()   {return m_vData.size();}
     159              : 
     160            0 :                 virtual void copy_data(size_t indFrom, size_t indTo)    {m_vData[indTo] = m_vData[indFrom];}
     161              : 
     162            0 :                 virtual void reset_entry(size_t index)
     163              :                         {
     164            0 :                                 m_vData[index] = m_defaultValue;
     165            0 :                         }
     166              : 
     167            0 :                 virtual void defragment(size_t* pNewIndices, size_t numValidElements)
     168              :                         {
     169            0 :                                 size_t numOldElems = size();
     170            0 :                                 DataContainer vDataOld = m_vData;
     171            0 :                                 m_vData.resize(numValidElements);
     172            0 :                                 for(size_t i = 0; i < numOldElems; ++i)
     173              :                                 {
     174            0 :                                         size_t nInd = pNewIndices[i];
     175            0 :                                         if(nInd != INVALID_ATTACHMENT_INDEX)
     176            0 :                                                 m_vData[nInd] = vDataOld[i];
     177              :                                 }
     178            0 :                         }
     179              :         
     180              :         /**     copies entries from the this-container to the container
     181              :          *      specified by pDestCon.
     182              :          *      For the i-th entry in the target container, pIndexMap has to contain
     183              :          *      the index of the associated source entry in this container.
     184              :          *      num specifies the number of entries to be copied.
     185              :          *      Make sure, that pDest can hold 'num' elements.
     186              :          *
     187              :          *      pDestCon has to have the same or a derived dynamic type as the container
     188              :          *      on which this method is called.*/
     189            0 :                 virtual void copy_to_container(IAttachmentDataContainer* pDestCon,
     190              :                                                                                 int* indexMap, int num) const
     191              :                         {
     192            0 :                                 ClassType* destConT = dynamic_cast<ClassType*>(pDestCon);
     193              :                                 assert(destConT && "Type of pDestBuf has to be the same as the"
     194              :                                                 "type of this buffer");
     195              : 
     196            0 :                                 if(!destConT)
     197              :                                         return;
     198              : 
     199              :                                 DataContainer& dest = destConT->get_data_container();
     200            0 :                                 for(int i = 0; i < num; ++i)
     201            0 :                                         dest[i] = m_vData[indexMap[i]];
     202              :                         }
     203              : 
     204              : 
     205              :         ///     returns the memory occupied by the container
     206            0 :                 virtual size_t occupied_memory()
     207              :                 {
     208            0 :                         return m_vData.capacity() * sizeof(T);
     209              :                 }
     210              : 
     211              :                 inline TConstRef get_elem(size_t index) const           {return m_vData[index];}
     212              :                 inline TRef get_elem(size_t index)                                      {return m_vData[index];}
     213              :                 inline TConstRef operator[] (size_t index) const        {return m_vData[index];}
     214              :                 inline TRef operator[] (size_t index)                           {return m_vData[index];}
     215              : 
     216              :         ///     swaps the buffer content of associated data
     217              :                 void swap(AttachmentDataContainer<T>& container)      {m_vData.swap(container.m_vData);}
     218              : 
     219              :         protected:
     220              :                 DataContainer& get_data_container()                 {return m_vData;}
     221              :                 //inline const T* get_ptr() const                       {return &m_vData.front();}
     222              :                 //inline T* get_ptr()                                           {return &m_vData.front();}
     223              :                 
     224              :         protected:
     225              :                 DataContainer   m_vData;
     226              :                 T                               m_defaultValue;
     227              : };
     228              : 
     229              : ////////////////////////////////////////////////////////////////////////////////////////////////
     230              : //      IAttachment
     231              : ///     the interface for attachments.
     232              : /** Attachments can be attached to an AttachmentPipe and thus enhance the pipes elements by data,
     233              :  * whose type, container and behavior is defined by the Attachment itself.
     234              :  * In order to use an Attachment with libGrid (in particular with libGrids AttachmentAccessors),
     235              :  * derivatives of IAttachment have to feature some special typedefs (see Attachment<T> for more information).
     236              :  * Whenever possible you should use the template-derivative Attachment<T> instead of IAttachment.
     237              :  */
     238           11 : class UG_API IAttachment : public UID
     239              : {
     240              :         public:
     241           11 :                 IAttachment() : m_name("undefined")   {}
     242            5 :                 IAttachment(const char* name) : m_name(name)
     243              :                         {assert(m_name);}
     244              : 
     245              :                 virtual ~IAttachment()  {}
     246              :                 virtual IAttachment* clone() = 0;
     247              :                 virtual IAttachmentDataContainer*       create_container() = 0;
     248              :                 virtual bool default_pass_on_behaviour() const = 0;
     249              : 
     250            0 :                 const char* get_name()  {return m_name;}    ///< should only be used for debug purposes.
     251              : 
     252              :         protected:
     253              :                 const char* m_name; //only for debug
     254              : };
     255              : 
     256              : ////////////////////////////////////////////////////////////////////////////////////////////////
     257              : //      Attachment
     258              : /// A generic specialization of IAttachment
     259              : /** This class is intended to simplify the process of Attachment creation.
     260              :  * Note that there are typedefs, which are required by libGrids AttachmentAccessors.
     261              :  */
     262            0 : template <class T> class UG_API Attachment : public IAttachment
     263              : {
     264              :         public:
     265              :                 typedef AttachmentDataContainer<T>        ContainerType;
     266              :                 typedef T                                                       ValueType;
     267              : 
     268           11 :                 Attachment() : IAttachment(), m_passOnBehaviour(false)    {}
     269            0 :                 Attachment(bool passOnBehaviour) : IAttachment(), m_passOnBehaviour(passOnBehaviour)    {}
     270            0 :                 Attachment(const char* name) : IAttachment(name), m_passOnBehaviour(false)              {}
     271            5 :                 Attachment(const char* name, bool passOnBehaviour) : IAttachment(name), m_passOnBehaviour(passOnBehaviour)      {}
     272              : 
     273           17 :                 virtual ~Attachment()   {}
     274           11 :                 virtual IAttachment* clone()                                                    {IAttachment* pA = new Attachment<T>; *pA = *this; return pA;}
     275           11 :                 virtual IAttachmentDataContainer* create_container()    {return new ContainerType;}
     276            7 :                 virtual bool default_pass_on_behaviour() const                  {return m_passOnBehaviour;}
     277            0 :                 IAttachmentDataContainer* create_container(const T& defaultValue)   {return new ContainerType(defaultValue);}
     278              : 
     279              :         protected:
     280              :                 bool m_passOnBehaviour;
     281              : };
     282              : 
     283              : ////////////////////////////////////////////////////////////////////////////////////////////////
     284              : //      AttachmentEntry
     285              : ///     This struct is used by AttachmentPipe in order to manage its attachments
     286              : struct AttachmentEntry
     287              : {
     288              :         AttachmentEntry() : m_pAttachment(NULL), m_pContainer(NULL), m_userData(0)      {}
     289           11 :         AttachmentEntry(IAttachment* pAttachment, IAttachmentDataContainer* pContainer, uint userData = 0) :
     290           11 :                         m_pAttachment(pAttachment), m_pContainer(pContainer), m_userData(userData)      {}
     291              : 
     292              :         IAttachment*                            m_pAttachment;
     293              :         IAttachmentDataContainer*       m_pContainer;
     294              :         uint                                            m_userData;
     295              : };
     296              : 
     297              : 
     298              : ////////////////////////////////////////////////////////////////////////////////////////////////
     299              : ///     define the interface that enables you to use your own types as element-types in an AttachmentPipe.
     300              : /** By creating a template specialization for your own element types, you can
     301              :  * use arbitrary types as element-types in an AttachmentPipe.
     302              :  */
     303              : template<class TElem, class TElemHandler>
     304              : class attachment_traits
     305              : {
     306              :         public:
     307              :                 typedef TElem&              ElemRef;
     308              :                 typedef void*           ElemPtr;
     309              :                 typedef const void* ConstElemPtr;
     310              :                 typedef void*           ElemHandlerPtr;
     311              :                 typedef const void*     ConstElemHandlerPtr;
     312              : 
     313              :                 typedef void            element_iterator;
     314              : 
     315              :                 static inline element_iterator elements_begin(ElemHandlerPtr pHandler)                                  {}
     316              :                 static inline element_iterator elements_end(ElemHandlerPtr pHandler)                                    {}
     317              :                 static inline uint get_data_index(ElemHandlerPtr pHandler, ConstElemPtr elem)                   {return INVALID_ATTACHMENT_INDEX;/*STATIC_ASSERT(0, INVALID_ATTACHMENT_TRAITS);*/}
     318              :                 static inline void set_data_index(ElemHandlerPtr pHandler, ElemPtr elem, size_t index)  {/*STATIC_ASSERT(0, INVALID_ATTACHMENT_TRAITS);*/}
     319              : };
     320              : 
     321              : ////////////////////////////////////////////////////////////////////////////////////////////////
     322              : //      AttachmentPipe
     323              : ///     Handles data which has been attached to the pipe using callbacks for the element.
     324              : /** The AttachmentPipe can be used to attach data to a collection of elements.
     325              :  * Elements have to be registered at the AttachmentPipe. Using the methods
     326              :  * defined in the attachment_traits template class, registered elements are
     327              :  * associated with their data-entries.
     328              :  *
     329              :  * TODO:
     330              :  * enum Options : CopyAllowed
     331              :  *
     332              :  * - copy_values(TElem from, TElem to)
     333              :  * - swap_entry_indices()?!?
     334              :  */
     335              : template<class TElem, class TElemHandler>
     336              : class UG_API AttachmentPipe
     337              : {
     338              :         public:
     339              :                 typedef TElem                                                           element;
     340              :                 typedef TElemHandler                                            ElementHandler;
     341              :                 typedef std::list<AttachmentEntry>                        AttachmentEntryContainer;
     342              :                 typedef AttachmentEntryContainer::iterator      AttachmentEntryIterator;
     343              :                 typedef AttachmentEntryContainer::const_iterator        ConstAttachmentEntryIterator;
     344              :                 typedef Hash<uint, AttachmentEntryIterator>               AttachmentEntryIteratorHash;
     345              :                 typedef attachment_traits<TElem, TElemHandler>    atraits;
     346              : 
     347              :         public:
     348              :                 AttachmentPipe();
     349              :                 AttachmentPipe(typename atraits::ElemHandlerPtr pHandler);
     350              :                 ~AttachmentPipe();
     351              :                 
     352           10 :                 inline typename atraits::ElemHandlerPtr get_elem_handler()              {return m_pHandler;}
     353              :                 
     354              :         ///     calls both clear_elements and clear_attachments.
     355              :                 void clear();
     356              :         ///     clears elements and associated data but keeps registered attachments
     357              :                 void clear_elements();
     358              :         ///     clears registered attachments and associated data but keeps existing elements.
     359              :                 void clear_attachments();
     360              : 
     361              :         ///     Reserves memory for element- and data-entries.
     362              :         /**     This method reserves memory for data and elements.
     363              :          * Note that numElems specifies the total amount of elements
     364              :          * for which data shall be reserved. If numElems is smaller than
     365              :          * num_elements, then nothing will be done.
     366              :          * Note that a call to reserve does not change num_elements nor
     367              :          * num_data_entries.
     368              :          *
     369              :          * If you want to reserve space for additional N elements, please
     370              :          * call reserve with numElems = num_elements() + N.
     371              :          *
     372              :          * Note that reserve is optional and only serves performance benefits.
     373              :          */
     374              :                 void reserve(size_t numElems);
     375              : 
     376              :         ///     Registers a new element at the attachment pipe.
     377              :         /**     Registers the element and reserves memory for all registered
     378              :          * attachments. Note that this method may be faster if memory has
     379              :          * previously been reserved using reserve_new.
     380              :          */
     381              :                 void register_element(TElem elem);
     382              : 
     383              :         ///     Unregisters the given element.
     384              :         /**     Unregisters the given element but does not yet clear associated data.
     385              :          * Indeed the memory is kept until defragment is called or new elements
     386              :          * reuse the memory.
     387              :          */
     388              :                 void unregister_element(const TElem& elem);
     389              : 
     390              :         /**     Aligns data with elements and removes unused data-memory.*/
     391              :                 void defragment();
     392              : 
     393              :         /**\brief attaches a new data-array to the pipe.
     394              :          *
     395              :          * Attachs a new attachment and creates a container which holds the
     396              :          * data associated with the elements through this attachment.
     397              :          * Several overloads exist: You may pass an attachment together with
     398              :          * a default value and with an option constant or simply the attachment
     399              :          * together with an optional option constant. Not that in the first
     400              :          * case the concrete type of the attachment has to be known, whereas
     401              :          * in the second case only the interface IAttachment has to be specified.
     402              :          *
     403              :          * The option constant is not used by the attachment system but may be
     404              :          * used by a user to store a constant with each attachment.
     405              :          * \{
     406              :          */
     407              :                 template <class TAttachment>
     408              :                 void attach(TAttachment& attachment,
     409              :                                         const typename TAttachment::ValueType& defaultValue,
     410              :                                         uint options);
     411              : 
     412              :                 void attach(IAttachment& attachment, uint options = 0);
     413              :         /**     \}      */
     414              : 
     415              :         ///     Removes the data associated with the given attachment from the pipe.
     416              :                 void detach(IAttachment& attachment);
     417              : 
     418              :         ///     Returns true if the given attachment is currently attached to the pipe.
     419              :                 bool has_attachment(IAttachment& attachment) const;
     420              : 
     421              :         ///     Lets you access the raw data array associated with the given attachment.
     422              :         /**     If you access several arrays through this method, it is guaranteed that
     423              :          * the data associated with one specific object are found at the same indices
     424              :          * in those arrays.
     425              :          *
     426              :          * Note that if you access the data arrays after a call to defragment, then
     427              :          * the i-th data-entry corresponds to the i-th element.
     428              :          *
     429              :          * Please not that the pointer may be invalidated through the following operations:
     430              :          *              - register_element
     431              :          *              - defragment
     432              :          *              - clear, clear_elements, clear_attachments
     433              :          */
     434              :                 template <class TAttachment>
     435              :                 typename TAttachment::ValueType*
     436              :                 get_data_array(TAttachment& attachment);
     437              :                 
     438              :         /**     \brief Returns the data container managing the data array for the given attachment.
     439              :          * \{ */
     440              :                 IAttachmentDataContainer* get_data_container(IAttachment& attachment) const;
     441              : 
     442              :                 template <class TAttachment>
     443              :                 typename TAttachment::ContainerType*
     444              :                 get_data_container(TAttachment& attachment);
     445              :         /**     \} */
     446              : 
     447              :                 inline ConstAttachmentEntryIterator attachments_begin() const   {return m_attachmentEntryContainer.begin();}
     448              :                 inline ConstAttachmentEntryIterator attachments_end() const             {return m_attachmentEntryContainer.end();}
     449              : 
     450              :         ///     Returns the number of registered elements
     451            0 :                 inline size_t num_elements() const              {return m_numElements;}
     452              :         ///     Returns the size of the associated data arrays
     453              :         /**     Note: If the pipe is fragmented, then num_elements and num_data_entries
     454              :          * differ. If the pipe however isn't fragmented, then both values are the same.
     455              :          */
     456            0 :                 inline size_t num_data_entries() const  {return m_numDataEntries;}
     457              : 
     458              :         ///     Returns whether the attachment pipe is fragmented.
     459              :         /**     The pipe gets fragmented whenever elements are erased.
     460              :          * Through the creation of new elements the pipe may be automatically
     461              :          * defragmented.
     462              :          * Through a call to defragment() the pipe can be defragmented at any time.
     463              :          */
     464              :                 inline bool is_fragmented() const               {return m_numElements != m_numDataEntries;}
     465              : 
     466              :                 void reset_values(size_t dataIndex);///< fills the attached data at the given index with the default values.
     467              : 
     468              :         protected:
     469              :                 void resize_attachment_containers(size_t newSize);
     470              :                 void grow_attachment_containers(size_t newMinSize);
     471              :                 inline size_t get_container_size();
     472              : 
     473              :         protected:
     474              :                 typedef std::stack<size_t>                UINTStack;
     475              : 
     476              :         protected:
     477              :                 AttachmentEntryContainer        m_attachmentEntryContainer;
     478              :                 AttachmentEntryIteratorHash     m_attachmentEntryIteratorHash;
     479              : 
     480              :                 UINTStack               m_stackFreeEntries;     ///< holds indices to free entries.
     481              : 
     482              :                 size_t                  m_numElements;
     483              :                 size_t                  m_numDataEntries;
     484              :                 size_t                  m_containerSize; ///< total size of containers.
     485              :                 
     486              :                 typename atraits::ElemHandlerPtr        m_pHandler;
     487              : };
     488              : 
     489              : 
     490              : ////////////////////////////////////////////////////////////////////////////////////////////////
     491              : //      AttachmentAccessor
     492              : ///     Used to access data that has been attached to an attachment pipe.
     493              : /** Once initialized, an AttachmentAccessor can be used to access the data stored
     494              :  * in the given Attachment at the given AttachmentPipe.
     495              :  * The reference type of the associated value is taken from attachment_value_traits.
     496              :  * By default this is the standard reference type.
     497              :  *
     498              :  * To initialize an AttachmentAccessor, you may either use its constructor or
     499              :  * its access method, which returns false if the specified attachment is not present
     500              :  * in the specified attachment pipe.
     501              :  *
     502              :  * Note that data-access using an attachment accessor is cheap. Setting up
     503              :  * a new attachment accessor however involves some work. While this is generally
     504              :  * fast, too, it would introduce an unnecessary overhead inside inner loops
     505              :  * or frequently called methods. You should thus try to minimize calls to access
     506              :  * or to the accessors constructor.
     507              :  */
     508              : template <class TElem, class TAttachment, class TElemHandler>
     509              : class UG_API AttachmentAccessor
     510              : {
     511              :         public:
     512              :                 typedef TAttachment                                                     attachment;
     513              :                 typedef TElem                                                           element;
     514              :                 typedef typename TAttachment::ValueType         ValueType;
     515              :                 typedef typename TAttachment::ContainerType     ContainerType;
     516              :                 typedef TElemHandler                                            ElemHandler;
     517              :                 typedef attachment_traits<TElem, TElemHandler>    atraits;
     518              :                 typedef AttachmentPipe<TElem, TElemHandler>       attachment_pipe;
     519              : 
     520              :         public:
     521              :                 AttachmentAccessor();
     522              :                 AttachmentAccessor(const AttachmentAccessor& aa);
     523              :                 AttachmentAccessor(AttachmentPipe<TElem, TElemHandler>& attachmentPipe, TAttachment& attachment);
     524              : 
     525              :                 bool access(attachment_pipe& attachmentPipe, TAttachment& attachment);
     526              : 
     527              :                 inline typename attachment_value_traits<ValueType>::reference
     528              :                 operator[](typename atraits::ConstElemPtr elem)
     529              :                         {
     530              :                                 assert((attachment_traits<TElem, TElemHandler>::get_data_index(m_pHandler, elem) != INVALID_ATTACHMENT_INDEX) &&
     531              :                                                 "ERROR in AttachmentAccessor::operator[]: accessing element with invalid attachment index!");
     532              :                                 assert(m_pContainer && "ERROR in AttachmentAccessor::operator[]: no AttachmentPipe assigned.");
     533           28 :                                 return m_pContainer->get_elem(attachment_traits<TElem, TElemHandler>::get_data_index(m_pHandler, elem));
     534              :                         }
     535              :                         
     536              :                 inline typename attachment_value_traits<ValueType>::const_reference
     537              :                 operator[](typename atraits::ConstElemPtr elem) const
     538              :                         {
     539              :                                 assert((attachment_traits<TElem, TElemHandler>::get_data_index(m_pHandler, elem) != INVALID_ATTACHMENT_INDEX) &&
     540              :                                                 "ERROR in AttachmentAccessor::operator[]: accessing element with invalid attachment index!");
     541              :                                 assert(m_pContainer && "ERROR in AttachmentAccessor::operator[]: no AttachmentPipe assigned.");
     542            0 :                                 return m_pContainer->get_elem(attachment_traits<TElem, TElemHandler>::get_data_index(m_pHandler, elem));
     543              :                         }
     544              :                         
     545              : /*
     546              :                 inline ValueType&
     547              :                 operator[](int index)
     548              :                         {
     549              :                                 assert(m_pContainer && "ERROR in AttachmentAccessor::operator[]: no AttachmentPipe assigned.");
     550              :                                 return m_pContainer->get_elem(index);
     551              :                         }
     552              : */
     553              :                 inline bool valid() const
     554            0 :                         {return m_pContainer != NULL;}
     555              : 
     556              :                 inline void invalidate()
     557           12 :                         {m_pContainer = NULL;}
     558              :                         
     559              :         ///     calls swap on associated containers
     560              :                 void swap(AttachmentAccessor<TElem, TAttachment, TElemHandler>& acc)
     561              :                 {
     562              :                         m_pContainer->swap(*acc.m_pContainer);
     563              :                 }
     564              : 
     565              :         ///     returns the raw pointer to the data of the associated container
     566              :         /**     ATTENTION: Use this method with extreme care!
     567              :          * Returns NULL if no container was associated. 
     568              :          */
     569              :                 ValueType* raw_data()
     570              :                 {
     571              :                         if(m_pContainer){
     572              :                                 if(m_pContainer->size() > 0)
     573              :                                         return &(*m_pContainer)[0];
     574              :                         }
     575              :                         return NULL;
     576              :                 }
     577              :                 
     578              :         ///     returns the data index of the given element regarding the associated container.
     579              :         /**     Note that the data index does not stay constant all the time. If the
     580              :          * associated container is, e.g., defragmented, the data index may change.*/
     581              :                 size_t element_data_index(typename atraits::ConstElemPtr elem)
     582              :                 {
     583              :                         return attachment_traits<TElem, TElemHandler>::get_data_index(m_pHandler, elem);
     584              :                 }
     585              :                 
     586              :         protected:
     587              :                 ContainerType*  m_pContainer;
     588              :                 TElemHandler*   m_pHandler;
     589              : };
     590              : 
     591              : 
     592              : }//     end of namespace
     593              : 
     594              : //      include implementation
     595              : #include "attachment_pipe.hpp"
     596              : 
     597              : #endif
        

Generated by: LCOV version 2.0-1