MOAB: Mesh Oriented datABase  (version 5.2.1)
ExtraDataUser.hpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2006 Lawrence Livermore National Laboratory.  Under
00005     the terms of Contract B545069 with the University of Wisconsin --
00006     Madison, Lawrence Livermore National Laboratory retains certain
00007     rights in this software.
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Lesser General Public
00011     License as published by the Free Software Foundation; either
00012     version 2.1 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2006) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file ExtraDataUser.hpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #ifndef MSQ_EXTRA_DATA_USER_HPP
00033 #define MSQ_EXTRA_DATA_USER_HPP
00034 
00035 #include "Mesquite.hpp"
00036 #include "ExtraData.hpp"
00037 #include <assert.h>
00038 
00039 namespace MBMesquite
00040 {
00041 
00042 template < typename T >
00043 class ExtraUserData;
00044 
00045 /**\brief Manage extra data attached to PatchData instances
00046  *
00047  * This class manages the details of using the ExtraData mechanism
00048  * for attaching data to and/or observing a PatchData.  The template
00049  * parameter is the type definint the data to be stored on the
00050  * PatchData.
00051  *
00052  * To use this class, define a type (struct or whatever) to contain
00053  * the data that will be stored on PatchData instances, and create
00054  * a subclass of this class, where the template parameter for this
00055  * class is the data type.  Provide implementations of the pure
00056  * virtual (abstract) methods for notification of changes to the PatchData.
00057  */
00058 template < typename T >
00059 class ExtraDataUser
00060 {
00061   public:
00062     ExtraDataUser();
00063 
00064     virtual ~ExtraDataUser();
00065 
00066     typedef T DataType;
00067 
00068     /** returns null if data hasn't been set via set_data */
00069     T* get_data_ptr( PatchData& patch );
00070 
00071     /** creates data if doesn't exist */
00072     T& get_data( PatchData& patch );
00073 
00074     void set_data( PatchData& patch, const T& data );
00075 
00076     void notify_patch_destroyed( ExtraUserData< T >* data );
00077 
00078     virtual void notify_patch_destroyed( T& data ) = 0;
00079 
00080     virtual void notify_new_patch( PatchData& patch, T& data ) = 0;
00081 
00082     virtual void notify_sub_patch( PatchData& patch, T& data, PatchData& sub_patch, const size_t* vertex_index_map,
00083                                    const size_t* element_index_map, MsqError& err ) = 0;
00084 
00085   private:
00086     ExtraUserData< T >* listHead;
00087 };
00088 
00089 template < typename T >
00090 class ExtraUserData : public ExtraData
00091 {
00092   public:
00093     ExtraDataUser< T >* dataOwner;
00094     ExtraUserData< T >* userNext;
00095     T userData;
00096 
00097     ExtraUserData( PatchData& patch, ExtraDataUser< T >* owner, ExtraUserData< T >* next, const T& data )
00098         : ExtraData( patch ), dataOwner( owner ), userNext( next ), userData( data )
00099     {
00100     }
00101 
00102     ExtraUserData( PatchData& patch, ExtraDataUser< T >* owner, ExtraUserData< T >* next )
00103         : ExtraData( patch ), dataOwner( owner ), userNext( next )
00104     {
00105     }
00106 
00107     virtual void notify_patch_destroyed();
00108 
00109     virtual void notify_new_patch();
00110 
00111     virtual void notify_sub_patch( PatchData& sub_patch, const size_t* vtx_index_map, const size_t* elm_index_map,
00112                                    MsqError& err );
00113 };
00114 
00115 template < typename T >
00116 void ExtraUserData< T >::notify_patch_destroyed()
00117 {
00118     dataOwner->notify_patch_destroyed( this );
00119 }
00120 
00121 template < typename T >
00122 void ExtraUserData< T >::notify_new_patch()
00123 {
00124     dataOwner->notify_new_patch( *get_patch_data(), userData );
00125 }
00126 
00127 template < typename T >
00128 void ExtraUserData< T >::notify_sub_patch( PatchData& sub, const size_t* vertex_map, const size_t* element_map,
00129                                            MsqError& err )
00130 {
00131     dataOwner->notify_sub_patch( *get_patch_data(), userData, sub, vertex_map, element_map, err );
00132 }
00133 
00134 template < typename T >
00135 ExtraDataUser< T >::ExtraDataUser() : listHead( 0 )
00136 {
00137 }
00138 
00139 template < typename T >
00140 ExtraDataUser< T >::~ExtraDataUser()
00141 {
00142     while( ExtraUserData< T >* dead_ptr = listHead )
00143     {
00144         listHead           = dead_ptr->userNext;
00145         dead_ptr->userNext = 0;
00146         delete dead_ptr;
00147     }
00148 }
00149 
00150 template < typename T >
00151 T* ExtraDataUser< T >::get_data_ptr( PatchData& patch )
00152 {
00153     for( ExtraUserData< T >* ptr = listHead; ptr; ptr = ptr->userNext )
00154         if( ptr->get_patch_data() == &patch ) return &( ptr->userData );
00155     return 0;
00156 }
00157 
00158 template < typename T >
00159 T& ExtraDataUser< T >::get_data( PatchData& patch )
00160 {
00161     T* ptr = get_data_ptr( patch );
00162     if( !ptr )
00163     {
00164         listHead = new ExtraUserData< T >( patch, this, listHead );
00165         ptr      = &( listHead->userData );
00166     }
00167     return *ptr;
00168 }
00169 
00170 template < typename T >
00171 void ExtraDataUser< T >::set_data( PatchData& patch, const T& data )
00172 {
00173     T* ptr = get_data_ptr( patch );
00174     if( ptr )
00175         *ptr = data;
00176     else
00177         listHead = new ExtraUserData< T >( patch, this, listHead, data );
00178 }
00179 
00180 template < typename T >
00181 void ExtraDataUser< T >::notify_patch_destroyed( ExtraUserData< T >* data )
00182 {
00183     // remove from list
00184     assert( listHead != 0 );
00185     if( listHead == data )
00186         listHead = data->userNext;
00187     else
00188     {
00189         ExtraUserData< T >* prev;
00190         for( prev = listHead; prev->userNext != data; prev = prev->userNext )
00191             assert( prev->userNext != 0 );
00192         prev->userNext = data->userNext;
00193     }
00194     data->userNext = 0;
00195 
00196     // notify concrete class of event
00197     notify_patch_destroyed( data->userData );
00198 
00199     delete data;
00200 }
00201 
00202 }  // namespace MBMesquite
00203 
00204 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines