LCOV - code coverage report
Current view: top level - ugbase/pcl - pcl_communication_structs.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 11 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 24 0

            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 __H__PCL__PCL_COMMUNICATION_STRUCTS__
      34              : #define __H__PCL__PCL_COMMUNICATION_STRUCTS__
      35              : 
      36              : #include <iterator>
      37              : #include <vector>
      38              : #include <list>
      39              : #include <map>
      40              : #include <algorithm>
      41              : #include "common/util/smart_pointer.h"
      42              : #include "common/util/binary_buffer.h"
      43              : #include "common/error.h"
      44              : 
      45              : namespace pcl
      46              : {
      47              : 
      48              : /// \addtogroup pcl
      49              : /// \{
      50              : 
      51              : ////////////////////////////////////////////////////////////////////////
      52              : //      type-traits
      53              : ///     associate internally used types with an external typename
      54              : /**
      55              :  * By default it is assumed, that the external typename and the element
      56              :  * type used in interfaces match.
      57              :  *
      58              :  * You may specialize type_traits for your own types through template
      59              :  * specialization. Be sure to specialize them before you use any
      60              :  * pcl-classes with your type.
      61              :  */
      62              : template <class TType>
      63              : struct type_traits
      64              : {
      65              :         typedef TType Elem;     ///     Type of interface elements
      66              : };
      67              : 
      68              : 
      69              : ////////////////////////////////////////////////////////////////////////
      70              : //      Interface Categories
      71              : ///     Interface tags allow to differentiate between interfaces with different features
      72              : namespace interface_tags
      73              : {
      74              : /**     Every interface has to feature this tag (at least indirectly - by tag-derivation).
      75              :  *      This tag simply says that one may iterate over the elements of the
      76              :  *      interface.
      77              :  *
      78              :  *      Additionally you may receive the local_src_id. This id represents the
      79              :  *      sender during local communication (communication on one process only).
      80              :  *      Values < 0 mark the sender as invalid (during local communication).
      81              :  *      The src-id is ignored during parallel communication. Instead pcl::ProcRank
      82              :  *      is used.
      83              :  *
      84              :  *      typedefs that have to be featured in such interfaces:
      85              :  *              - category_tag
      86              :  *              - iterator
      87              :  *              - const_iterator
      88              :  *              - Type
      89              :  *              - Element
      90              :  *
      91              :  *      Methods that have to be featured in such interfaces:
      92              :  *              - iterator begin();
      93              :  *              - iterator end();
      94              :  *              - const_iterator begin() const;
      95              :  *              - const_iterator end() const;
      96              :  *              - Element& get_element(iterator iter);
      97              :  *              - const Element& get_element(iterator iter) const;
      98              :  *              - int get_target_proc();
      99              :  *              - void swap(Interface& interface);
     100              :  */
     101              : class basic_interface_tag                                                                       {};
     102              : 
     103              : /**     The ordered_interface_tag derives from the basic_interface_tag.
     104              :  *      Thus all classes and methods that may operate on interfaces
     105              :  *      with the basic_interface_tag will operate on interfaces with
     106              :  *      this tag, too.
     107              :  *
     108              :  *      Interfaces with this category have to associated a local id with
     109              :  *      each entry.
     110              :  *
     111              :  *      Methods that have to be featured in such interfaces:
     112              :  *              - get_local_id(iterator iter);
     113              :  */
     114              : class ordered_interface_tag : public basic_interface_tag        {};
     115              : }//     end of namespace interface_tags
     116              : 
     117              : 
     118              : ////////////////////////////////////////////////////////////////////////
     119              : //      BasicInterface
     120              : ///     You may add elements to this interface and iterate over them
     121              : /**
     122              :  * This interface type features a minimal set of methods that is
     123              :  * required to actually work with it.
     124              :  * You may add new elements, erase old ones and iterate through them.
     125              :  *
     126              :  * In order to access the associated element of an iterator you should
     127              :  * use get_element (not the * operator of the iterator). This increases
     128              :  * the flexibility of your code.
     129              :  *
     130              :  * You may specify a stl-container compatible type that is used to store.
     131              :  * the elements. Supported types are std::vector and std::list.
     132              :  *
     133              :  * TContainer defaults to std::vector. This is the best option if your
     134              :  * interface is mainly used static or grows, but is considerably slower
     135              :  * than std::list if you want to erase elements often.
     136              :  * For dynamic interfaces std::list may be the better option.
     137              :  */
     138              : template <class TType,
     139              :                   template <class T, class Alloc> class TContainer = std::vector,
     140              :                   template <class T> class TAlloc = std::allocator>
     141              : class BasicInterface
     142              : {
     143              :         protected:
     144              :                 typedef typename type_traits<TType>::Elem         TElem;
     145              :                 typedef TContainer<TElem, TAlloc<TElem> >           ElemContainer;
     146              : 
     147              :         public:
     148              :                 typedef interface_tags::basic_interface_tag             category_tag;
     149              : 
     150              :                 typedef TType                                                                   Type;
     151              :                 typedef typename type_traits<TType>::Elem         Element;
     152              :                 typedef typename ElemContainer::iterator                iterator;
     153              :                 typedef typename ElemContainer::const_iterator  const_iterator;
     154              : 
     155              :         public:
     156              :                 BasicInterface(int targetProc = -1)     : m_size(0), m_targetProc(targetProc)   {};
     157              : 
     158              :                 inline iterator push_back(const Element& elem)      {++m_size; return m_elements.insert(m_elements.end(), elem);}
     159              :                 inline iterator erase(iterator iter)                            {--m_size; return m_elements.erase(iter);}
     160              : 
     161              :                 inline iterator begin()         {return m_elements.begin();}
     162              :                 inline iterator end()           {return m_elements.end();}
     163              :                 inline const_iterator begin() const             {return m_elements.begin();}
     164              :                 inline const_iterator end() const               {return m_elements.end();}
     165              : 
     166              :                 inline Element& get_element(iterator iter)                                          {return *iter;}
     167              :                 inline const Element& get_element(const_iterator iter) const        {return *iter;}
     168              : 
     169              :         ///     returns the number of elements that are stored in the interface.
     170              :                 inline size_t size() const                                      {return m_size;}
     171              :                 inline bool empty() const                                       {return size() == 0;}
     172              : 
     173              :                 int get_target_proc() const                                     {return m_targetProc;}
     174              : 
     175              :         ///     swaps the content of two interfaces.
     176              :         /** m_elements, m_size and m_targetProc are swapped.*/
     177              :                 void swap(BasicInterface& interface)
     178              :                 {
     179              :                         using std::swap;
     180              :                         m_elements.swap(interface.m_elements);
     181              :                         swap(m_size, interface.m_size);
     182              :                         swap(m_targetProc, interface.m_targetProc);
     183              :                 }
     184              : 
     185              :         ///     sort the entries in this interface.
     186              :                 template <class TCompare>
     187              :                 void sort(TCompare cmp)
     188              :                 {
     189              :                         using std::sort;
     190              :                         m_elements.sort(cmp);
     191              :                 }
     192              : 
     193              :         protected:
     194              :                 ElemContainer   m_elements;
     195              :                 size_t                  m_size;
     196              :                 int                             m_targetProc;
     197              : };
     198              : 
     199              : ////////////////////////////////////////////////////////////////////////
     200              : //      OrderedInterface
     201              : ///     You may add elements to this interface and iterate over them
     202              : /**     You may retrieve a localID for each element in the interface*/
     203              : template <class TType,
     204              :                   template <class T, class Alloc> class TContainer = std::vector,
     205              :                   template <class T> class TAlloc = std::allocator>
     206              : class OrderedInterface
     207              : {
     208              :         protected:
     209              :                 typedef typename type_traits<TType>::Elem TElem;
     210              : 
     211              :                 struct InterfaceEntry
     212              :                 {
     213              :                         InterfaceEntry(TElem e, size_t locID) : elem(e), localID(locID) {}
     214              : 
     215              :                         TElem   elem;
     216              :                         size_t  localID;
     217              :                 };
     218              : 
     219              :                 template <class TElemCmp>
     220              :                 struct InterfaceEntryCmp{
     221              :                         InterfaceEntryCmp(TElemCmp elemCmp) : m_elemCmp(elemCmp) {}
     222              :                         bool operator()(InterfaceEntry const& e1, InterfaceEntry const& e2)
     223              :                         {return m_elemCmp(e1.elem, e2.elem);}
     224              :                         TElemCmp        m_elemCmp;
     225              :                 };
     226              : 
     227              :                 typedef TContainer<InterfaceEntry, TAlloc<InterfaceEntry> >
     228              :                                                                                                                 ElemContainer;
     229              : 
     230              :         public:
     231              :                 typedef TType                                                                   Type;
     232              :                 typedef typename type_traits<TType>::Elem         Element;
     233              : 
     234              :                 typedef interface_tags::ordered_interface_tag   category_tag;
     235              : 
     236              :                 typedef typename ElemContainer::iterator                iterator;
     237              :                 typedef typename ElemContainer::const_iterator  const_iterator;
     238              : 
     239              :         public:
     240              :                 OrderedInterface(int targetProc = -1) :
     241              :                         m_size(0),
     242              :                         m_targetProc(targetProc),
     243              :                         m_idCounter(1)  {}
     244              : 
     245              :                 inline iterator push_back(const Element& elem)
     246              :                 {
     247              :                         ++m_size;
     248              :                         return m_elements.insert(m_elements.end(),
     249              :                                                                         (InterfaceEntry(elem, get_free_id())));
     250              :                 }
     251              : 
     252              :                 /**
     253              :                  * @brief Insert an element before the passed iterator.
     254              :                  *
     255              :                  * The insertion iterator is best determined using the find_insert_pos_sorted()
     256              :                  * method designed for this purpose.
     257              :                  *
     258              :                  * @return iterator to inserted element
     259              :                  * @note The method is intended for manipulation of the interface
     260              :                  *       after it has been ordered and only suited for a small
     261              :                  *       number of insertions (typically a single insertion).
     262              :                  *       For more insertions, consider push_back() and re-ordering.
     263              :                  * @warning This method is highly experimental. Use with extreme caution!
     264              :                  */
     265              :                 inline iterator insert(const Element& elem, iterator insertBefore)
     266              :                 {
     267              :                         ++m_size;
     268              : 
     269              :                         size_t startNumber = 0;
     270              :                         if (insertBefore != end())
     271              :                                 startNumber = insertBefore->localID;
     272              : 
     273              :                         iterator it = m_elements.insert(insertBefore, (InterfaceEntry(elem, get_free_id())));
     274              : 
     275              :                         if (startNumber)
     276              :                         {
     277              :                                 //      we have to reset all local indices
     278              :                                 --startNumber;
     279              :                                 for (iterator iter = it; iter != m_elements.end(); ++iter)
     280              :                                                 (*iter).localID = ++startNumber;
     281              :                         }
     282              : 
     283              :                         return it;
     284              :                 }
     285              : 
     286              :                 inline iterator erase(iterator iter)
     287              :                 {
     288              :                         --m_size;
     289              :                         return m_elements.erase(iter);
     290              :                 }
     291              : 
     292              :                 inline iterator begin()         {return m_elements.begin();}
     293              :                 inline iterator end()           {return m_elements.end();}
     294              : 
     295              :                 inline const_iterator begin() const {return m_elements.begin();}
     296              :                 inline const_iterator end() const {return m_elements.end();}
     297              : 
     298              :                 inline Element& get_element(iterator iter)  {return (*iter).elem;}
     299              :                 inline size_t get_local_id(iterator iter)       {return (*iter).localID;}
     300              : 
     301              :                 inline const Element& get_element(const_iterator iter) const        {return (*iter).elem;}
     302              :                 inline size_t get_local_id(const_iterator iter) const                   {return (*iter).localID;}
     303              : 
     304              : 
     305              :         ///     returns the number of elements that are stored in the interface.
     306            0 :                 inline size_t size() const                                      {return m_size;}
     307              :                 inline bool empty()     const                                   {return size() == 0;}
     308              : 
     309              :                 int get_target_proc() const                                     {return m_targetProc;}
     310              : 
     311              :         ///     returns true if iter1 < iter2.
     312              :                 static inline bool cmp(iterator iter1, iterator iter2,
     313              :                                                                 const std::input_iterator_tag&)
     314              :                 {
     315              :                         return (*iter1).localID < (*iter2).localID;
     316              :                 }
     317              : 
     318              :         ///     swaps the content of two interfaces.
     319              :         /** m_elements, m_size, m_targetProc and m_idCounter are swapped.*/
     320              :                 void swap(OrderedInterface& interface)
     321              :                 {
     322              :                         using std::swap;
     323              :                         m_elements.swap(interface.m_elements);
     324              :                         swap(m_size, interface.m_size);
     325              :                         swap(m_targetProc, interface.m_targetProc);
     326              :                         swap(m_idCounter, interface.m_idCounter);
     327              :                 }
     328              :                 
     329              :         ///     sort the entries in this interface.
     330              :                 template <class TCompare>
     331              :                 void sort(TCompare cmp)
     332              :                 {
     333              :                         using std::sort;
     334              :                         InterfaceEntryCmp<TCompare> ieCmp(cmp);
     335              :                         m_elements.sort(ieCmp);
     336              : 
     337              :                 //      we have to reset all local indices
     338              :                         m_idCounter = 1;
     339              :                         for(iterator iter = m_elements.begin(); iter != m_elements.end(); ++iter)
     340              :                                 (*iter).localID = m_idCounter++;
     341              :                 }
     342              : 
     343              :         /**
     344              :          * @brief find insertion position for an element to be inserted
     345              :          * @return iterator to insertion position if found; end-iterator otherwise
     346              :          * @warning This method implicitly requires the interface to be sorted
     347              :          *          w.r.t. the passed compare object. If it is not, the position
     348              :          *          might not be correct.
     349              :          */
     350              :                 template <class TCompare>
     351              :                 iterator find_insert_pos_sorted(const Element e, TCompare cmp)
     352              :                 {
     353              :                         InterfaceEntryCmp<TCompare> ieCmp(cmp);
     354              :                         iterator it_begin = m_elements.begin();
     355              :                         iterator it_end = m_elements.end();
     356              :                         InterfaceEntry iEntry(e, 0);
     357              :                         return std::lower_bound(it_begin, it_end, iEntry, ieCmp);
     358              :                 }
     359              : 
     360              : 
     361              :         protected:
     362              :         ///     returns a free id in each call.
     363              :         /**     Those ids are not necessarily aligned.*/
     364              :                 size_t get_free_id()
     365              :                 {
     366              :                         if(m_idCounter == 0)
     367              :                         {
     368              :                                 m_idCounter = 1;
     369              :                         //      we have to reset all entries
     370              :                                 for(iterator iter = begin(); iter != end(); ++iter)
     371              :                                         (*iter).localID = m_idCounter++;
     372              :                         }
     373              : 
     374              :                         return m_idCounter++;
     375              :                 }
     376              : 
     377              :         protected:
     378              :                 ElemContainer   m_elements;
     379              :                 size_t m_size;
     380              :                 int m_targetProc;
     381              :                 size_t m_idCounter;
     382              : };
     383              : 
     384              : 
     385              : ////////////////////////////////////////////////////////////////////////
     386              : //      Layout Categories
     387              : ///     Layout tags allow to differentiate between layouts with different features
     388              : namespace layout_tags
     389              : {
     390              : ///     marks a layout as a single-level layout
     391              : /**
     392              :  * Typedefs that have to be supported by a layout with this tag:
     393              :  *              - category_tag
     394              :  *              - iterator
     395              :  *              - Interface
     396              :  *              - Type
     397              :  *              - Element
     398              :  *
     399              :  * Methods that have to be supported by a layout with this tag:
     400              :  *              - iterator begin()
     401              :  *              - iterator end()
     402              :  *              - Interface& interface(iterator iter)
     403              :  *              - int proc_id(iterator iter)
     404              :  *              - iterator erase(iterator iter)
     405              :  *              - int get_local_src_id()
     406              :  */
     407              : class single_level_layout_tag   {};
     408              : 
     409              : ///     marks a layout as a multi-level layout
     410              : /**
     411              :  * Typedefs that have to be supported by a layout with this tag:
     412              :  *              - category_tag
     413              :  *              - iterator
     414              :  *              - Interface
     415              :  *              - Element
     416              :  *
     417              :  * Methods that have to be supported by a layout with this tag:
     418              :  *              - size_t num_levels()
     419              :  *              - iterator begin(size_t level)
     420              :  *              - iterator end(size_t level)
     421              :  *              - Interface& interface(iterator iter)
     422              :  *              - int proc_id(iterator iter)
     423              :  *              - iterator erase(iterator iter, size_t level)
     424              :  *              - int get_local_src_id()
     425              :  */
     426              : class multi_level_layout_tag    {};
     427              : 
     428              : }//     end of namespace layout_tags
     429              : 
     430              : 
     431              : ////////////////////////////////////////////////////////////////////////
     432              : //      SingleLevelLayout
     433              : ///     the standard single-level-layout implementation
     434              : /**
     435              :  * A Layout is a collection of interfaces.
     436              :  * Each interface is associated with a process-id.
     437              :  *
     438              :  * This layout type supports the requirements of the
     439              :  * pcl::layout_tags::single_level_layout_tag category.
     440              :  *
     441              :  * The layout passes its local srcID on to created interfaces.
     442              :  *
     443              :  * Additionally it features methods that allow to add new interfaces
     444              :  *
     445              :  * In order to allow one method to operate both on a SingleLevelLayout
     446              :  * and a MultiLevelLayout, the (size_t level = 0) convenience parameter
     447              :  * has been added to some methods. Those parameters are ignored throughout
     448              :  * the whole implementation.
     449              :  */
     450              : template <class TInterface>
     451              : class SingleLevelLayout
     452              : {
     453              :         public:
     454              :                 SingleLevelLayout()             {}
     455              : 
     456              :         ////////////////////////////////////////////////
     457              :         //      typedefs required by implementation
     458              :         ///     an interface-map is a list of interfaces, each associated with a process id.
     459              :                 typedef std::map<int, TInterface> InterfaceMap;
     460              : 
     461              :         ////////////////////////////////////////////////
     462              :         //      typedefs required by layout-tag
     463              :         ///     Layout category
     464              :                 typedef layout_tags::single_level_layout_tag    category_tag;
     465              : 
     466              :         ///     Interface type
     467              :                 typedef TInterface                                              Interface;
     468              : 
     469              :         ///     Type
     470              :                 typedef typename Interface::Type                Type;
     471              : 
     472              :         ///     Element type
     473              :                 typedef typename Interface::Element             Element;
     474              : 
     475              :         ///     An iterator that allows to iterate over the interfaces stored in the layout.
     476              :                 typedef typename InterfaceMap::iterator                 iterator;
     477              :                 typedef typename InterfaceMap::const_iterator   const_iterator;
     478              : 
     479              :         public:
     480              :         ////////////////////////////////////////////////
     481              :         //      methods required by the layout-tag
     482              : 
     483              :         ///     returns the iterator to the first interface of the layout.
     484              :         /**     You should access the values of this iterator using the methods
     485              :                 Layout::interface and Layout::proc_id.*/
     486              :                 inline iterator begin(size_t level = 0)                                 {return m_interfaceMap.begin();}
     487              :                 inline const_iterator begin(size_t level = 0) const             {return m_interfaceMap.begin();}
     488              : 
     489              :         ///     returns the iterator to the last interface of the layout.
     490              :         /**     You should access the values of this iterator using the methods
     491              :                 Layout::interface and Layout::proc_id.*/
     492              :                 inline iterator end(size_t level = 0)                                   {return m_interfaceMap.end();}
     493              :                 inline const_iterator end(size_t level = 0)     const           {return m_interfaceMap.end();}
     494              : 
     495              :         ///     returns true if the layout has no interfaces.
     496              :         /**     Note that this method only tells whether there are interfaces or not.
     497              :          * To check whether there are any elements use has_interface_elements.
     498              :          */
     499              :                 inline bool empty(size_t level = 0)     const                           {return begin() == end();}
     500              :                 
     501              :         ///     returns 1
     502              :                 inline size_t num_levels() const                                                {return 1;}
     503              :                 
     504              :         ///     returns the interface to the given iterator.
     505              :                 inline Interface& interface(iterator iter)                                          {return iter->second;}
     506              :                 inline const Interface& interface(const_iterator iter) const        {return iter->second;}
     507              : 
     508              :         ///     returns the target process of the interface given in iterator
     509              :                 inline int proc_id(iterator iter) const                                 {return iter->first;}
     510              :                 inline int proc_id(const_iterator iter) const                   {return iter->first;}
     511              : 
     512              :         ///     erases the interface at the given iterator.
     513              :         /**     returns an iterator to the next interface.*/
     514              :                 inline iterator erase(iterator iter, size_t level = 0)
     515              :                         {
     516              :                                 iterator tIter = iter++;
     517              :                                 m_interfaceMap.erase(tIter);
     518              :                                 return iter;
     519              :                         }
     520              :                 
     521              :         ///     clears the layout
     522              :                 void clear()                                                                                    {m_interfaceMap.clear();}
     523              : 
     524              :         ///     returns the interface to the given process.
     525              :         /**     if the queried interface exist, it will be returned.
     526              :          *      If not it will be created.
     527              :          *      The new interfaces localSrcID will be set to the localSrcID of this layout.*/
     528              :                 inline Interface& interface(int procID, size_t level = 0)
     529              :                 {
     530              :                         iterator iter = m_interfaceMap.find(procID);
     531              :                         if(iter != m_interfaceMap.end())
     532              :                                 return iter->second;
     533              :                         return m_interfaceMap.insert(make_pair(procID, Interface(procID))).first->second;
     534              :                 }
     535              : 
     536              :                 inline const Interface& interface(int procID, size_t level = 0) const
     537              :                 {
     538              :                         const_iterator iter = m_interfaceMap.find(procID);
     539              :                         UG_ASSERT(iter != m_interfaceMap.end(), "trying to access an non-existing interface in a constant layout");
     540              :                         return iter->second;
     541              :                 }
     542              : 
     543              :         ///     returns true if an interface to the given procID already exists.
     544              :                 inline bool interface_exists(int procID, size_t level = 0) const
     545              :                         {return m_interfaceMap.find(procID) != m_interfaceMap.end();}
     546              : 
     547              :         ///     returns the sum of the interface sizes
     548              :                 inline size_t num_interface_elements() const
     549              :                 {
     550              :                         size_t sum = 0;
     551              :                         for(const_iterator iter = begin(); iter != end(); ++iter)
     552              :                                 sum += interface(iter).size();
     553              :                         return sum;
     554              :                 }
     555              : 
     556              :         ///     returns true if the layout contains interface elements
     557              :                 inline bool has_interface_elements() const
     558              :                 {
     559              :                         for(iterator iter = begin(); iter != end(); ++iter){
     560              :                                 if(!interface(iter).empty())
     561              :                                         return true;
     562              :                         }
     563              :                         return false;
     564              :                 }
     565              : 
     566              :         /// returns the number of interfaces in the layout
     567              :                 inline size_t num_interfaces(size_t level = 0) const
     568              :                 {
     569              :                         return m_interfaceMap.size();
     570              :                 }
     571              : 
     572              :         ///     sort the entries in all interfaces of this layout
     573              :                 template <class TCompare>
     574              :                 void sort_interface_entries(TCompare cmp)
     575              :                 {
     576              :                         for(iterator iter = begin(); iter != end(); ++iter)
     577              :                                 interface(iter).sort(cmp);
     578              :                 }
     579              : 
     580              :         private:
     581              : /*
     582              :         ///     copy-constructor is not yet implemented
     583              :                 SingleLevelLayout(const SingleLevelLayout& sll);
     584              : 
     585              :         ///     assignement-operator is not yet implemented
     586              :                 SingleLevelLayout& operator = (const SingleLevelLayout& sll);
     587              : */
     588              :         protected:
     589              :         ///     holds the interfaces in a map.
     590              :                 InterfaceMap    m_interfaceMap;
     591              : };
     592              : 
     593              : ////////////////////////////////////////////////////////////////////////
     594              : //      MultiLevelLayout
     595              : ///     the standard multi-level-layout implementation
     596              : /**
     597              :  * A MultiLevelLayout is a collection of interfaces, which are
     598              :  * grouped in different levels.
     599              :  *
     600              :  * Each interface is associated with a process-id.
     601              :  * If the localSrcID of this layout == -1 then, when a new level is
     602              :  * created, it's local srcID is automatically
     603              :  * initialized with the level index. localSrcIDs of interfaces created on
     604              :  * those levels are then initialised with the level index, too.
     605              :  *
     606              :  * If the localSrcID >= 0 it is simply passed on to the level-layouts.
     607              :  *
     608              :  * This layout type supports the requirements of the
     609              :  * pcl::layout_tags::multi_level_layout_tag category.
     610              :  *
     611              :  * Additionally it features methods that allow to add new interfaces.
     612              :  */
     613              : template <class TInterface>
     614              : class MultiLevelLayout
     615              : {
     616              :         public:
     617              :         ////////////////////////////////////////////////
     618              :         //      typedefs required by implementation
     619              :         ///     on each level a single-level-layout is used
     620              :                 typedef SingleLevelLayout<TInterface>             LevelLayout;
     621              : 
     622              :         ////////////////////////////////////////////////
     623              :         //      typedefs required by layout-tag
     624              :         ///     Layout category
     625              :                 typedef layout_tags::multi_level_layout_tag     category_tag;
     626              : 
     627              :         ///     Interface type
     628              :                 typedef TInterface                                                      Interface;
     629              : 
     630              :         ///     Type
     631              :                 typedef typename Interface::Type                        Type;
     632              : 
     633              :         ///     Element type
     634              :                 typedef typename Interface::Element                     Element;
     635              : 
     636              :         ///     An iterator that allows to iterate over the interfaces stored in the layout.
     637              :                 typedef typename LevelLayout::iterator                  iterator;
     638              :                 typedef typename LevelLayout::const_iterator    const_iterator;
     639              : 
     640              :         public:
     641              :                 MultiLevelLayout()                                                              {}
     642              :                 MultiLevelLayout(const MultiLevelLayout& mll)       {assign_layout(mll);}
     643              : 
     644              :                 ~MultiLevelLayout()                                                             {clear();}
     645              : 
     646              :                 MultiLevelLayout& operator = (const MultiLevelLayout& mll)
     647              :                 {
     648              :                         assign_layout(mll);
     649              :                         return *this;
     650              :                 }
     651              : 
     652              :         ////////////////////////////////////////////////
     653              :         //      methods required by the layout-tag
     654              : 
     655              :         ///     returns the iterator to the first interface of the layout in the given level.
     656              :         /**     You should access the values of this iterator using the methods
     657              :          *      Layout::interface and Layout::proc_id.
     658              :          *      Make sure that the level matches the level in the associated end() call.*/
     659            0 :                 inline iterator begin(size_t level)                             {require_level(level); return m_vLayouts[level]->begin();}
     660            0 :                 inline const_iterator begin(size_t level) const {require_level(level); return m_vLayouts[level]->begin();}
     661              : 
     662              :         ///     returns the iterator to the last interface of the layout in the given level.
     663              :         /**     You should access the values of this iterator using the methods
     664              :          *      Layout::interface and Layout::proc_id.
     665              :          *      Make sure that the level matches the level in the associated begin() call.*/
     666            0 :                 inline iterator end(size_t level)                               {require_level(level); return m_vLayouts[level]->end();}
     667            0 :                 inline const_iterator end(size_t level) const   {require_level(level); return m_vLayouts[level]->end();}
     668              : 
     669              :         ///     returns true if the layout has no interfaces on the given level.
     670              :         /**     Note that this method only tells whether there are interfaces or not.
     671              :          * To check whether there are any elements use has_interface_elements.
     672              :          */
     673              :                 inline bool empty(size_t level)                                 {return begin(level) == end(level);}
     674            0 :                 inline bool empty(size_t level) const                   {return begin(level) == end(level);}
     675              : 
     676              :         ///     returns true if the layout has no interfaces.
     677              :         /**     Note that this method only tells whether there are interfaces or not.
     678              :          * To check whether there are any elements use has_interface_elements.
     679              :          */
     680              :                 inline bool empty()     const                                           {for(size_t l = 0; l < num_levels(); ++l){if(!empty(l)) return false;} return true;}
     681              : 
     682              :         ///     returns the interface to the given iterator.
     683              :                 inline Interface& interface(iterator iter)                                          {return iter->second;}
     684              :                 inline const Interface& interface(const_iterator iter) const        {return iter->second;}
     685              : 
     686              :         ///     returns the interface to the given iterator.
     687              :                 inline int proc_id(const_iterator iter) const                                   {return iter->first;}
     688              : 
     689              :         ///     erases the interface at the given iterator on the given level.
     690              :         /**     returns an iterator to the next interface.*/
     691            0 :                 inline iterator erase(iterator iter, size_t level)      {return m_vLayouts[level]->erase(iter);}
     692              :                 
     693              :         ///     returns the number of levels.
     694              :                 inline size_t num_levels()      const                                   {return m_vLayouts.size();}
     695              : 
     696              :         ////////////////////////////////////////////////
     697              :         //      methods that enhance the layout-tag
     698              :         ///     deletes all levels.
     699              :                 void clear()
     700              :                 {
     701              :                         for(size_t i = 0; i < m_vLayouts.size(); ++i)
     702              :                                 delete m_vLayouts[i];
     703              :                         m_vLayouts.clear();
     704              :                 }
     705              : 
     706              :         ///     returns the interface to the given process.
     707              :         /**     if the interface doesn't exist yet, it will be created.*/
     708              :                 inline Interface& interface(int procID, size_t level)                               {require_level(level); return m_vLayouts[level]->interface(procID);}
     709              :                 inline const Interface& interface(int procID, size_t level) const   {require_level(level); return m_vLayouts[level]->interface(procID);}
     710              : 
     711              :         ///     returns true if an interface to the given procID on the given level already exists.
     712              :                 inline bool interface_exists(int procID, size_t level)                  {require_level(level); return m_vLayouts[level]->interface_exists(procID);}
     713              :                 inline bool interface_exists(int procID, size_t level) const    {require_level(level); return m_vLayouts[level]->interface_exists(procID);}
     714              : 
     715              :         ///     returns true if an interface to the given procID already exists.
     716              :                 inline bool interface_exists(int procID)                                {for(size_t i = 0; i < num_levels(); ++i){if(m_vLayouts[i]->interface_exists(procID)) return true;} return false;}
     717              :                 inline bool interface_exists(int procID) const                  {for(size_t i = 0; i < num_levels(); ++i){if(m_vLayouts[i]->interface_exists(procID)) return true;} return false;}
     718              : 
     719              :         ///     returns the layout at the given level.
     720              :         /**     If level >= num_levels() then the layouts in between
     721              :                 will be automatically created.*/
     722              :                 inline LevelLayout& layout_on_level(int level)                              {require_level(level); return *m_vLayouts[level];}
     723            0 :                 inline const LevelLayout& layout_on_level(int level) const  {require_level(level); return *m_vLayouts[level];}
     724              : 
     725              :         ///     returns the sum of the interface sizes
     726              :                 inline size_t num_interface_elements() const
     727              :                 {
     728              :                         size_t sum = 0;
     729              :                         for(size_t lvl = 0; lvl < num_levels(); ++lvl){
     730              :                                 for(iterator iter = begin(lvl); iter != end(lvl); ++iter)
     731              :                                         sum += interface(iter).size();
     732              :                         }
     733              :                         return sum;
     734              :                 }
     735              : 
     736              :         ///     returns true if the layout contains any interface entries
     737              :                 inline bool has_interface_elements() const
     738              :                 {
     739              :                         for(size_t lvl = 0; lvl < num_levels(); ++lvl){
     740              :                                 for(iterator iter = begin(lvl); iter != end(lvl); ++iter){
     741              :                                         if(!interface(iter).empty())
     742              :                                                 return true;
     743              :                                 }
     744              :                         }
     745              :                         return false;
     746              :                 }
     747              : 
     748              :         /// returns the number of interfaces in the layout
     749              :                 inline size_t num_interfaces(size_t level) const
     750              :                 {
     751              :                         return m_vLayouts[level].size();
     752              :                 }
     753              : 
     754              :         ///     sort the entries in all interfaces of this layout
     755              :                 template <class TCompare>
     756              :                 void sort_interface_entries(TCompare cmp)
     757              :                 {
     758              :                         for(size_t lvl = 0; lvl < num_levels(); ++lvl)
     759              :                                 layout_on_level(lvl).sort_interface_entries(cmp);
     760              :                 }
     761              : 
     762              :         protected:
     763              :         ///     adds num new levels.
     764            0 :                 inline void new_levels(size_t num)              {for(size_t i = 0; i < num; ++i) m_vLayouts.push_back(new LevelLayout());}
     765              : 
     766              :         ///     if the required level doesn't exist yet, it will created.
     767            0 :                 inline void require_level(size_t level)                 {if(level >= num_levels()) new_levels(level - num_levels() + 1);}
     768            0 :                 inline void require_level(size_t level) const   {if(level >= num_levels()){UG_THROW("Level too high: " << level << ", while num_levels == " << num_levels());}}
     769              : 
     770              :         ///     clears this layout and then copies all levels from the given layout
     771              :                 void assign_layout(const MultiLevelLayout& mll)
     772              :                 {
     773              :                         clear();
     774              :                         for(size_t i = 0; i < mll.m_vLayouts.size(); ++i)
     775              :                                 m_vLayouts.push_back(new LevelLayout(*mll.m_vLayouts[i]));
     776              :                 }
     777              : 
     778              :         protected:
     779              :                 std::vector<LevelLayout*> m_vLayouts;
     780              : };
     781              : 
     782              : ////////////////////////////////////////////////////////////////////////
     783              : //      ICommunicationPolicy
     784              : ///     specializations are responsible to pack and unpack interface data during communication.
     785              : /**     Make sure that you use the same communication-policy for send and receive operations.
     786              :  *      Otherwise problems regarding buffer-sizes may occur.
     787              :  */
     788              : template <class TLayout>
     789              : class ICommunicationPolicy
     790              : {
     791              :         public:
     792              :                 typedef TLayout                                         Layout;
     793              :                 typedef typename Layout::Interface      Interface;
     794              : 
     795              :                 virtual ~ICommunicationPolicy() {}
     796              : 
     797              :         ////////////////////////////////
     798              :         //      COLLECT AND EXTRACT
     799              :         ///     returns the size of the buffer in bytes, that will be required for interface-communication.
     800              :         /**     Determines the size of the buffer on which the extract and receive methods
     801              :          *      for the given interface will operate.
     802              :          *      If the buffer-size can't be calculated on both sides (sender and receiver)
     803              :          *      this method should return -1. This will lead to an additional communication
     804              :          *      step in which buffer-sizes will be exchanged.
     805              :          *      If the buffer-size can be calculated on both sides, it makes sense to do so,
     806              :          *      since this leads to less communication and overall improved performance.
     807              :          *      The buffer-size has to exactly match the size of required memory. Make sure that you
     808              :          *      completely fill the buffer during collect(...) and that you read all data during
     809              :          *      extract(...).
     810              :          *      The default implementation returns -1.
     811              :          */     
     812              :                 virtual int
     813              :                 get_required_buffer_size(const Interface& interface)        {return -1;}
     814              :                 
     815              :         ////////////////////////////////
     816              :         //      COLLECT
     817              :         ///     signals the beginning of a layout collection.
     818              :         /**     the default implementation returns true and does nothing else.
     819              :          * This method is only called on processes which collect data.*/
     820              :                 virtual bool
     821              :                 begin_layout_collection(const Layout* pLayout)                  {return true;}
     822              : 
     823              :         ///     signals the end of a layout collection
     824              :         /**     the default implementation returns true and does nothing else.
     825              :          * This method is only called on processes which collect data.*/
     826              :                 virtual bool
     827              :                 end_layout_collection(const Layout* pLayout)                    {return true;}
     828              : 
     829              :         ///     should write data which is associated with the interface elements to the buffer.
     830              :                 virtual bool
     831              :                 collect(ug::BinaryBuffer& buff, const Interface& interface) = 0;
     832              : 
     833              :         ////////////////////////////////
     834              :         //      EXTRACT
     835              :         ///     signals the beginning of a layout extraction.
     836              :         /**     the default implementation returns true and does nothing else.
     837              :          * This method is only called on processes which extract data.*/
     838              :                 virtual bool
     839              :                 begin_layout_extraction(const Layout* pLayout)                  {return true;}
     840              : 
     841              :         ///     signals the end of a layout extraction
     842              :         /**     the default implementation returns true and does nothing else.
     843              :          * This method is only called on processes which extract data.*/
     844              :                 virtual bool
     845              :                 end_layout_extraction(const Layout* pLayout)                    {return true;}
     846              : 
     847              :         ///     signals that a new layout-level will now be processed.
     848              :         /**     This is primarily interesting for layout-extraction of multi-level-layouts.
     849              :          *      Before extract is called for the interfaces of one level of a layout,
     850              :          *      begin_level_extraction(level) is called.
     851              :          *      If single-level-layouts are processed, this method is called
     852              :          *      once with level = 0.
     853              :          *      This method is called after begin_layout_extraction and before
     854              :          *      the associated extract calls.*/
     855              :                 virtual void begin_level_extraction(int level)                  {}
     856              : 
     857              :         ///     extract data from the buffer and assigns it to the interface-elements.
     858              :         /**     If this method is called between calls to begin_layout_extraction and
     859              :                 end_layout_extraction, the interface that is passed to this method
     860              :                 belongs to the layout.*/
     861              :                 virtual bool
     862              :                 extract(ug::BinaryBuffer& buff, const Interface& interface) = 0;
     863              : };
     864              : 
     865              : // end group pcl
     866              : /// \}
     867              : 
     868              : }//     end of namespace pcl
     869              : 
     870              : #endif
        

Generated by: LCOV version 2.0-1