From db549e73be33d02a8965720c0406dedc10331eb9 Mon Sep 17 00:00:00 2001 From: Nicola Baldo Date: Fri, 26 Oct 2012 14:10:40 +0200 Subject: [PATCH] make MultiModelSpectrumChannel support SpectrumModel changes at run time --- CHANGES.html | 2 + .../model/multi-model-spectrum-channel.cc | 67 ++++++++++++++----- .../model/multi-model-spectrum-channel.h | 34 +++------- 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/CHANGES.html b/CHANGES.html index 5375fad3f..08cbb2b75 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -64,6 +64,8 @@ us a note on ns-developers mailing list.

Changed behavior:


diff --git a/src/spectrum/model/multi-model-spectrum-channel.cc b/src/spectrum/model/multi-model-spectrum-channel.cc index 6e6b9ce29..da4125ad5 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.cc +++ b/src/spectrum/model/multi-model-spectrum-channel.cc @@ -91,7 +91,6 @@ MultiModelSpectrumChannel::DoDispose () m_spectrumPropagationLoss = 0; m_txSpectrumModelInfoMap.clear (); m_rxSpectrumModelInfoMap.clear (); - m_phyVector.clear (); SpectrumChannel::DoDispose (); } @@ -142,12 +141,24 @@ MultiModelSpectrumChannel::AddRx (Ptr phy) std::vector >::const_iterator it; - // make sure this phy had not been already added - for ( it = m_phyVector.begin (); it != m_phyVector.end (); ++it) + // remove a previous entry of this phy if it exists + // we need to scan for all rxSpectrumModel values since we don't + // know which spectrum model the phy had when it was previously added + // (it's probably different than the current one) + for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin (); + rxInfoIterator != m_rxSpectrumModelInfoMap.end (); + ++rxInfoIterator) { - NS_ASSERT (*it != phy); + std::set >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy); + if (phyIt != rxInfoIterator->second.m_rxPhySet.end ()) + { + rxInfoIterator->second.m_rxPhySet.erase (phyIt); + --m_numDevices; + break; // there should be at most one entry + } } - m_phyVector.push_back (phy); + + ++m_numDevices; RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid); @@ -157,8 +168,9 @@ MultiModelSpectrumChannel::AddRx (Ptr phy) std::pair ret; ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel))); NS_ASSERT (ret.second); - // also add the phy to the newly created list of SpectrumPhy for this RxSpectrumModel - ret.first->second.m_rxPhyList.push_back (phy); + // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel + std::pair >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy); + NS_ASSERT (ret2.second); // and create the necessary converters for all the TX spectrum models that we know of for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin (); @@ -176,7 +188,8 @@ MultiModelSpectrumChannel::AddRx (Ptr phy) else { // spectrum model is already known, just add the device to the corresponding list - rxInfoIterator->second.m_rxPhyList.push_back (phy); + std::pair >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy); + NS_ASSERT (ret2.second); } } @@ -224,6 +237,7 @@ MultiModelSpectrumChannel::FindAndEventuallyAddTxSpectrumModel (Ptr txParams) @@ -268,14 +282,12 @@ MultiModelSpectrumChannel::StartTx (Ptr txParams) } - for (std::list >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin (); - rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end (); + for (std::set >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin (); + rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end (); ++rxPhyIterator) { NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid, - "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation"); - - + "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)"); if ((*rxPhyIterator) != txParams->txPhy) { @@ -364,7 +376,7 @@ MultiModelSpectrumChannel::StartRx (Ptr params, Ptr MultiModelSpectrumChannel::GetDevice (uint32_t i) const { - return m_phyVector.at (i)->GetDevice (); + NS_ASSERT (i < m_numDevices); + // this method implementation is computationally intensive. This + // method would be faster if we actually used a std::vector for + // storing devices, which we don't due to the need to have fast + // SpectrumModel conversions and to allow PHY devices to changea + // SpectrumModel at run time. Note that having this method slow is + // acceptable as it is not used much at run time (often not at all). + // On the other hand, having slow SpectrumModel conversion would be + // less acceptable. + uint32_t j = 0; + for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin (); + rxInfoIterator != m_rxSpectrumModelInfoMap.end (); + ++rxInfoIterator) + { + for (std::set >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin (); + phyIt != rxInfoIterator->second.m_rxPhySet.end (); + ++phyIt) + { + if (j == i) + { + return (*phyIt)->GetDevice (); + } + } + } + NS_FATAL_ERROR ("m_numDevice > actual number of devices"); + return 0; } diff --git a/src/spectrum/model/multi-model-spectrum-channel.h b/src/spectrum/model/multi-model-spectrum-channel.h index 6c40e7f44..7e4095058 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.h +++ b/src/spectrum/model/multi-model-spectrum-channel.h @@ -28,7 +28,7 @@ #include #include #include -#include +#include namespace ns3 { @@ -62,7 +62,7 @@ public: RxSpectrumModelInfo (Ptr rxSpectrumModel); Ptr m_rxSpectrumModel; - std::list > m_rxPhyList; + std::set > m_rxPhySet; }; typedef std::map RxSpectrumModelInfoMap_t; @@ -75,9 +75,13 @@ typedef std::map RxSpectrumModelInfoMap * * This SpectrumChannel implementation can handle the presence of * SpectrumPhy instances which can use - * different spectrum models, i.e., different SpectrumModel. The only - * requirement is that every SpectrumPhy instance uses the same - * SpectrumModel for the whole simulation. + * different spectrum models, i.e., different SpectrumModel. + * + * \note It is allowed for a receiving SpectrumPhy to switch to a + * different SpectrumModel during the simulation. The requirement + * for this to work is that, after the SpectrumPhy switched its + * SpectrumModel, MultiModelSpectrumChannel::AddRx () is + * called again passing the pointer to that SpectrumPhy. */ class MultiModelSpectrumChannel : public SpectrumChannel { @@ -120,18 +124,6 @@ private: */ TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel (Ptr txSpectrumModel); - - /** - * make sure that there are SpectrumConverters from any - * SpectrumPhy being used for TX to the given SpectrumModel being used for RX - * - * @param rxPhy the RXing SpectrumPhy - * @param rxSpectrumModel the SpectrumModel used for RX by rxPhy - */ - void CheckAddRxSpectrumModel (Ptr rxPhy, Ptr rxSpectrumModel); - - - /** * used internally to reschedule transmission after the propagation delay * @@ -177,13 +169,7 @@ private: */ RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap; - /** - * this is only used to provide a straighforward implementation of - * GetNDevices() and GetDevice() - * - */ - std::vector > m_phyVector; - + uint32_t m_numDevices; double m_maxLossDb;