00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00241 mVisuallyConnectedPorts.remove(&in);
00242 }
00243 else
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 }
00369
00370 #endif // __OutPort_hxx__
00371