DataPort.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Thu Mar 2 08:30:18 CET 2006  DataPort.hpp
00003 
00004                         DataPort.hpp -  description
00005                            -------------------
00006     begin                : Thu March 02 2006
00007     copyright            : (C) 2006 Peter Soetens
00008     email                : peter.soetens@fmtc.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 #ifndef ORO_EXECUTION_DATA_PORT_INTERFACE_HPP
00040 #define ORO_EXECUTION_DATA_PORT_INTERFACE_HPP
00041 
00042 #include <string>
00043 #include "Logger.hpp"
00044 #include "PortInterface.hpp"
00045 #include "DataConnection.hpp"
00046 #include "OperationInterface.hpp"
00047 #include "Method.hpp"
00048 #include "ConnectionTypes.hpp"
00049 #include "TaskObject.hpp"
00050 
00051 namespace RTT
00052 {
00053     template<class T>
00054     class DataPortBase
00055         : public PortInterface
00056     {
00057         typedef T DataType;
00058     public:
00063         DataPortBase(const std::string& name) : PortInterface(name), mconn() {}
00064 
00065         ~DataPortBase() {
00066             if (mconn)
00067                 mconn->removePort(this);
00068         }
00069 
00074         DataPortBase<T>& operator=(DataObjectInterface<T>* impl);
00075 
00076         ConnectionInterface::shared_ptr createConnection(DataSourceBase::shared_ptr data);
00077 
00078         virtual ConnectionModel getConnectionModel() const { return Data; }
00079 
00080         virtual const TypeInfo* getTypeInfo() const { return detail::DataSourceTypeInfo<T>::getTypeInfo(); }
00081 
00082         bool connect(ConnectionInterface::shared_ptr conn)
00083         {
00084             if ( mconn || !conn )
00085                 return false;
00086             mconn = boost::dynamic_pointer_cast< DataConnection<T> > (conn);
00087             return (mconn);
00088         }
00089 
00090         virtual ConnectionInterface::shared_ptr connection() const { return mconn; }
00091 
00092         bool connected() const { return mconn; };
00093 
00094         using PortInterface::connectTo;
00095         bool connectTo( ConnectionInterface::shared_ptr other) {
00096             return other && !mconn && other->addPort( this );
00097         }
00098 
00099         void disconnect() {
00100             mconn = 0;
00101         }
00102 
00108         const DataObjectInterface<T>* data() const { return mconn ? mconn->data() : 0; }
00109 
00115         DataObjectInterface<T>* data() { return mconn ? mconn->data() : 0; }
00116 
00117     protected:
00121         mutable typename DataConnection<T>::shared_ptr mconn;
00122     };
00123 
00131     template<class T>
00132     class ReadDataPort
00133         : public DataPortBase<T>
00134     {
00135         using DataPortBase<T>::mconn;
00136     public:
00137         using DataPortBase<T>::operator=;
00138         typedef T DataType;
00139 
00144         ReadDataPort(const std::string& name) : DataPortBase<T>(name) {}
00145 
00151         T Get() const
00152         {
00153 #ifndef ORO_EMBEDDED
00154             try {
00155 #endif
00156                 if ( mconn )
00157                     return mconn->data()->Get();
00158 #ifndef ORO_EMBEDDED
00159             } catch (...) {
00160                 mconn = 0;
00161             }
00162 #endif
00163             return T();
00164         }
00165 
00172         void Get(T& result)
00173         {
00174 #ifndef ORO_EMBEDDED
00175             try {
00176 #endif
00177                 if ( mconn )
00178                     return mconn->data()->Get(result);
00179 #ifndef ORO_EMBEDDED
00180             } catch (...) {
00181                 mconn = 0;
00182             }
00183 #endif
00184         }
00185 
00186         virtual PortInterface::PortType getPortType() const { return PortInterface::ReadPort; }
00187 
00188         virtual PortInterface* clone() const {
00189             return new ReadDataPort<T>( this->getName() );
00190         }
00191 
00192         virtual PortInterface* antiClone() const;
00193 
00194         virtual TaskObject* createPortObject() {
00195 #ifndef ORO_EMBEDDED
00196             typedef T (ReadDataPort<T>::*GetType)(void) const;
00197             GetType get_type = &ReadDataPort<T>::Get;
00198             TaskObject* to = new TaskObject( this->getName() );
00199             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00200                                       "Check if this port is connected and ready for use.");
00201             to->methods()->addMethod( method("Get",get_type, this),
00202                                       "Get the current value of this Read Data Port");
00203             return to;
00204 #else
00205             return 0;
00206 #endif
00207         }
00208 
00209     };
00210 
00218     template<class T>
00219     class WriteDataPort
00220         : public DataPortBase<T>
00221     {
00222         using DataPortBase<T>::mconn;
00223     public:
00224         using DataPortBase<T>::operator=;
00225         typedef T DataType;
00226 
00234         WriteDataPort(const std::string& name, const DataType& initial_value = DataType() )
00235             : DataPortBase<T>(name), minitial_value(initial_value) {}
00236 
00243         void Set(const T& data )
00244         {
00245 #ifndef ORO_EMBEDDED
00246             try {
00247 #endif
00248                 if ( mconn )
00249                 {
00250                     mconn->data()->Set(data);
00251                     mconn->signal();
00252                     return;
00253                 }
00254 
00255 #ifndef ORO_EMBEDDED
00256             } catch (...) {
00257                 mconn = 0;
00258             }
00259 #endif
00260             minitial_value = data;
00261         }
00262 
00263         virtual PortInterface::PortType getPortType() const { return PortInterface::WritePort; }
00264 
00265         virtual PortInterface* clone() const {
00266             return new WriteDataPort<T>( this->getName(), minitial_value );
00267         }
00268 
00269         virtual PortInterface* antiClone() const {
00270             return new ReadDataPort<T>( this->getName() );
00271         }
00272 
00273         ConnectionInterface::shared_ptr createConnection(ConnectionTypes::ConnectionType con_type);
00274 
00275         virtual TaskObject* createPortObject() {
00276 #ifndef ORO_EMBEDDED
00277             TaskObject* to = new TaskObject( this->getName() );
00278             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00279                                       "Check if this port is connected and ready for use.");
00280             to->methods()->addMethod( method("Set",&WriteDataPort<T>::Set, this),
00281                                       "Set the current value of this Write Data Port",
00282                                       "Value", "The new value.");
00283             return to;
00284 #else
00285             return 0;
00286 #endif
00287         }
00288 
00289     protected:
00290         DataType minitial_value;
00291     };
00292 
00293 
00299     template<class T>
00300     class DataPort
00301         : public DataPortBase<T>
00302     {
00303     protected:
00304         T minitial_value;
00305         using DataPortBase<T>::mconn;
00306     public:
00307         using DataPortBase<T>::operator=;
00308         typedef T DataType;
00316         DataPort(const std::string& name, const DataType& initial_value = DataType() )
00317             : DataPortBase<T>(name), minitial_value(initial_value)
00318         {}
00319 
00326         void Set(const DataType& data )
00327         {
00328 #ifndef ORO_EMBEDDED
00329             try {
00330 #endif
00331                 if ( mconn ) {
00332                     mconn->data()->Set(data);
00333                     mconn->signal();
00334                     return;
00335                 }
00336 #ifndef ORO_EMBEDDED
00337             } catch (...) {
00338                 mconn = 0;
00339             }
00340 #endif
00341             minitial_value = data;
00342         }
00343 
00350         DataType Get() const
00351         {
00352 #ifndef ORO_EMBEDDED
00353             try {
00354 #endif
00355                 if ( mconn )
00356                     return mconn->data()->Get();
00357 #ifndef ORO_EMBEDDED
00358             } catch (...) {
00359                 mconn = 0;
00360             }
00361 #endif
00362             return minitial_value;
00363         }
00364 
00372         void Get(DataType& result)
00373         {
00374 #ifndef ORO_EMBEDDED
00375             try {
00376 #endif
00377                 if ( mconn )
00378                     return mconn->data()->Get(result);
00379 #ifndef ORO_EMBEDDED
00380             } catch (...) {
00381                 mconn = 0;
00382             }
00383 #endif
00384             result = minitial_value;
00385         }
00386 
00387         virtual PortInterface::PortType getPortType() const { return PortInterface::ReadWritePort; }
00388 
00389         virtual PortInterface* clone() const {
00390             return new DataPort<T>( this->getName(), this->minitial_value );
00391         }
00392 
00393         virtual PortInterface* antiClone() const {
00394             return this->clone();
00395         }
00396 
00397         virtual TaskObject* createPortObject() {
00398 #ifndef ORO_EMBEDDED
00399             typedef T (DataPort<T>::*GetType)(void) const;
00400             GetType get_type = &DataPort<T>::Get;
00401             TaskObject* to = new TaskObject( this->getName() );
00402             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00403                                       "Check if this port is connected and ready for use.");
00404             to->methods()->addMethod( method("Get", get_type, this),
00405                                       "Get the current value of this Data Port");
00406             to->methods()->addMethod( method("Set",&DataPort<T>::Set, this),
00407                                       "Set the current value of this Data Port",
00408                                       "Value", "The new value.");
00409             return to;
00410 #else
00411             return 0;
00412 #endif
00413         }
00414 
00415         ConnectionInterface::shared_ptr createConnection(ConnectionTypes::ConnectionType con_type);
00416     };
00417 }
00418 #endif
00419 
00420 #ifndef ORO_DATA_PORT_INLINE
00421 #define ORO_DATA_PORT_INLINE
00422 
00423 #include "ConnectionFactory.hpp"
00424 #include "DataConnection.hpp"
00425 
00426 namespace RTT
00427 {
00428     template<class T>
00429     DataPortBase<T>& DataPortBase<T>::operator=(DataObjectInterface<T>* impl)
00430     {
00431         if ( !mconn ) {
00432             ConnectionInterface::shared_ptr con = new DataConnection<T>(impl);
00433             this->connectTo(con);
00434             con->connect();
00435             } else
00436                 mconn->setImplementation(impl);
00437         return *this;
00438     }
00439 
00440     template<class T>
00441     PortInterface* ReadDataPort<T>::antiClone() const {
00442         return new WriteDataPort<T>( this->getName() );
00443     }
00444 
00445     template<class T>
00446     ConnectionInterface::shared_ptr DataPortBase<T>::createConnection(DataSourceBase::shared_ptr data)
00447     {
00448         DataObjectInterface<T>* doi = dynamic_cast< DataObjectInterface<T>* >( data.get() );
00449         if (!doi)
00450         {
00451             // use this to figure out what is actually registered.
00452             log(Error) << "Dynamic cast failed for "
00453                        << "'" << typeid(data.get()).name() << "', '"
00454                        << data->getType() << "', '"
00455                        << data->getTypeName() << "'"
00456                        << ". Do your typenames not match?" << endlog();
00457             TypeInfoRepository::Instance()->logTypeInfo();
00458         }
00459         /* If the doi doesn't cast and the following assert fires,
00460            then you may have misnamed your types when registering. Both the
00461            types registered with the RTT toolkit as well as the types registered
00462            with any transport (eg CORBA), must all have the *exact same name*.
00463            If not, then the above cast fails. FYI ...
00464         */
00465         assert(doi && "Dynamic cast failed! See log file for details.");
00466         ConnectionInterface::shared_ptr ci( new DataConnection<T>( doi ) );
00467         ci->addPort(this);
00468         return ci;
00469     }
00470 
00471     template<class T>
00472     ConnectionInterface::shared_ptr WriteDataPort<T>::createConnection(ConnectionTypes::ConnectionType con_type)
00473     {
00474         ConnectionFactory<T> cf;
00475         ConnectionInterface::shared_ptr res = cf.createDataObject(minitial_value, con_type);
00476         res->addPort(this);
00477         return res;
00478     }
00479 
00480     template<class T>
00481     ConnectionInterface::shared_ptr DataPort<T>::createConnection(ConnectionTypes::ConnectionType con_type)
00482     {
00483         ConnectionFactory<T> cf;
00484         ConnectionInterface::shared_ptr res = cf.createDataObject(minitial_value, con_type);
00485         res->addPort(this);
00486         return res;
00487     }
00488 
00489 }
00490 
00491 #endif
Generated on Thu Dec 23 13:22:37 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3