OutPort.hxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef __OutPort_hxx__
00023 #define __OutPort_hxx__
00024 
00025 #include "WritingRegion.hxx"
00026 #include <typeinfo>
00027 #include <list>
00028 #include <string>
00029 #include "InPort.hxx"
00030 #include "InPortPublisher.hxx"
00031 
00032 namespace CLAM
00033 {
00034 
00035 class Processing;
00036 
00037 class OutPortBase
00038 {
00039 public:
00040         typedef std::list<InPortBase*> InPortsList;
00041         OutPortBase( const std::string & name = "unnamed out port", Processing * proc = 0 );
00042         virtual ~OutPortBase();
00043         const std::string & GetName();
00044         Processing * GetProcessing();
00045         InPortsList::iterator BeginVisuallyConnectedInPorts();
00046         InPortsList::iterator EndVisuallyConnectedInPorts();
00047         
00048         virtual void ConnectToIn(InPortBase& in) = 0;
00049         virtual void DisconnectFromIn(InPortBase & in) = 0;
00050         virtual void DisconnectFromAll()=0;
00051         virtual bool IsVisuallyConnectedTo(InPortBase & in) = 0;
00052         virtual bool IsConnectableTo(InPortBase & ) = 0;
00053         virtual bool CanProduce()=0;
00054         virtual int GetSize()=0;
00055         virtual void SetSize(int newSize)=0;
00056         virtual int GetHop()=0;
00057         virtual void SetHop(int newHop)=0;
00058         bool HasConnections(){ return mVisuallyConnectedPorts.size()!=0; }
00059         virtual void CenterEvenRegions()=0;
00060         void SetPublisher( OutPortBase& publisher); 
00061         void UnsetPublisher(); 
00062         virtual void UnpublishOutPort() =0;
00063         virtual const std::type_info & GetTypeId() const = 0;
00064 protected:
00065         InPortsList mVisuallyConnectedPorts;    
00066         std::string mName;
00067         Processing * mProcessing;
00068         OutPortBase* mPublisher;
00069 };
00070 
00071 
00072 template<typename Token>
00073 class OutPort : public OutPortBase
00074 {
00075         typedef OutPort<Token> ProperOutPort;
00076         typedef InPort<Token> ProperInPort;
00077         typedef WritingRegion<Token> ProperWritingRegion;
00078 public:
00079         OutPort( const std::string & name = "unnamed out port", Processing * proc = 0 );
00080         virtual ~OutPort();
00081 
00082         void DisconnectFromAll();
00083         void ConnectToIn( InPortBase& in);
00084         void ConnectToConcreteIn(InPort<Token>& in);
00085         void DisconnectFromIn( InPortBase& in);
00086         void DisconnectFromConcreteIn(InPort<Token>& in);
00087         bool IsConnectableTo(InPortBase & in);
00088         bool IsVisuallyConnectedTo(InPortBase & in);
00089         bool IsPhysicallyConnectedToIn(InPort<Token>& ); 
00090         InPortPublisher<Token>* GetPublisherContaining(InPort<Token>&);
00091 
00092         Token & GetData(int offset=0);  
00093         void SetSize( int newSize );
00094         int GetSize();
00095         int GetHop();
00096         void SetHop( int hop ); 
00097         void Produce();
00098         bool CanProduce();
00099         void CenterEvenRegions();
00100         
00101         static Token & GetLastWrittenData( OutPortBase &, int offset = 0);
00102         void UnpublishOutPort() {} 
00103         virtual const std::type_info & GetTypeId() const
00104         {
00105                 return typeid(Token);
00106         };
00107 
00108 protected:      
00109         bool TryConnectToPublisher( InPortBase & in );
00110         bool TryConnectToConcreteIn( InPortBase & in );
00111 
00112         bool TryDisconnectFromPublisher( InPortBase & in );
00113         bool TryDisconnectFromConcreteIn( InPortBase & in );
00114 
00115         Token & GetLastWrittenData( int offset = 0 );
00116         ProperWritingRegion mRegion;
00117 
00118 };
00119 
00120 template<class Token>
00121 OutPort<Token>::OutPort( const std::string & name, Processing * proc )
00122         : OutPortBase(name,proc)
00123 {
00124 }
00125 
00126 template<class Token>
00127 void OutPort<Token>::DisconnectFromAll()
00128 {
00129         InPortsList::iterator it = mVisuallyConnectedPorts.begin();
00130         for( it=BeginVisuallyConnectedInPorts(); it!=EndVisuallyConnectedInPorts(); it++ )      
00131         { 
00132                 (*it)->UnAttachRegion();
00133         }
00134         mVisuallyConnectedPorts.clear();
00135 }
00136 
00137 template<class Token>
00138 OutPort<Token>::~OutPort()
00139 {
00140         DisconnectFromAll();
00141 }
00142 
00143 template<class Token>
00144 bool OutPort<Token>::TryConnectToConcreteIn( InPortBase & in )
00145 {
00146         try
00147         {
00148                 ConnectToConcreteIn( dynamic_cast<ProperInPort&>(in) );
00149         }
00150         catch(std::bad_cast & e)
00151         {
00152                 return false;
00153         }
00154         return true;
00155 }
00156 
00157 template<class Token>
00158 bool OutPort<Token>::TryConnectToPublisher( InPortBase & in )
00159 {
00160         InPortPublisher<Token> * publisher =  dynamic_cast< InPortPublisher<Token> *>(&in);
00161         if (!publisher) 
00162                 return false;
00163         
00164         typename InPortPublisher<Token>::ProperInPortsList::iterator it;
00165         mVisuallyConnectedPorts.push_back( &in );
00166         for( it=publisher->BeginPublishedInPortsList(); it!=publisher->EndPublishedInPortsList(); it++)
00167                 (*it)->AttachRegionToOutPort(this, mRegion );
00168 
00169         in.SetVisuallyConnectedOutPort(this);
00170 
00171         return true;
00172 }
00173 
00174 template<class Token>
00175 void OutPort<Token>::ConnectToIn( InPortBase& in)
00176 {
00177         bool successfullConnection;
00178         successfullConnection = TryConnectToConcreteIn( in ) || TryConnectToPublisher( in );
00179         CLAM_ASSERT( successfullConnection,
00180                      "OutPort<Token>::connectToIn coudn't connect to inPort "
00181                      "because was not templatized by the same Token type as outPort" );
00182 }
00183 
00184 template<class Token>
00185 void OutPort<Token>::ConnectToConcreteIn(InPort<Token>& in)
00186 {
00187         CLAM_ASSERT( !in.GetVisuallyConnectedOutPort(), "OutPort<Token>::ConnectToConcreteIn - Trying to connect an inport "
00188                                                     "already connected to another out port" );
00189         CLAM_ASSERT( !IsVisuallyConnectedTo(in), "OutPort<Token>::ConnectToConcreteIn - Trying to connect an in port "
00190                                         "already connected to this out port" );
00191         mVisuallyConnectedPorts.push_back(&in);
00192         in.AttachRegionToOutPort(this, mRegion );
00193 }
00194 
00195 template<class Token>
00196 void OutPort<Token>::DisconnectFromIn( InPortBase& in)
00197 {
00198         bool successfullDisconnection;
00199         successfullDisconnection = TryDisconnectFromConcreteIn( in ) || TryDisconnectFromPublisher( in );
00200         CLAM_ASSERT( successfullDisconnection,
00201                      "OutPort<Token>::DisconnectFromIn coudn't discconnect from inPort "
00202                      "because was not templatized by the same Token type as outPort" );
00203 }
00204 
00205 template<class Token>
00206 bool OutPort<Token>::TryDisconnectFromConcreteIn( InPortBase & in )
00207 {
00208         ProperInPort * concreteIn = dynamic_cast<ProperInPort*>(&in);
00209         if (!concreteIn)
00210                 return false;
00211         
00212         DisconnectFromConcreteIn( *concreteIn );
00213         return true;
00214 }
00215 
00216 template<class Token>
00217 bool OutPort<Token>::TryDisconnectFromPublisher( InPortBase & in )
00218 {
00219         InPortPublisher<Token> *publisher = dynamic_cast<InPortPublisher<Token> *>(&in);
00220         if (!publisher)
00221                 return false;
00222         
00223         typename InPortPublisher<Token>::ProperInPortsList::iterator it;
00224         mVisuallyConnectedPorts.remove( &in );
00225         for( it=publisher->BeginPublishedInPortsList(); it!=publisher->EndPublishedInPortsList(); it++)
00226         {
00227                 if( (*it)->GetVisuallyConnectedOutPort())
00228                         (*it)->UnAttachRegion();
00229         }
00230         return true;
00231 }
00232 
00233 template<class Token>
00234 void OutPort<Token>::DisconnectFromConcreteIn(InPort<Token>& in)
00235 {
00236         CLAM_ASSERT( IsVisuallyConnectedTo(in) || IsPhysicallyConnectedToIn(in), 
00237                         "OutPort::DisconnectFromConcreteIn() in port is not directly neither physically connected" );
00238         if (IsVisuallyConnectedTo(in) )
00239         {
00240                 // is directly connected
00241                 mVisuallyConnectedPorts.remove(&in);
00242         }
00243         else // then IsPhysicallyConnected()
00244         {
00245                 InPortPublisher<Token> *pub = GetPublisherContaining(in);
00246                 CLAM_DEBUG_ASSERT(0!=pub, "in port should be published");
00247                 pub->UnPublishInPort(in);
00248         }
00249         in.UnAttachRegion();
00250 }
00251 
00252 template<class Token>
00253 Token & OutPort<Token>::GetData(int offset )
00254 {
00255         return mRegion[offset];
00256 }
00257 
00258 template<class Token>
00259 void OutPort<Token>::SetSize( int newSize )
00260 {
00261         mRegion.Size( newSize );
00262 }
00263 
00264 template<class Token>
00265 int OutPort<Token>::GetSize()
00266 {
00267         return mRegion.Size();
00268 }
00269 
00270 template<class Token>
00271 int OutPort<Token>::GetHop()
00272 {
00273         return mRegion.Hop();
00274 }
00275 
00276 template<class Token>
00277 void OutPort<Token>::SetHop( int hop )
00278 {
00279         mRegion.Hop(hop);
00280 }
00281 
00282 template<class Token>
00283 void OutPort<Token>::Produce()
00284 {
00285         mRegion.Produce();
00286 }
00287 
00288 template<class Token>
00289 bool OutPort<Token>::CanProduce()
00290 {
00291         return mRegion.CanProduce();
00292 }
00293 
00294 template<class Token>
00295 bool OutPort<Token>::IsConnectableTo(InPortBase & in)
00296 {       
00297         return ( dynamic_cast< ProperInPort* >(&in) || 
00298                 dynamic_cast< InPortPublisher<Token> *>(&in));
00299 }
00300 
00301 template<class Token>
00302 bool OutPort<Token>::IsPhysicallyConnectedToIn(InPort<Token>& in)
00303 { 
00304         if (IsVisuallyConnectedTo(in))
00305                 return true;
00306         
00307         return ( 0!=GetPublisherContaining(in) );
00308         
00309 }
00310 
00311 template<class Token>
00312 InPortPublisher<Token>* OutPort<Token>::GetPublisherContaining(InPort<Token>& in)
00313 {
00314         
00315         InPortPublisher<Token> *result=0;
00316         InPortsList::iterator it;
00317         for( it=mVisuallyConnectedPorts.begin(); it!=mVisuallyConnectedPorts.end(); it++ )
00318                 if ( (*it)->IsPublisherOf(in) )
00319                 {
00320                         result=dynamic_cast<InPortPublisher<Token> *>(*it);
00321                         CLAM_DEBUG_ASSERT( result, "OutPort::GetPublisherContaining(in) IsPublisher but dynamic_cast failed");
00322                         return result;
00323                 }
00324 
00325         return 0;
00326                 
00327 }
00328 
00329 template<class Token>
00330 bool OutPort<Token>::IsVisuallyConnectedTo(InPortBase & in)
00331 {
00332         InPortsList::iterator it;
00333         for( it=mVisuallyConnectedPorts.begin(); it!=mVisuallyConnectedPorts.end(); it++ )
00334                 if(*it == &in) return true;
00335         return false;
00336 }
00337         
00338 template<class Token>
00339 void OutPort<Token>::CenterEvenRegions()
00340 {
00341         mRegion.CenterEvenRegions();
00342 }
00343 
00344 template<class Token>
00345 Token & OutPort<Token>::GetLastWrittenData( int offset )
00346 {
00347         CLAM_DEBUG_ASSERT( 0 <= offset, "OutPort<Token>::GetLastWrittenData - Index under bounds" );
00348         CLAM_DEBUG_ASSERT( offset <= GetSize(), "OutPort<Token>::GetLastWrittenData - Index over bounds" );
00349         return mRegion.GetLastWrittenData( offset );
00350 }
00351 
00352 template<class Token>
00353 Token & OutPort<Token>::GetLastWrittenData( OutPortBase & out, int offset )
00354 {
00355         try
00356         {
00357                 OutPort<Token>& concreteOut = dynamic_cast< OutPort<Token>& >(out);
00358                 return concreteOut.GetLastWrittenData( offset );
00359         }
00360         catch(...)
00361         {
00362                 CLAM_ASSERT( false, "OutPort<Token>::GetLastWrittenData - Passed an outport of wrong type" );
00363         }
00364         return *(Token *)NULL;
00365                 
00366 }
00367 
00368 } // namespace CLAM
00369 
00370 #endif // __OutPort_hxx__
00371 

Generated on Tue Aug 12 22:33:43 2008 for CLAM by  doxygen 1.5.5