Orocos Real-Time Toolkit
2.5.0
|
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 if (mservice && mservice->hasService( port.getName()) != 0) { 00063 log(Warning) <<"'addPort' "<< port.getName() << ": name already in use as Service. Replacing previous service with new one." <<endlog(); 00064 mservice->removeService(port.getName()); 00065 } 00066 00067 if (!mservice) { 00068 log(Warning) <<"'addPort' "<< port.getName() << ": DataFlowInterface not given to parent. Not adding Service." <<endlog(); 00069 return port; 00070 } 00071 Service::shared_ptr ms( this->createPortObject( port.getName()) ); 00072 if ( ms ) 00073 mservice->addService( ms ); 00074 // END NOTE. 00075 return port; 00076 } 00077 00078 PortInterface& DataFlowInterface::addLocalPort(PortInterface& port) { 00079 for ( Ports::iterator it(mports.begin()); 00080 it != mports.end(); 00081 ++it) 00082 if ( (*it)->getName() == port.getName() ) { 00083 log(Warning) <<"'addPort' "<< port.getName() << ": name already in use. Disconnecting and replacing previous port with new one." <<endlog(); 00084 removePort( port.getName() ); 00085 break; 00086 } 00087 00088 mports.push_back( &port ); 00089 port.setInterface( this ); 00090 return port; 00091 } 00092 00093 InputPortInterface& DataFlowInterface::addEventPort(InputPortInterface& port, SlotFunction callback) { 00094 if ( !chkPtr("addEventPort", "PortInterface", &port) ) return port; 00095 this->addLocalEventPort(port, callback); 00096 if (mservice && mservice->hasService( port.getName()) != 0) { 00097 log(Warning) <<"'addPort' "<< port.getName() << ": name already in use as Service. Replacing previous service with new one." <<endlog(); 00098 mservice->removeService(port.getName()); 00099 } 00100 00101 if (!mservice) { 00102 log(Warning) <<"'addPort' "<< port.getName() << ": DataFlowInterface not given to parent. Not adding Service." <<endlog(); 00103 return port; 00104 } 00105 Service::shared_ptr ms( this->createPortObject( port.getName()) ); 00106 if ( ms ) 00107 mservice->addService( ms ); 00108 return port; 00109 } 00110 00111 #ifdef ORO_SIGNALLING_PORTS 00112 void DataFlowInterface::setupHandles() { 00113 for_each(handles.begin(), handles.end(), boost::bind(&Handle::connect, _1)); 00114 } 00115 00116 void DataFlowInterface::cleanupHandles() { 00117 for_each(handles.begin(), handles.end(), boost::bind(&Handle::disconnect, _1)); 00118 } 00119 #else 00120 void DataFlowInterface::dataOnPort(base::PortInterface* port) 00121 { 00122 if ( mservice && mservice->getOwner() ) 00123 mservice->getOwner()->dataOnPort(port); 00124 } 00125 #endif 00126 00127 InputPortInterface& DataFlowInterface::addLocalEventPort(InputPortInterface& port, SlotFunction callback) { 00128 this->addLocalPort(port); 00129 00130 if (mservice == 0 || mservice->getOwner() == 0) { 00131 log(Error) << "addLocalEventPort "<< port.getName() <<": DataFlowInterface not part of a TaskContext. Will not trigger any TaskContext nor register callback." <<endlog(); 00132 return port; 00133 } 00134 00135 #ifdef ORO_SIGNALLING_PORTS 00136 // setup synchronous callback, only purpose is to register that port fired and trigger the TC's engine. 00137 Handle h = port.getNewDataOnPortEvent()->connect(boost::bind(&TaskContext::dataOnPort, mservice->getOwner(), _1) ); 00138 if (h) { 00139 log(Info) << mservice->getName() << " will be triggered when new data is available on InputPort " << port.getName() << endlog(); 00140 handles.push_back(h); 00141 } else { 00142 log(Error) << mservice->getName() << " can't connect to event of InputPort " << port.getName() << endlog(); 00143 return port; 00144 } 00145 #endif 00146 if (callback) 00147 mservice->getOwner()->dataOnPortCallback(&port,callback); // the handle will be deleted when the port is removed. 00148 00149 #ifndef ORO_SIGNALLING_PORTS 00150 port.signalInterface(true); 00151 #endif 00152 return port; 00153 } 00154 00155 void DataFlowInterface::removePort(const std::string& name) { 00156 for ( Ports::iterator it(mports.begin()); 00157 it != mports.end(); 00158 ++it) 00159 if ( (*it)->getName() == name ) { 00160 if (mservice) { 00161 mservice->removeService( name ); 00162 if (mservice->getOwner()) 00163 mservice->getOwner()->dataOnPortRemoved( *it ); 00164 } 00165 (*it)->disconnect(); // remove all connections and callbacks. 00166 mports.erase(it); 00167 return; 00168 } 00169 } 00170 00171 DataFlowInterface::Ports DataFlowInterface::getPorts() const { 00172 return mports; 00173 } 00174 00175 DataFlowInterface::PortNames DataFlowInterface::getPortNames() const { 00176 std::vector<std::string> res; 00177 for ( Ports::const_iterator it(mports.begin()); 00178 it != mports.end(); 00179 ++it) 00180 res.push_back( (*it)->getName() ); 00181 return res; 00182 } 00183 00184 PortInterface* DataFlowInterface::getPort(const std::string& name) const { 00185 for ( Ports::const_iterator it(mports.begin()); 00186 it != mports.end(); 00187 ++it) 00188 if ( (*it)->getName() == name ) 00189 return *it; 00190 return 0; 00191 } 00192 00193 std::string DataFlowInterface::getPortDescription(const std::string& name) const { 00194 for ( Ports::const_iterator it(mports.begin()); 00195 it != mports.end(); 00196 ++it) 00197 if ( (*it)->getName() == name ) 00198 return (*it)->getDescription(); 00199 return ""; 00200 } 00201 00202 bool DataFlowInterface::setPortDescription(const std::string& name, const std::string description) { 00203 Service::shared_ptr srv = mservice->getService(name); 00204 if (srv) { 00205 srv->doc(description); 00206 return true; 00207 } 00208 return false; 00209 } 00210 00211 Service* DataFlowInterface::createPortObject(const std::string& name) { 00212 PortInterface* p = this->getPort(name); 00213 if ( !p ) 00214 return 0; 00215 Service* to = p->createPortObject(); 00216 if (to) { 00217 std::string d = this->getPortDescription(name); 00218 if ( !d.empty() ) 00219 to->doc( d ); 00220 else 00221 to->doc("No description set for this Port. Use .doc() to document it."); 00222 } 00223 return to; 00224 } 00225 00226 void DataFlowInterface::clear() 00227 { 00228 // remove TaskObjects: 00229 for ( Ports::iterator it(mports.begin()); 00230 it != mports.end(); 00231 ++it) { 00232 if (mservice) 00233 mservice->removeService( (*it)->getName() ); 00234 } 00235 mports.clear(); 00236 } 00237 00238 bool DataFlowInterface::chkPtr(const std::string & where, const std::string & name, const void *ptr) 00239 { 00240 if ( ptr == 0) { 00241 log(Error) << "You tried to add a null pointer in '"<< where << "' for the object '" << name << "'. Fix your code !"<< endlog(); 00242 return false; 00243 } 00244 return true; 00245 } 00246 00247 }