DataFlowInterface.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002   tag: FMTC  Tue Mar 11 21:49:27 CET 2008  DataFlowInterface.cpp
00003 
00004                         DataFlowInterface.cpp -  description
00005                            -------------------
00006     begin                : Tue March 11 2008
00007     copyright            : (C) 2008 FMTC
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 #include "DataFlowInterface.hpp"
00040 #include "Logger.hpp"
00041 #include "Service.hpp"
00042 #include "TaskContext.hpp"
00043 
00044 namespace RTT
00045 {
00046     using namespace detail;
00047 
00048     DataFlowInterface::DataFlowInterface(Service* parent /* = 0 */)
00049         : mservice(parent)
00050     {}
00051 
00052     DataFlowInterface::~DataFlowInterface() {
00053     }
00054 
00055     TaskContext* DataFlowInterface::getOwner() const {
00056         return mservice ? mservice->getOwner() : 0;
00057     }
00058 
00059     PortInterface& DataFlowInterface::addPort(PortInterface& port) {
00060         if ( !chkPtr("addPort", "PortInterface", &port) ) return port;
00061         this->addLocalPort(port);
00062         Service::shared_ptr mservice_ref;
00063         if (mservice && mservice->hasService( port.getName()) ) {
00064             // Since there is at least one child service, mservice is ref counted. The danger here is that mservice is destructed during removeService()
00065             // for this reason, we take a ref to mservice until we leave addPort.
00066             mservice_ref = mservice->provides(); // uses shared_from_this()
00067             log(Warning) <<"'addPort' "<< port.getName() << ": name already in use as Service. Replacing previous service with new one." <<endlog();
00068             mservice->removeService(port.getName());
00069         }
00070 
00071         if (!mservice) {
00072             log(Warning) <<"'addPort' "<< port.getName() << ": DataFlowInterface not given to parent. Not adding Service." <<endlog();
00073             return port;
00074         }
00075         Service::shared_ptr ms( this->createPortObject( port.getName()) );
00076         if ( ms )
00077             mservice->addService( ms );
00078         // END NOTE.
00079         return port;
00080     }
00081 
00082     PortInterface& DataFlowInterface::addLocalPort(PortInterface& port) {
00083         for ( Ports::iterator it(mports.begin());
00084               it != mports.end();
00085               ++it)
00086             if ( (*it)->getName() == port.getName() ) {
00087                 log(Warning) <<"'addPort' "<< port.getName() << ": name already in use. Disconnecting and replacing previous port with new one." <<endlog();
00088                 removeLocalPort( port.getName() );
00089                 break;
00090             }
00091 
00092         mports.push_back( &port );
00093         port.setInterface( this );
00094         return port;
00095     }
00096 
00097     InputPortInterface& DataFlowInterface::addEventPort(InputPortInterface& port, SlotFunction callback) {
00098         if ( !chkPtr("addEventPort", "PortInterface", &port) ) return port;
00099         this->addLocalEventPort(port, callback);
00100         Service::shared_ptr mservice_ref;
00101         if (mservice && mservice->hasService( port.getName()) ) {
00102             // Since there is at least one child service, mservice is ref counted. The danger here is that mservice is destructed during removeService()
00103             // for this reason, we take a ref to mservice until we leave addPort.
00104             mservice_ref = mservice->provides(); // uses shared_from_this()
00105             log(Warning) <<"'addPort' "<< port.getName() << ": name already in use as Service. Replacing previous service with new one." <<endlog();
00106             mservice->removeService(port.getName());
00107         }
00108 
00109         if (!mservice) {
00110             log(Warning) <<"'addPort' "<< port.getName() << ": DataFlowInterface not given to parent. Not adding Service." <<endlog();
00111             return port;
00112         }
00113         Service::shared_ptr ms( this->createPortObject( port.getName()) );
00114         if ( ms )
00115             mservice->addService( ms );
00116         return port;
00117     }
00118 
00119 #ifdef ORO_SIGNALLING_PORTS
00120     void DataFlowInterface::setupHandles() {
00121         for_each(handles.begin(), handles.end(), boost::bind(&Handle::connect, _1));
00122     }
00123 
00124     void DataFlowInterface::cleanupHandles() {
00125         for_each(handles.begin(), handles.end(), boost::bind(&Handle::disconnect, _1));
00126     }
00127 #else
00128     void DataFlowInterface::dataOnPort(base::PortInterface* port)
00129     {
00130         if ( mservice && mservice->getOwner() )
00131             mservice->getOwner()->dataOnPort(port);
00132     }
00133 #endif
00134 
00135     InputPortInterface& DataFlowInterface::addLocalEventPort(InputPortInterface& port, SlotFunction callback) {
00136         this->addLocalPort(port);
00137 
00138         if (mservice == 0 || mservice->getOwner() == 0) {
00139             log(Error) << "addLocalEventPort "<< port.getName() <<": DataFlowInterface not part of a TaskContext. Will not trigger any TaskContext nor register callback." <<endlog();
00140             return port;
00141         }
00142 
00143 #ifdef ORO_SIGNALLING_PORTS
00144         // setup synchronous callback, only purpose is to register that port fired and trigger the TC's engine.
00145         Handle h = port.getNewDataOnPortEvent()->connect(boost::bind(&TaskContext::dataOnPort, mservice->getOwner(), _1) );
00146         if (h) {
00147             log(Info) << mservice->getName() << " will be triggered when new data is available on InputPort " << port.getName() << endlog();
00148             handles.push_back(h);
00149         } else {
00150             log(Error) << mservice->getName() << " can't connect to event of InputPort " << port.getName() << endlog();
00151             return port;
00152         }
00153 #endif
00154         if (callback)
00155             mservice->getOwner()->dataOnPortCallback(&port,callback); // the handle will be deleted when the port is removed.
00156 
00157 #ifndef ORO_SIGNALLING_PORTS
00158         port.signalInterface(true);
00159 #endif
00160         return port;
00161     }
00162 
00163     void DataFlowInterface::removePort(const std::string& name) {
00164         for ( Ports::iterator it(mports.begin());
00165               it != mports.end();
00166               ++it)
00167             if ( (*it)->getName() == name ) {
00168                 Service::shared_ptr mservice_ref;
00169                 if (mservice && mservice->hasService(name) ) {
00170                     // Since there is at least one child service, mservice is ref counted. The danger here is that mservice is destructed during removeService()
00171                     // for this reason, we take a ref to mservice until we leave removePort.
00172                     mservice_ref = mservice->provides(); // uses shared_from_this()
00173                     mservice->removeService( name );
00174                     if (mservice->getOwner())
00175                         mservice->getOwner()->dataOnPortRemoved( *it );
00176                 }
00177                 (*it)->disconnect(); // remove all connections and callbacks.
00178                 mports.erase(it);
00179                 return;
00180             }
00181     }
00182 
00183     void DataFlowInterface::removeLocalPort(const std::string& name) {
00184         for ( Ports::iterator it(mports.begin());
00185               it != mports.end();
00186               ++it)
00187             if ( (*it)->getName() == name ) {
00188                 (*it)->disconnect(); // remove all connections and callbacks.
00189                 mports.erase(it);
00190                 return;
00191             }
00192     }
00193 
00194     DataFlowInterface::Ports DataFlowInterface::getPorts() const {
00195         return mports;
00196     }
00197 
00198     DataFlowInterface::PortNames DataFlowInterface::getPortNames() const {
00199         std::vector<std::string> res;
00200         for ( Ports::const_iterator it(mports.begin());
00201               it != mports.end();
00202               ++it)
00203             res.push_back( (*it)->getName() );
00204         return res;
00205     }
00206 
00207     PortInterface* DataFlowInterface::getPort(const std::string& name) const {
00208         for ( Ports::const_iterator it(mports.begin());
00209               it != mports.end();
00210               ++it)
00211             if ( (*it)->getName() == name )
00212                 return *it;
00213         return 0;
00214     }
00215 
00216     std::string DataFlowInterface::getPortDescription(const std::string& name) const {
00217         for ( Ports::const_iterator it(mports.begin());
00218               it != mports.end();
00219               ++it)
00220             if ( (*it)->getName() == name )
00221                 return (*it)->getDescription();
00222         return "";
00223     }
00224 
00225     bool DataFlowInterface::setPortDescription(const std::string& name, const std::string description) {
00226         Service::shared_ptr srv = mservice->getService(name);
00227         if (srv) {
00228             srv->doc(description);
00229             return true;
00230         }
00231         return false;
00232     }
00233 
00234     Service* DataFlowInterface::createPortObject(const std::string& name) {
00235         PortInterface* p = this->getPort(name);
00236         if ( !p )
00237             return 0;
00238         Service* to = p->createPortObject();
00239         if (to) {
00240             std::string d = this->getPortDescription(name);
00241             if ( !d.empty() )
00242                 to->doc( d );
00243             else
00244                 to->doc("No description set for this Port. Use .doc() to document it.");
00245         }
00246         return to;
00247     }
00248 
00249     void DataFlowInterface::clear()
00250     {
00251         // remove TaskObjects:
00252         for ( Ports::iterator it(mports.begin());
00253               it != mports.end();
00254               ++it) {
00255             if (mservice)
00256                 mservice->removeService( (*it)->getName() );
00257         }
00258         mports.clear();
00259     }
00260 
00261     bool DataFlowInterface::chkPtr(const std::string & where, const std::string & name, const void *ptr)
00262     {
00263         if ( ptr == 0) {
00264             log(Error) << "You tried to add a null pointer in '"<< where << "' for the object '" << name << "'. Fix your code !"<< endlog();
00265             return false;
00266         }
00267         return true;
00268     }
00269 
00270 }


rtt
Author(s): RTT Developers
autogenerated on Wed Aug 26 2015 16:15:47