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
|