Orocos Real-Time Toolkit
2.6.0
|
00001 /*************************************************************************** 00002 tag: The SourceWorks Tue Sep 7 00:55:18 CEST 2010 SendHandleC.cpp 00003 00004 SendHandleC.cpp - description 00005 ------------------- 00006 begin : Tue September 07 2010 00007 copyright : (C) 2010 The SourceWorks 00008 email : peter@thesourceworks.com 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 "SendHandleC.hpp" 00040 #include "../FactoryExceptions.hpp" 00041 #include "DataSourceCommand.hpp" 00042 #include "../Service.hpp" 00043 #include "../Logger.hpp" 00044 #include "Exceptions.hpp" 00045 #include <vector> 00046 00047 namespace RTT { 00048 using namespace detail; 00049 00050 00051 class SendHandleC::E 00052 { 00053 public: 00054 E(base::DataSourceBase::shared_ptr op) : s(), b(), mop(op), orp(0) {} 00055 00056 ~E() { 00057 // force synchronisation in case we are the last SendHandleC. We may not cleanup mop (holds data!), until the op 00058 // completed or failed. 00059 // Reduce refcount on mopkeeper 00060 mopkeeper.reset(); 00061 } 00062 00067 internal::DataSource<SendStatus>::shared_ptr s; 00071 internal::AssignableDataSource<bool>::shared_ptr b; 00075 base::DataSourceBase::shared_ptr mop; 00076 00081 struct OperationKeeper 00082 { 00083 DataSource<SendStatus>::shared_ptr ms; 00084 AssignableDataSource<bool>::shared_ptr mb; 00085 bool autocollect; 00086 OperationKeeper(DataSource<SendStatus>::shared_ptr s, AssignableDataSource<bool>::shared_ptr b) : ms(s), mb(b), autocollect(true) {} 00087 ~OperationKeeper() { 00088 if (ms && autocollect) { 00089 mb->set(true); // blocking 00090 try { // the evaluated function may throw 00091 ms->evaluate(); 00092 } catch (std::exception&) { 00093 } 00094 } 00095 } 00096 }; 00097 00098 boost::shared_ptr<OperationKeeper> mopkeeper; 00099 00103 OperationInterfacePart* orp; 00104 }; 00105 00106 00107 00108 class SendHandleC::D 00109 { 00110 public: 00111 OperationInterfacePart* mofp; 00112 std::string mname; 00113 std::vector<DataSourceBase::shared_ptr> args; 00114 DataSource<SendStatus>::shared_ptr s; 00115 DataSourceBase::shared_ptr msh; 00116 AssignableDataSource<bool>::shared_ptr blocking; 00117 00118 void checkAndCreate() { 00119 Logger::In in("SendHandleC"); 00120 if ( mofp ) { 00121 size_t sz = mofp->collectArity(); 00122 if ( sz == args.size() ) { 00123 // insert the send handle first. 00124 args.insert( args.begin(), msh ); 00125 // may throw or return nill 00126 s = boost::dynamic_pointer_cast<DataSource<SendStatus> >( mofp->produceCollect(args, blocking ) ); 00127 args.clear(); 00128 if ( !s ) { 00129 log(Error) << "Failed to produce collector for "<< mname << " with " << sz << " arguments." << endlog(); 00130 return; 00131 } 00132 } 00133 } 00134 } 00135 00136 void newarg(DataSourceBase::shared_ptr na) 00137 { 00138 this->args.push_back( na ); 00139 this->checkAndCreate(); 00140 } 00141 00142 D( base::DataSourceBase::shared_ptr sh, OperationInterfacePart* ofp, const std::string& name) 00143 : mofp(ofp), mname(name), s(), msh(sh), blocking( new ValueDataSource<bool>(false) ) 00144 { 00145 this->checkAndCreate(); 00146 } 00147 00148 D(const D& other) 00149 : mofp(other.mofp), mname(other.mname), 00150 args( other.args ), s( other.s ), msh(other.msh), blocking(new ValueDataSource<bool>(false)) 00151 { 00152 } 00153 00154 ~D() 00155 { 00156 } 00157 00158 }; 00159 00160 SendHandleC::SendHandleC() 00161 : d(0), e( new E(0) ) 00162 { 00163 } 00164 00165 SendHandleC::SendHandleC( base::DataSourceBase::shared_ptr op, base::DataSourceBase::shared_ptr sh, OperationInterfacePart* ofp, const std::string& name ) 00166 : d( ofp ? new D( sh, ofp, name ) : 0 ), e( new E(op) ) 00167 { 00168 if ( d->s ) { 00169 e->s = d->s; 00170 e->b = d->blocking; 00171 e->mopkeeper.reset( new E::OperationKeeper( e->s, e->b) ); 00172 delete d; 00173 d = 0; 00174 } 00175 this->e->orp = ofp; 00176 } 00177 00178 SendHandleC::SendHandleC(const SendHandleC& other) 00179 : d( other.d ? new D(*other.d) : 0 ), e( new E(*other.e) ) 00180 { 00181 } 00182 00183 SendHandleC& SendHandleC::operator=(const SendHandleC& other) 00184 { 00185 if ( &other == this ) 00186 return *this; 00187 delete d; 00188 d = ( other.d ? new D(*other.d) : 0 ); 00189 e->s = other.e->s; 00190 e->b = other.e->b; 00191 e->mop = other.e->mop; 00192 e->mopkeeper = other.e->mopkeeper; 00193 e->orp = other.e->orp; 00194 return *this; 00195 } 00196 00197 SendHandleC::~SendHandleC() 00198 { 00199 delete d; 00200 delete e; 00201 } 00202 00203 SendHandleC& SendHandleC::arg( DataSourceBase::shared_ptr a ) 00204 { 00205 if (d) 00206 d->newarg( a ); 00207 else { 00208 Logger::log() <<Logger::Warning << "Extra argument discarded for SendHandleC."<<Logger::endl; 00209 } 00210 if ( d && d->s ) { 00211 e->s = d->s; 00212 e->b = d->blocking; 00213 e->orp = d->mofp; 00214 e->mopkeeper.reset( new E::OperationKeeper( e->s, e->b) ); 00215 delete d; 00216 d = 0; 00217 } 00218 return *this; 00219 } 00220 00221 SendStatus SendHandleC::collect() { 00222 if (e->s) { 00223 e->b->set(true); // blocking 00224 e->s->evaluate(); 00225 return e->s->value(); 00226 } 00227 else { 00228 Logger::log() <<Logger::Error << "collect() called on incomplete SendHandleC."<<Logger::endl; 00229 if (d) { 00230 size_t sz; 00231 sz = d->mofp->collectArity(); 00232 Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl; 00233 Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl; 00234 } 00235 } 00236 return SendFailure; 00237 } 00238 00239 SendStatus SendHandleC::collectIfDone() { 00240 if (e->s) { 00241 e->b->set(false); // non blocking 00242 // does the send. 00243 e->s->evaluate(); 00244 // pass on handle. 00245 return e->s->value(); 00246 } 00247 else { 00248 Logger::log() <<Logger::Error << "collectIfDone() called on incomplete SendHandleC."<<Logger::endl; 00249 if (d) { 00250 size_t sz; 00251 sz = d->mofp->collectArity(); 00252 Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl; 00253 Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl; 00254 } 00255 } 00256 return SendFailure; 00257 } 00258 00259 bool SendHandleC::ready() const 00260 { 00261 return e->s; 00262 } 00263 00264 void SendHandleC::setAutoCollect(bool on_off) { 00265 if (e->mopkeeper) 00266 e->mopkeeper->autocollect = on_off; 00267 } 00268 00269 void SendHandleC::check() { 00270 if (d) { 00271 // something went wrong, let producer throw 00272 if (d->mofp) 00273 DataSourceBase::shared_ptr dummy = d->mofp->produceCollect( d->args, d->blocking ); 00274 else 00275 throw invalid_handle_exception(); 00276 } 00277 } 00278 00279 00280 DataSourceBase::shared_ptr SendHandleC::getSendHandleDataSource() { return e->s; } 00281 00282 OperationInterfacePart* SendHandleC::getOrp() { return e->orp; } 00283 }