Orocos Real-Time Toolkit
2.5.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 ms->evaluate(); 00091 } 00092 } 00093 }; 00094 00095 boost::shared_ptr<OperationKeeper> mopkeeper; 00096 00100 OperationInterfacePart* orp; 00101 }; 00102 00103 00104 00105 class SendHandleC::D 00106 { 00107 public: 00108 OperationInterfacePart* mofp; 00109 std::string mname; 00110 std::vector<DataSourceBase::shared_ptr> args; 00111 DataSource<SendStatus>::shared_ptr s; 00112 DataSourceBase::shared_ptr msh; 00113 AssignableDataSource<bool>::shared_ptr blocking; 00114 00115 void checkAndCreate() { 00116 Logger::In in("SendHandleC"); 00117 if ( mofp ) { 00118 size_t sz = mofp->collectArity(); 00119 if ( sz == args.size() ) { 00120 // insert the send handle first. 00121 args.insert( args.begin(), msh ); 00122 // may throw or return nill 00123 s = boost::dynamic_pointer_cast<DataSource<SendStatus> >( mofp->produceCollect(args, blocking ) ); 00124 args.clear(); 00125 if ( !s ) { 00126 log(Error) << "Failed to produce collector for "<< mname << " with " << sz << " arguments." << endlog(); 00127 return; 00128 } 00129 } 00130 } 00131 } 00132 00133 void newarg(DataSourceBase::shared_ptr na) 00134 { 00135 this->args.push_back( na ); 00136 this->checkAndCreate(); 00137 } 00138 00139 D( base::DataSourceBase::shared_ptr sh, OperationInterfacePart* ofp, const std::string& name) 00140 : mofp(ofp), mname(name), s(), msh(sh), blocking( new ValueDataSource<bool>(false) ) 00141 { 00142 this->checkAndCreate(); 00143 } 00144 00145 D(const D& other) 00146 : mofp(other.mofp), mname(other.mname), 00147 args( other.args ), s( other.s ), msh(other.msh), blocking(new ValueDataSource<bool>(false)) 00148 { 00149 } 00150 00151 ~D() 00152 { 00153 } 00154 00155 }; 00156 00157 SendHandleC::SendHandleC() 00158 : d(0), e( new E(0) ) 00159 { 00160 } 00161 00162 SendHandleC::SendHandleC( base::DataSourceBase::shared_ptr op, base::DataSourceBase::shared_ptr sh, OperationInterfacePart* ofp, const std::string& name ) 00163 : d( ofp ? new D( sh, ofp, name ) : 0 ), e( new E(op) ) 00164 { 00165 if ( d->s ) { 00166 e->s = d->s; 00167 e->b = d->blocking; 00168 e->mopkeeper.reset( new E::OperationKeeper( e->s, e->b) ); 00169 delete d; 00170 d = 0; 00171 } 00172 this->e->orp = ofp; 00173 } 00174 00175 SendHandleC::SendHandleC(const SendHandleC& other) 00176 : d( other.d ? new D(*other.d) : 0 ), e( new E(*other.e) ) 00177 { 00178 } 00179 00180 SendHandleC& SendHandleC::operator=(const SendHandleC& other) 00181 { 00182 if ( &other == this ) 00183 return *this; 00184 delete d; 00185 d = ( other.d ? new D(*other.d) : 0 ); 00186 e->s = other.e->s; 00187 e->b = other.e->b; 00188 e->mop = other.e->mop; 00189 e->mopkeeper = other.e->mopkeeper; 00190 e->orp = other.e->orp; 00191 return *this; 00192 } 00193 00194 SendHandleC::~SendHandleC() 00195 { 00196 delete d; 00197 delete e; 00198 } 00199 00200 SendHandleC& SendHandleC::arg( DataSourceBase::shared_ptr a ) 00201 { 00202 if (d) 00203 d->newarg( a ); 00204 else { 00205 Logger::log() <<Logger::Warning << "Extra argument discarded for SendHandleC."<<Logger::endl; 00206 } 00207 if ( d && d->s ) { 00208 e->s = d->s; 00209 e->b = d->blocking; 00210 e->orp = d->mofp; 00211 e->mopkeeper.reset( new E::OperationKeeper( e->s, e->b) ); 00212 delete d; 00213 d = 0; 00214 } 00215 return *this; 00216 } 00217 00218 SendStatus SendHandleC::collect() { 00219 if (e->s) { 00220 e->b->set(true); // blocking 00221 e->s->evaluate(); 00222 return e->s->value(); 00223 } 00224 else { 00225 Logger::log() <<Logger::Error << "collect() called on incomplete SendHandleC."<<Logger::endl; 00226 if (d) { 00227 size_t sz; 00228 sz = d->mofp->collectArity(); 00229 Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl; 00230 Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl; 00231 } 00232 } 00233 return SendFailure; 00234 } 00235 00236 SendStatus SendHandleC::collectIfDone() { 00237 if (e->s) { 00238 e->b->set(false); // non blocking 00239 // does the send. 00240 e->s->evaluate(); 00241 // pass on handle. 00242 return e->s->value(); 00243 } 00244 else { 00245 Logger::log() <<Logger::Error << "collectIfDone() called on incomplete SendHandleC."<<Logger::endl; 00246 if (d) { 00247 size_t sz; 00248 sz = d->mofp->collectArity(); 00249 Logger::log() <<Logger::Error << "Wrong number of arguments provided for method '"+d->mname+"'"<<Logger::nl; 00250 Logger::log() <<Logger::Error << "Expected "<< sz << ", got: " << d->args.size() <<Logger::endl; 00251 } 00252 } 00253 return SendFailure; 00254 } 00255 00256 bool SendHandleC::ready() const 00257 { 00258 return e->s; 00259 } 00260 00261 void SendHandleC::setAutoCollect(bool on_off) { 00262 if (e->mopkeeper) 00263 e->mopkeeper->autocollect = on_off; 00264 } 00265 00266 void SendHandleC::check() { 00267 if (d) { 00268 // something went wrong, let producer throw 00269 if (d->mofp) 00270 DataSourceBase::shared_ptr dummy = d->mofp->produceCollect( d->args, d->blocking ); 00271 else 00272 throw invalid_handle_exception(); 00273 } 00274 } 00275 00276 00277 DataSourceBase::shared_ptr SendHandleC::getSendHandleDataSource() { return e->s; } 00278 00279 OperationInterfacePart* SendHandleC::getOrp() { return e->orp; } 00280 }