MiXiM
2.3
|
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_*/