ChannelInfo.h

00001 #ifndef CHANNELINFO_H_
00002 #define CHANNELINFO_H_
00003 
00004 #include <list>
00005 #include <omnetpp.h>
00006 #include "AirFrame_m.h"
00007 
00042 class ChannelInfo {
00043 
00044 protected:
00045 
00047   typedef std::pair<simtime_t, AirFrame*> AirFrameTimePair;
00049   typedef std::list<AirFrameTimePair> AirFrameTimeList;
00054   typedef std::map<simtime_t, AirFrameTimeList > AirFrameMatrix;
00055 
00079   template<class C, class ItMatrix, class ItList>
00080   class BaseIntersectionIterator
00081   {
00082   public:
00084     C* intervals;
00085 
00087     simtime_t from;
00088 
00090     simtime_t to;
00091 
00093     ItMatrix endIt;
00094 
00096     ItList startIt;
00097 
00099     bool alreadyNext;
00100 
00101   public:
00102 
00107     BaseIntersectionIterator(C* airFrames, simtime_t from, simtime_t to) :
00108       intervals(airFrames), from(from), to(to)
00109     {
00110       // begin at the smallest end-time-entry fulfilling the intersection
00111       // condition 1
00112       endIt = intervals->lower_bound(from);
00113 
00114       if(endIt != intervals->end()) {
00115         startIt = endIt->second.begin();
00116       }
00117       //we are already pointing at the first unchecked interval
00118       alreadyNext = true;
00119     }
00120 
00125     AirFrame* next()
00126     {
00127       if(endIt == intervals->end())
00128         return 0;
00129 
00130       // "alreadyNext" indicates that some previous iterator function has
00131       // already increased the intern iterators to a yet unchecked values.
00132       // This happens after initialization of the iterator and when an
00133       // element is erased.
00134       if(alreadyNext)
00135         alreadyNext = false;
00136       else
00137         startIt++;
00138 
00139 
00140       while(endIt != intervals->end())
00141       {
00142         // while there are entries left at the current end-time
00143         while(startIt != endIt->second.end())
00144         {
00145           // check if this entry fulfilles the intersection condition
00146           // 2 (condition 1 is already fulfilled in the constructor by
00147           // the start-value of the end-time-iterator)
00148           if(startIt->first <= to) {
00149             return startIt->second;
00150           }
00151           startIt++;
00152         }
00153 
00154         endIt++;
00155         if(endIt == intervals->end())
00156           return 0;
00157 
00158         startIt = endIt->second.begin();
00159 
00160       }
00161 
00162       return 0;
00163     }
00164   };
00165 
00167   typedef BaseIntersectionIterator
00168         <const AirFrameMatrix,
00169          AirFrameMatrix::const_iterator,
00170          AirFrameTimeList::const_iterator> ConstIntersectionIterator;
00171 
00177   class IntersectionIterator:
00178       public BaseIntersectionIterator<AirFrameMatrix,
00179                       AirFrameMatrix::iterator,
00180                       AirFrameTimeList::iterator>
00181   {
00182   private:
00184     typedef BaseIntersectionIterator<AirFrameMatrix,
00185                      AirFrameMatrix::iterator,
00186                      AirFrameTimeList::iterator> Base;
00187   public:
00192     IntersectionIterator(AirFrameMatrix* airFrames,
00193                simtime_t from,
00194                simtime_t to) :
00195       Base(airFrames, from, to)
00196     {}
00197 
00205     void eraseAirFrame()
00206     {
00207       assert(endIt != intervals->end());
00208       assert(startIt != endIt->second.end());
00209 
00210       //erase AirFrame from list
00211       startIt = endIt->second.erase(startIt);
00212 
00213       //check if we've deleted the last entry in the list
00214       if(startIt == endIt->second.end())
00215       {
00216         //check if we deleted the only entry in the list
00217         if(endIt->second.empty()) {
00218           intervals->erase(endIt++); //delete list from map
00219         } else {
00220           endIt++;
00221         }
00222 
00223         //increase to a valid value if we are not done
00224         if(endIt != intervals->end()) {
00225           startIt = endIt->second.begin();
00226         }
00227       }
00228       alreadyNext = true;
00229     }
00230   };
00231 
00237   AirFrameMatrix activeAirFrames;
00238 
00245   AirFrameMatrix inactiveAirFrames;
00246 
00248   typedef std::map<AirFrame*, simtime_t> AirFrameStartMap;
00249 
00251   AirFrameStartMap airFrameStarts;
00252 
00255   simtime_t earliestInfoPoint;
00256 
00259   simtime_t recordStartTime;
00260 
00261 public:
00267   typedef std::list<AirFrame*> AirFrameVector;
00268 
00269 protected:
00274   void assertNoIntersections();
00275 
00276 
00284   void getIntersections( const AirFrameMatrix& airFrames,
00285                simtime_t from, simtime_t to,
00286                AirFrameVector& outVector) const;
00287 
00292   bool isIntersecting( const AirFrameMatrix& airFrames,
00293              simtime_t from, simtime_t to) const;
00294 
00304   void addToInactives(AirFrame* a, simtime_t startTime, simtime_t endTime);
00305 
00309   void deleteAirFrame(AirFrameMatrix& airFrames,
00310             AirFrame* a,
00311             simtime_t startTime, simtime_t endTime);
00312 
00316   simtime_t findEarliestInfoPoint();
00317 
00328   void checkAndCleanInterval(simtime_t startTime, simtime_t endTime);
00329 
00342   bool canDiscardInterval(simtime_t startTime, simtime_t endTime);
00343 
00350   void checkAndCleanFrom(simtime_t start) {
00351     //nothing to do
00352     if(inactiveAirFrames.empty())
00353       return;
00354 
00355     //take last ended inactive airframe as end of interval
00356     checkAndCleanInterval(start, inactiveAirFrames.rbegin()->first);
00357   }
00358 
00359 public:
00360   ChannelInfo():
00361     earliestInfoPoint(-1),
00362     recordStartTime(-1)
00363   {}
00364 
00365   virtual ~ChannelInfo() {}
00366 
00375   void addAirFrame(AirFrame* a, simtime_t startTime);
00376 
00385   simtime_t removeAirFrame(AirFrame* a);
00386 
00397   void getAirFrames(simtime_t from, simtime_t to, AirFrameVector& out) const;
00398 
00403   simtime_t getEarliestInfoPoint()
00404   {
00405     assert(!isChannelEmpty() || earliestInfoPoint == -1);
00406 
00407     return earliestInfoPoint;
00408   }
00409 
00424   void startRecording(simtime_t start)
00425   {
00426     // clean up until old record start
00427     if(recordStartTime > -1) {
00428       recordStartTime = start;
00429       checkAndCleanInterval(0, recordStartTime);
00430     } else {
00431       recordStartTime = start;
00432     }
00433   }
00434 
00441   void stopRecording()
00442   {
00443     if(recordStartTime > -1) {
00444       simtime_t old = recordStartTime;
00445       recordStartTime = -1;
00446       checkAndCleanFrom(old);
00447     }
00448   }
00449 
00454   bool isRecording() const
00455   {
00456     return recordStartTime > -1;
00457   }
00458 
00463   bool isChannelEmpty() const {
00464     assert(recordStartTime != -1
00465          || activeAirFrames.empty() == airFrameStarts.empty());
00466 
00467     return airFrameStarts.empty();
00468   }
00469 };
00470 
00471 #endif /*CHANNELINFO_H_*/