MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #ifndef TYPE_SEQUENCE_MANAGER_HPP 00002 #define TYPE_SEQUENCE_MANAGER_HPP 00003 00004 #include "EntitySequence.hpp" 00005 #include "moab/Range.hpp" 00006 00007 #include <set> 00008 #include <vector> 00009 00010 namespace moab 00011 { 00012 00013 class Error; 00014 00015 /**\brief Maintain data structures organizing EntitySequence instances 00016 * 00017 * EntitySequenceManager is a composition of instances of TypeSequenceManager, 00018 * one instance for each EntityType. The TypeSequenceManager provides 00019 * organization, ownership, and querying of EntitySequences for a specific 00020 * EntityType. 00021 */ 00022 class TypeSequenceManager 00023 { 00024 public: 00025 /**\brief Comparison function used in std::set 00026 * 00027 * Define less-than comparison for EntitySequence pointers as a comparison 00028 * of the entity handles in the pointed-to EntitySequences. 00029 */ 00030 template < class T > 00031 class SequenceCompare 00032 { 00033 public: 00034 inline bool operator()( const T* a, const T* b ) const 00035 { 00036 return a->end_handle() < b->start_handle(); 00037 } 00038 }; 00039 /**\brief Dummy EntitySequence for use in querying set container */ 00040 class DummySequence : public EntitySequence 00041 { 00042 public: 00043 DummySequence( EntityHandle start ) : EntitySequence( start ) {} 00044 00045 EntitySequence* split( EntityHandle ) 00046 { 00047 return 0; 00048 } 00049 SequenceData* create_data_subset( EntityHandle, EntityHandle ) const 00050 { 00051 return 0; 00052 } 00053 00054 void get_const_memory_use( unsigned long& a, unsigned long& b ) const 00055 { 00056 a = b = 0; 00057 } 00058 unsigned long get_per_entity_memory_use( EntityHandle, EntityHandle ) const 00059 { 00060 return 0; 00061 } 00062 }; 00063 00064 /**\brief Type of container for organizing EntitySequence instances */ 00065 typedef std::set< EntitySequence*, SequenceCompare< EntitySequence > > set_type; 00066 /**\brief Iterator for set_type */ 00067 typedef set_type::iterator iterator; 00068 /**\brief Iterator for set_type */ 00069 typedef set_type::const_iterator const_iterator; 00070 /**\brief Type of container for organizing SequenceData instances */ 00071 typedef std::set< SequenceData*, SequenceCompare< SequenceData > > data_set_type; 00072 /**\brief iterator type for data_set_type */ 00073 typedef data_set_type::iterator data_iterator; 00074 00075 struct SequenceDataPtr 00076 { 00077 private: 00078 friend class TypeSequenceManager; 00079 TypeSequenceManager::iterator firstSequence; 00080 }; 00081 00082 private: 00083 mutable EntitySequence* lastReferenced; //!< Last accessed EntitySequence - Null only if no sequences 00084 set_type sequenceSet; //!< Set of all managed EntitySequence instances 00085 data_set_type availableList; //!< SequenceData containing unused entries 00086 00087 iterator erase( iterator i ); //!< Remove a sequence 00088 00089 iterator split_sequence( iterator i, EntityHandle h ); //!< split a sequence 00090 00091 void append_memory_use( EntityHandle first, 00092 EntityHandle last, 00093 const SequenceData* data, 00094 unsigned long long& entity_storage, 00095 unsigned long long& total_storage ) const; 00096 00097 // check if sequence at passed iterator should be merged with 00098 // the subsequent sequence, and if so merge them retaining i. 00099 ErrorCode check_merge_next( iterator i ); 00100 // check if sequence at passed iterator should be merged with 00101 // the previous sequence, and if so merge them retaining i. 00102 ErrorCode check_merge_prev( iterator i ); 00103 // common code for check_merge_next and check_merge_prev 00104 ErrorCode merge_internal( iterator keep, iterator dead ); 00105 00106 #ifndef NDEBUG 00107 bool check_valid_data( const EntitySequence* seq ) const; 00108 #endif 00109 00110 public: 00111 /**\brief Add an entity sequence 00112 * 00113 * Take ownership of passed EntitySequence, and update relevant 00114 * data structures. Sequence may not overlap with any existing 00115 * sequence. 00116 * 00117 * NOTE: Sequence may be merged with other, existing sequences. 00118 * This function will always ensure that the passed 00119 * EntitySequence* is the remaining one, but the passed 00120 * sequence may have modified start and end handles. 00121 */ 00122 ErrorCode insert_sequence( EntitySequence* seq_ptr ); 00123 00124 /**\brief Remove an entity sequence. 00125 * 00126 * Give up ownership of specified EntitySequence, and remove it 00127 * from all internal data structures. Passes back bool flag to 00128 * notify caller that ownership of the corresponding SequenceData 00129 * is also relinquished because the specified EntitySequence is 00130 * the last one referencing it. 00131 */ 00132 ErrorCode remove_sequence( const EntitySequence* seq_ptr, bool& is_last_user_of_sequence_data ); 00133 00134 /**\brief Replace sequence or subset of sequence 00135 * 00136 * Replace one sequence or a subset of one sequence with 00137 * another sequence. With fail if a) the existing 00138 * sequence is not a subset of an existing sequence or 00139 * b) existing sequence shares a SequenceData with the 00140 * passed sequence. 00141 * 00142 * This method is provided for use when changing the 00143 * number of nodes in elements. 00144 */ 00145 ErrorCode replace_subsequence( EntitySequence* seq_ptr, const int* tag_sizes, int num_tag_sizes ); 00146 00147 TypeSequenceManager() : lastReferenced( 0 ) {} 00148 00149 ~TypeSequenceManager(); 00150 00151 /**\brief Start of EntitySequence set */ 00152 const_iterator begin() const 00153 { 00154 return sequenceSet.begin(); 00155 } 00156 iterator begin() 00157 { 00158 return sequenceSet.begin(); 00159 } 00160 00161 /**\brief End of EntitySequence set */ 00162 const_iterator end() const 00163 { 00164 return sequenceSet.end(); 00165 } 00166 iterator end() 00167 { 00168 return sequenceSet.end(); 00169 } 00170 00171 /**\brief Return EntitySequence for specified handle. 00172 * 00173 * Return EntitySequence for specified handle, or if 00174 * no such sequence, the next one. Returns end() if 00175 * all sequences have ranges less than specified handle. 00176 */ 00177 const_iterator lower_bound( EntityHandle h ) const 00178 { 00179 DummySequence f( h ); 00180 return sequenceSet.lower_bound( &f ); 00181 } 00182 iterator lower_bound( EntityHandle h ) 00183 { 00184 DummySequence f( h ); 00185 return sequenceSet.lower_bound( &f ); 00186 } 00187 00188 /**\brief Return EntitySequence after specified handle. 00189 * 00190 * Return EntitySequence with smallest start handle 00191 * that is greater than input handle. Returns end() if 00192 * all sequences have start handles less than specified 00193 * handle. 00194 */ 00195 const_iterator upper_bound( EntityHandle h ) const 00196 { 00197 DummySequence f( h ); 00198 return sequenceSet.upper_bound( &f ); 00199 } 00200 00201 /**\brief Get EntitySequence for handle. 00202 *\return EntitySequence for handle, or NULL if no such sequence. 00203 */ 00204 inline EntitySequence* find( EntityHandle h ) const; 00205 inline EntitySequence* find( EntityHandle h ); 00206 inline ErrorCode find( EntityHandle h, EntitySequence*& ); 00207 inline ErrorCode find( EntityHandle h, const EntitySequence*& ) const; 00208 inline const EntitySequence* get_last_accessed() const; 00209 00210 /**\brief Get handles for all entities in all sequences. */ 00211 inline void get_entities( Range& entities_out ) const; 00212 00213 /**\brief Get handles for all entities in all sequences. */ 00214 inline void get_entities( std::vector< EntityHandle >& entities_out ) const; 00215 00216 /**\brief Get number of entities represented by all sequences. */ 00217 inline EntityID get_number_entities() const; 00218 00219 ErrorCode check_valid_handles( Error* error_handler, EntityHandle first, EntityHandle last ) const; 00220 00221 /**\brief Remove entities 00222 * 00223 * Update EntitySequence data as necessary to "delete" the 00224 * specified entities (e.g. split sequences, delete sequences, 00225 * free SequenceData instances, etc.) 00226 */ 00227 ErrorCode erase( Error* error_handler, EntityHandle first, EntityHandle last ); 00228 ErrorCode erase( Error* error_handler, EntityHandle entity ); 00229 00230 /**\brief Test if this instance contains no sequences */ 00231 bool empty() const 00232 { 00233 return 0 == lastReferenced; 00234 } 00235 00236 /**\brief Allocate a handle in an existing entity sequence 00237 * 00238 * Find an existing entity sequence to which a new handle can 00239 * be prepended or appended. The 'append_out' flag indicates 00240 * to the caller that the new handle should be appended to the 00241 * returned sequence if true, and prepended if false. 00242 * 00243 * If no appropriate EntitySequence is available, NULL will 00244 * be returned. The caller will typically then want to use 00245 * find_free_sequence() to find appropriate values for the 00246 * creation of a new EntitySequence. 00247 */ 00248 iterator find_free_handle( EntityHandle min_start_handle, 00249 EntityHandle max_end_handle, 00250 bool& append_out, 00251 int values_per_ent = 0 ); 00252 00253 /**\brief Find block of free handles 00254 * 00255 * Find block of free handles, such that block does not 00256 * overlap any existing EntitySequence. 00257 *\return First handle of block, or zero if no block found. 00258 */ 00259 EntityHandle find_free_block( EntityID num_entities, EntityHandle min_start_handle, EntityHandle max_end_handle ); 00260 00261 /**\brief Find block of free handles 00262 * 00263 * Find block of free handles, such that block a) does not 00264 * overlap any existing EntitySequence and b) is either 00265 * entirely within one existing SequenceData or does not 00266 * overlap any SequenceData. 00267 *\param num_entities Size of handle block. 00268 *\param min_start_handle Block may not contain any handle less than this. 00269 *\param max_end_handle Block may not contain any handle greater than this. 00270 *\param sequence_data_out If block is within an unused portion of an 00271 * existing SequenceData, a pointer to that 00272 * SequenceData. NULL otherwise. 00273 *\return values_per_ent Matched against EntitySequence::values_per_entity. 00274 * An existing SequenceData will not be returned if 00275 * the existing EntitySequences using have a different 00276 * value than the passed one. 00277 */ 00278 EntityHandle find_free_sequence( EntityID num_entities, 00279 EntityHandle min_start_handle, 00280 EntityHandle max_end_handle, 00281 SequenceData*& sequence_data_out, 00282 EntityID& sequence_data_size, 00283 int values_per_ent = 0 ); 00284 00285 /**\brief Check if block of handles is free. 00286 * 00287 * Check if block of handles is free and can be allocated 00288 * as a single EntitySequence. If the block of handles 00289 * is contained within an unused portion of a SequenceData, 00290 * the SequenceData is returned. 00291 */ 00292 bool is_free_sequence( EntityHandle start_handle, 00293 EntityID num_entities, 00294 SequenceData*& sequence_data_out, 00295 int values_per_ent = 0 ); 00296 00297 /**\brief Check if specific handle is free for allocation 00298 * 00299 * Check if a specific handle is not currently allocated 00300 * and can be allocated with the passed value of values_per_ent. 00301 * For example, the handle may not be allocated, but it may 00302 * fall within an existing SequenceData. In that case, it 00303 * must be possible to store the specified values_per_ent 00304 * in the existing SequenceData. 00305 * 00306 * There are four possible return 'states' from this function: 00307 * 00308 * - handle is not available or cannot be allocated with specified 00309 * values_per_ent. Returned error code is MB_ALREADY_ALLOCATED. 00310 * 00311 * - handle can be appended or prepended to an existing sequence. 00312 * seq_ptr_out is set to the sequence the handle should be added to. 00313 * 00314 * - handle cannot be appended to an existing sequence but falls 00315 * within an existing SequenceData. The caller is expected 00316 * to create a new sequence referencing that SequenceData. seq_ptr_out 00317 * is NULL and data_ptr_out is set to existing SequenceData. 00318 * 00319 * - handle does not correspond to any existing sequence or data. 00320 * The caller is expected to create a new sequence and SequenceData. 00321 * Both seq_ptr_out and data_ptr_out are set to NULL. 00322 * block_start and block_end are set to start and end handles of the 00323 * largest sequence that can be allocated and contain the input handle. 00324 * 00325 *\param handle The handle the caller wishes to allocate as a new entity 00326 *\param seq_ptr_out Output: pointer to sequence to append or prepend to 00327 * to allocate handle. end() if no such sequence. 00328 *\param data_ptr_out Output: Pointer to existing SequenceData containing input 00329 * handle, or NULL if no such SequenceData. 00330 *\param block_start Output: Smallest possible start handle for new sequence. 00331 *\param block_end Output: Largest possible end handle for new sequence. 00332 */ 00333 ErrorCode is_free_handle( EntityHandle handle, 00334 iterator& seq_ptr_out, 00335 SequenceData*& data_ptr_out, 00336 EntityHandle& block_start, 00337 EntityHandle& block_end, 00338 int values_per_ent = 0 ); 00339 00340 EntityHandle last_free_handle( EntityHandle after_this ) const; 00341 00342 /**\brief Notify that sequence was prepended to 00343 * 00344 * Notify of sequence modifications so we can check if 00345 * sequence needs to be merged. 00346 */ 00347 ErrorCode notify_prepended( iterator seq ); 00348 00349 /**\brief Notify that sequence was appended to 00350 * 00351 * Notify of sequence modifications so we can check if 00352 * sequence needs to be merged. 00353 */ 00354 ErrorCode notify_appended( iterator seq ); 00355 00356 void get_memory_use( unsigned long long& total_entity_storage, unsigned long long& total_storage ) const; 00357 00358 void get_memory_use( EntityHandle start, 00359 EntityHandle end, 00360 unsigned long long& total_entity_storage, 00361 unsigned long long& total_amortized_storage ) const; 00362 00363 unsigned long get_sequence_count() const 00364 { 00365 return sequenceSet.size(); 00366 } 00367 00368 /**\brief Get used size of SequenceData 00369 * 00370 * Get the sum of the size of all EntitySequences referencing 00371 * a SequenceData. Used for memory use calculations. 00372 */ 00373 EntityID get_occupied_size( const SequenceData* ) const; 00374 }; 00375 00376 inline EntitySequence* TypeSequenceManager::find( EntityHandle h ) const 00377 { 00378 if( !lastReferenced ) // only null if empty 00379 return 0; 00380 else if( h >= lastReferenced->start_handle() && h <= lastReferenced->end_handle() ) 00381 return lastReferenced; 00382 else 00383 { 00384 DummySequence seq( h ); 00385 const_iterator i = sequenceSet.find( &seq ); 00386 return i == end() ? 0 : ( lastReferenced = *i ); 00387 } 00388 } 00389 inline EntitySequence* TypeSequenceManager::find( EntityHandle h ) 00390 { 00391 if( !lastReferenced ) // only null if empty 00392 return 0; 00393 else if( h >= lastReferenced->start_handle() && h <= lastReferenced->end_handle() ) 00394 return lastReferenced; 00395 else 00396 { 00397 DummySequence seq( h ); 00398 iterator i = sequenceSet.find( &seq ); 00399 return i == end() ? 0 : ( lastReferenced = *i ); 00400 } 00401 } 00402 00403 inline ErrorCode TypeSequenceManager::find( EntityHandle h, const EntitySequence*& seq ) const 00404 { 00405 if( !lastReferenced ) 00406 { // only null if empty 00407 seq = 0; 00408 return MB_ENTITY_NOT_FOUND; 00409 } 00410 00411 seq = lastReferenced; 00412 if( h >= seq->start_handle() && h <= seq->end_handle() ) 00413 { 00414 return MB_SUCCESS; 00415 } 00416 00417 DummySequence ds( h ); 00418 iterator i = sequenceSet.lower_bound( &ds ); 00419 if( i == end() || ( *i )->start_handle() > h ) 00420 { 00421 seq = 0; 00422 return MB_ENTITY_NOT_FOUND; 00423 } 00424 seq = *i; 00425 lastReferenced = *i; 00426 return MB_SUCCESS; 00427 } 00428 00429 inline ErrorCode TypeSequenceManager::find( EntityHandle h, EntitySequence*& seq ) 00430 { 00431 if( !lastReferenced ) 00432 { // only null if empty 00433 seq = 0; 00434 return MB_ENTITY_NOT_FOUND; 00435 } 00436 00437 seq = lastReferenced; 00438 if( h >= seq->start_handle() && h <= seq->end_handle() ) 00439 { 00440 return MB_SUCCESS; 00441 } 00442 00443 DummySequence ds( h ); 00444 iterator i = sequenceSet.lower_bound( &ds ); 00445 if( i == end() || ( *i )->start_handle() > h ) 00446 { 00447 seq = 0; 00448 return MB_ENTITY_NOT_FOUND; 00449 } 00450 seq = *i; 00451 lastReferenced = *i; 00452 return MB_SUCCESS; 00453 } 00454 00455 inline const EntitySequence* TypeSequenceManager::get_last_accessed() const 00456 { 00457 return lastReferenced; /* only NULL if TypeSequenceManager is empty */ 00458 } 00459 00460 inline void TypeSequenceManager::get_entities( Range& entities_out ) const 00461 { 00462 Range::iterator in = entities_out.begin(); 00463 for( const_iterator i = begin(); i != end(); ++i ) 00464 in = entities_out.insert( in, ( *i )->start_handle(), ( *i )->end_handle() ); 00465 } 00466 00467 inline void TypeSequenceManager::get_entities( std::vector< EntityHandle >& entities_out ) const 00468 { 00469 for( const_iterator i = begin(); i != end(); ++i ) 00470 for( EntityHandle j = ( *i )->start_handle(); j <= ( *i )->end_handle(); ++j ) 00471 entities_out.push_back( j ); 00472 } 00473 00474 inline EntityID TypeSequenceManager::get_number_entities() const 00475 { 00476 EntityID count = 0; 00477 for( const_iterator i = begin(); i != end(); ++i ) 00478 count += ( *i )->size(); 00479 return count; 00480 } 00481 00482 } // namespace moab 00483 00484 #endif