MOAB: Mesh Oriented datABase  (version 5.4.0)
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 <cassert>
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,
00083                                    T& data,
00084                                    PatchData& sub_patch,
00085                                    const size_t* vertex_index_map,
00086                                    const size_t* element_index_map,
00087                                    MsqError& err ) = 0;
00088 
00089   private:
00090     ExtraUserData< T >* listHead;
00091 };
00092 
00093 template < typename T >
00094 class ExtraUserData : public ExtraData
00095 {
00096   public:
00097     ExtraDataUser< T >* dataOwner;
00098     ExtraUserData< T >* userNext;
00099     T userData;
00100 
00101     ExtraUserData( PatchData& patch, ExtraDataUser< T >* owner, ExtraUserData< T >* next, const T& data )
00102         : ExtraData( patch ), dataOwner( owner ), userNext( next ), userData( data )
00103     {
00104     }
00105 
00106     ExtraUserData( PatchData& patch, ExtraDataUser< T >* owner, ExtraUserData< T >* next )
00107         : ExtraData( patch ), dataOwner( owner ), userNext( next )
00108     {
00109     }
00110 
00111     virtual void notify_patch_destroyed();
00112 
00113     virtual void notify_new_patch();
00114 
00115     virtual void notify_sub_patch( PatchData& sub_patch,
00116                                    const size_t* vtx_index_map,
00117                                    const size_t* elm_index_map,
00118                                    MsqError& err );
00119 };
00120 
00121 template < typename T >
00122 void ExtraUserData< T >::notify_patch_destroyed()
00123 {
00124     dataOwner->notify_patch_destroyed( this );
00125 }
00126 
00127 template < typename T >
00128 void ExtraUserData< T >::notify_new_patch()
00129 {
00130     dataOwner->notify_new_patch( *get_patch_data(), userData );
00131 }
00132 
00133 template < typename T >
00134 void ExtraUserData< T >::notify_sub_patch( PatchData& sub,
00135                                            const size_t* vertex_map,
00136                                            const size_t* element_map,
00137                                            MsqError& err )
00138 {
00139     dataOwner->notify_sub_patch( *get_patch_data(), userData, sub, vertex_map, element_map, err );
00140 }
00141 
00142 template < typename T >
00143 ExtraDataUser< T >::ExtraDataUser() : listHead( 0 )
00144 {
00145 }
00146 
00147 template < typename T >
00148 ExtraDataUser< T >::~ExtraDataUser()
00149 {
00150     while( ExtraUserData< T >* dead_ptr = listHead )
00151     {
00152         listHead           = dead_ptr->userNext;
00153         dead_ptr->userNext = 0;
00154         delete dead_ptr;
00155     }
00156 }
00157 
00158 template < typename T >
00159 T* ExtraDataUser< T >::get_data_ptr( PatchData& patch )
00160 {
00161     for( ExtraUserData< T >* ptr = listHead; ptr; ptr = ptr->userNext )
00162         if( ptr->get_patch_data() == &patch ) return &( ptr->userData );
00163     return 0;
00164 }
00165 
00166 template < typename T >
00167 T& ExtraDataUser< T >::get_data( PatchData& patch )
00168 {
00169     T* ptr = get_data_ptr( patch );
00170     if( !ptr )
00171     {
00172         listHead = new ExtraUserData< T >( patch, this, listHead );
00173         ptr      = &( listHead->userData );
00174     }
00175     return *ptr;
00176 }
00177 
00178 template < typename T >
00179 void ExtraDataUser< T >::set_data( PatchData& patch, const T& data )
00180 {
00181     T* ptr = get_data_ptr( patch );
00182     if( ptr )
00183         *ptr = data;
00184     else
00185         listHead = new ExtraUserData< T >( patch, this, listHead, data );
00186 }
00187 
00188 template < typename T >
00189 void ExtraDataUser< T >::notify_patch_destroyed( ExtraUserData< T >* data )
00190 {
00191     // remove from list
00192     assert( listHead != 0 );
00193     if( listHead == data )
00194         listHead = data->userNext;
00195     else
00196     {
00197         ExtraUserData< T >* prev;
00198         for( prev = listHead; prev->userNext != data; prev = prev->userNext )
00199             assert( prev->userNext != 0 );
00200         prev->userNext = data->userNext;
00201     }
00202     data->userNext = 0;
00203 
00204     // notify concrete class of event
00205     notify_patch_destroyed( data->userData );
00206 
00207     delete data;
00208 }
00209 
00210 }  // namespace MBMesquite
00211 
00212 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines