MiXiM  2.3
ChannelInfo.h
00001 #ifndef CHANNELINFO_H_
00002 #define CHANNELINFO_H_
00003 
00004 #include <list>
00005 #include <map>
00006 #include <omnetpp.h>
00007 
00008 #include "MiXiMDefs.h"
00009 #include "MiXiMAirFrame.h"
00010 
00045 class MIXIM_API ChannelInfo {
00046 public:
00047     typedef MiximAirFrame  airframe_t;
00049   typedef airframe_t*    airframe_ptr_t;
00051   static const_simtime_t invalidSimTime;
00052 
00055   struct airframe_filter_fctr {
00056     virtual ~airframe_filter_fctr() {}
00057 
00062     virtual bool pass(const airframe_ptr_t& a) const {
00063       return true;
00064     }
00065     };
00066 protected:
00071   typedef std::map<simtime_t, std::multimap<simtime_t, airframe_ptr_t> > AirFrameMatrix;
00072 
00073   struct c_min_start_time_fctr {
00074     bool operator() (const AirFrameMatrix::value_type& a, const AirFrameMatrix::value_type& b) {
00075       return a.second.key_comp()(a.second.begin()->first, b.second.begin()->first);
00076     }
00077   };
00078 
00102   template<typename C, typename ItMatrix = typename C::const_iterator, typename ItSubMatrix = typename C::mapped_type::const_iterator>
00103   class BaseIntersectionIterator
00104   {
00105   public:
00106     typedef typename ItSubMatrix::value_type value_type;
00107     typedef typename ItSubMatrix::reference  reference;
00108     typedef typename ItSubMatrix::pointer    pointer;
00109 
00110     typedef BaseIntersectionIterator<C, ItMatrix, ItSubMatrix> iterator;
00111 
00112     typedef std::bidirectional_iterator_tag iterator_category;
00113     typedef ptrdiff_t                       difference_type;
00114 
00115   protected:
00116     friend class ChannelInfo;
00117     typedef BaseIntersectionIterator<C, ItMatrix, ItSubMatrix> _Self;
00118     //typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr;
00119     //typedef const _Rb_tree_node<_Tp>*           _Link_type;
00120 
00122     C* intervals;
00123 
00125     simtime_t_cref from;
00126 
00128     simtime_t_cref to;
00129 
00131     ItMatrix endIt;
00132 
00134     ItSubMatrix startIt;
00135     ItSubMatrix startItEnd;
00136 
00141       _Self& jumpToNextValid(ItMatrix endItEnd)
00142       {
00143       for (; endIt != endItEnd; startIt = endIt->second.begin()) {
00144         // while there are entries left at the current end-time
00145         if (startIt != startItEnd) {
00146           // check if this entry fulfills the intersection condition
00147           // 2 (condition 1 is already fulfilled in the constructor by
00148           // the start-value of the end-time-iterator)
00149           return *this;
00150         }
00151         if (++endIt != endItEnd) {
00152           startItEnd = endIt->second.upper_bound(to);
00153         }
00154       }
00155 
00156       intervals = NULL;
00157       return *this;
00158       }
00159   public:
00164     BaseIntersectionIterator(C* airFrames, simtime_t_cref from, simtime_t_cref to) :
00165       intervals(airFrames), from(from), to(to), endIt(), startIt(), startItEnd()
00166     {
00167       // begin at the smallest end-time-entry fulfilling the intersection
00168       // condition 1
00169       if (intervals) {
00170         endIt = intervals->lower_bound(from);
00171         if(endIt != intervals->end()) {
00172           startIt    = endIt->second.begin();
00173           startItEnd = endIt->second.upper_bound(to);
00174           jumpToNextValid(intervals->end());
00175         }
00176         else {
00177           intervals = NULL;
00178           startIt   = startItEnd;
00179         }
00180       }
00181       else {
00182         startIt = startItEnd;
00183       }
00184       //we are already pointing at the first unchecked interval
00185     }
00186     BaseIntersectionIterator(const iterator& __it) :
00187       intervals(__it.intervals), from(__it.from), to(__it.to), endIt(__it.endIt), startIt(__it.startIt),  startItEnd(__it.startItEnd)
00188     { }
00189 
00190     reference
00191       operator*() const
00192     {
00193       if(intervals == NULL || endIt == intervals->end() || startIt == startItEnd)
00194         return NULL;
00195       return startIt.operator*();
00196     }
00197 
00198     pointer
00199       operator->() const
00200     {
00201       if(intervals == NULL || endIt == intervals->end() || startIt == startItEnd)
00202         return NULL;
00203       return startIt.operator->();
00204     }
00205 
00208     _Self&
00209     operator++()
00210     {
00211       if (!intervals)
00212         return *this;
00213 
00214       const ItMatrix endItEnd = intervals->end();
00215       if(endIt == endItEnd) {
00216         intervals = NULL;
00217         return *this;
00218       }
00219 
00220       if (startIt != startItEnd)
00221         ++startIt;
00222 
00223       return jumpToNextValid(endItEnd);
00224     }
00225 
00228     _Self
00229     operator++(int)
00230       {
00231       _Self __tmp = *this;
00232       ++(*this);
00233       return __tmp;
00234       }
00235 
00238       bool
00239       operator==(const _Self& __x) const
00240       {
00241         if (intervals == NULL) {
00242           if (__x.intervals == NULL)
00243             return true;
00244           return (__x.endIt == __x.intervals->end() || __x.startIt == __x.startItEnd); // we have no next element
00245         }
00246         if (__x.intervals == NULL) {
00247           return (endIt == intervals->end() || startIt == endIt->second.end()); // we have no next element
00248         }
00249         if( (endIt == intervals->end() && __x.endIt == __x.intervals->end()) || (startIt == startItEnd && __x.startIt == __x.startItEnd) )
00250           return true;
00251         return intervals == __x.intervals && from == __x.from && to == __x.to && endIt == __x.endIt && startIt == __x.startIt && startItEnd == __x.startItEnd;
00252       }
00253 
00256       bool
00257       operator!=(const _Self& __x) const
00258       { return !(*this == __x); }
00259   };
00260 
00262   typedef BaseIntersectionIterator<const AirFrameMatrix,
00263                    AirFrameMatrix::const_iterator,
00264                    AirFrameMatrix::mapped_type::const_iterator> const_iterator;
00265 
00267   const static const_iterator cConstItEnd;
00268 
00274   const_iterator end() const {
00275     return cConstItEnd;
00276   }
00277 
00279   typedef BaseIntersectionIterator<AirFrameMatrix,
00280                    AirFrameMatrix::iterator,
00281                    AirFrameMatrix::mapped_type::iterator> iterator;
00282 
00284   const static iterator cItEnd;
00290   iterator end() {
00291     return cItEnd;
00292   }
00293 
00304   void erase(const iterator& __position) {
00305     assert(__position.endIt   != __position.intervals->end());
00306     assert(__position.startIt != __position.startItEnd);
00307 
00308     //erase AirFrame from list
00309     __position.endIt->second.erase(__position.startIt);
00310 
00311     //check if we deleted the only entry in the list
00312     if(__position.endIt->second.empty()) {
00313       __position.intervals->erase(__position.endIt); //delete list from map
00314     }
00315   }
00316 
00322   AirFrameMatrix activeAirFrames;
00323 
00330   AirFrameMatrix inactiveAirFrames;
00331 
00333   typedef std::map<long, simtime_t> AirFrameStartMap;
00334 
00336   AirFrameStartMap airFrameStarts;
00337 
00340   simtime_t recordStartTime;
00341 
00342 public:
00348   typedef std::list<airframe_ptr_t> AirFrameVector;
00349 
00350 protected:
00355   void assertNoIntersections() const;
00356 
00357 
00365   static void getIntersections( const AirFrameMatrix&     airFrames
00366                                 , simtime_t_cref            from
00367                                 , simtime_t_cref            to
00368                                 , AirFrameVector&           outVector
00369                                 , airframe_filter_fctr *const fctrFilter = NULL)
00370   {
00371       const_iterator itEnd = cConstItEnd;
00372       for (const_iterator it(&airFrames, from, to); it != itEnd; ++it) {
00373           if (fctrFilter != NULL) {
00374               if (!fctrFilter->pass(it->second))
00375                   continue;
00376           }
00377           outVector.push_back(it->second);
00378       }
00379   }
00380 
00385   static bool isIntersecting( const AirFrameMatrix& airFrames,
00386                               simtime_t_cref from, simtime_t_cref to );
00387 
00397   void addToInactives(airframe_ptr_t a, simtime_t_cref startTime, simtime_t_cref endTime);
00398 
00402   static void deleteAirFrame(AirFrameMatrix& airFrames,
00403                              airframe_ptr_t  a,
00404                              simtime_t_cref  startTime, simtime_t_cref endTime);
00405 
00409   simtime_t findEarliestInfoPoint(simtime_t_cref returnTimeIfEmpty = invalidSimTime) const;
00410 
00421   void checkAndCleanInterval(simtime_t_cref startTime, simtime_t_cref endTime);
00422 
00435   bool canDiscardInterval(simtime_t_cref startTime, simtime_t_cref endTime);
00436 
00443   void checkAndCleanFrom(simtime_t_cref start) {
00444     //nothing to do
00445     if(inactiveAirFrames.empty())
00446       return;
00447 
00448     //take last ended inactive airframe as end of interval
00449     checkAndCleanInterval(start, inactiveAirFrames.rbegin()->first);
00450   }
00451 
00452 public:
00453   ChannelInfo()
00454     : activeAirFrames()
00455     , inactiveAirFrames()
00456     , airFrameStarts()
00457     , recordStartTime(invalidSimTime)
00458   {}
00459 
00460   virtual ~ChannelInfo() {}
00461 
00470   void addAirFrame(airframe_ptr_t a, simtime_t_cref startTime);
00471 
00480   simtime_t removeAirFrame(airframe_ptr_t a, simtime_t_cref returnTimeIfEmpty = invalidSimTime);
00481 
00492   void getAirFrames( simtime_t_cref            from
00493                      , simtime_t_cref            to
00494                      , AirFrameVector&           out
00495                      , airframe_filter_fctr *const fctrFilter = NULL) const
00496   {
00497       //check for intersecting inactive AirFrames
00498       getIntersections(inactiveAirFrames, from, to, out, fctrFilter);
00499 
00500       //check for intersecting active AirFrames
00501       getIntersections(activeAirFrames, from, to, out, fctrFilter);
00502   }
00503 
00508   simtime_t getEarliestInfoPoint(simtime_t_cref returnTimeIfEmpty = invalidSimTime) const
00509   {
00510     return findEarliestInfoPoint(returnTimeIfEmpty);
00511   }
00512 
00527   void startRecording(simtime_t_cref start)
00528   {
00529     // clean up until old record start
00530     if(recordStartTime >= SIMTIME_ZERO) {
00531       recordStartTime = start;
00532       checkAndCleanInterval(0, recordStartTime);
00533     } else {
00534       recordStartTime = start;
00535     }
00536   }
00537 
00544   void stopRecording()
00545   {
00546     if(recordStartTime >= SIMTIME_ZERO) {
00547       simtime_t old = recordStartTime;
00548       recordStartTime = invalidSimTime;
00549       checkAndCleanFrom(old);
00550     }
00551   }
00552 
00557   bool isRecording() const
00558   {
00559     return recordStartTime >= SIMTIME_ZERO;
00560   }
00561 
00566   bool isChannelEmpty() const {
00567     return airFrameStarts.empty();
00568   }
00569 };
00570 
00571 #endif /*CHANNELINFO_H_*/