BufferPort.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Thu Mar 2 08:30:17 CET 2006  BufferPort.hpp 
00003 
00004                         BufferPort.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_BUFFER_PORT_HPP
00040 #define ORO_EXECUTION_BUFFER_PORT_HPP
00041 
00042 #include <string>
00043 #include "PortInterface.hpp"
00044 #include "BufferConnectionInterface.hpp"
00045 #include "OperationInterface.hpp"
00046 #include "Method.hpp"
00047 
00048 namespace RTT
00049 {
00057     template<class T>
00058     class ReadBufferPort
00059         : public virtual PortInterface
00060     {
00061     protected:
00062         typename ReadConnectionInterface<T>::shared_ptr mconn;
00063     public:
00068         ReadBufferPort(const std::string& name) : PortInterface(name), mconn() {}
00069 
00070         ~ReadBufferPort() {
00071             if (mconn) 
00072                 mconn->removeReader(this);
00073         }
00074 
00081         bool Pop(T& data)
00082         {
00083             if (mconn)
00084                 return mconn->read()->Pop(data);
00085             return false;
00086         }
00087 
00092         T front() const {
00093             if (mconn)
00094                 return mconn->read()->front();
00095             return T();
00096         }
00097 
00101         void clear() {
00102             if (mconn)
00103                 return mconn->read()->clear();
00104         }
00105 
00111         BufferBase::size_type size() const {
00112             if (mconn)
00113                 return mconn->read()->size();
00114             return 0;
00115         }
00116 
00122         BufferBase::size_type capacity() const {
00123             if (mconn)
00124                 return mconn->read()->capacity();
00125             return 0;
00126         }
00127             
00132         bool empty() const {
00133             if (mconn)
00134                 return mconn->read()->empty();
00135             return 0;
00136         }
00137             
00142         bool full() const {
00143             if (mconn)
00144                 return mconn->read()->full();
00145             return 0;
00146         }
00147 
00148         virtual PortType getPortType() const { return ReadPort; }
00149 
00150         virtual const TypeInfo* getTypeInfo() const { return detail::DataSourceTypeInfo<T>::getTypeInfo(); }
00151 
00156         ReadBufferPort& operator=(BufferInterface<T>* impl);
00157 
00158         bool connected() const { return mconn; };
00159 
00163         virtual bool connect( typename ReadConnectionInterface<T>::shared_ptr conn) {
00164             if ( mconn || !conn )
00165                 return false;
00166             mconn = conn;
00167             return true;
00168         }
00169 
00170         void disconnect() {
00171             mconn = 0;
00172         }
00173 
00174         using PortInterface::connectTo;
00175         bool connectTo( ConnectionInterface::shared_ptr other) {
00176             return other && !mconn && other->addReader( this );
00177         }
00178 
00184         virtual ReadInterface<T>* read() const { return mconn ? mconn->read() : 0; }
00185 
00186         virtual ConnectionInterface::shared_ptr connection() const { return mconn; }
00187 
00188         virtual PortInterface* clone() const {
00189             return new ReadBufferPort<T>( this->getName() );
00190         }
00191 
00196         virtual PortInterface* antiClone() const;
00197 
00198         virtual TaskObject* createPortObject() {
00199 #ifndef ORO_EMBEDDED
00200             TaskObject* to = new TaskObject( this->getName() );
00201             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00202                                       "Check if this port is connected and ready for use.");
00203             to->methods()->addMethod(method("Pop", &ReadBufferPort<T>::Pop, this),
00204                                      "Pop a single value from the Buffer. Returns false if empty.",
00205                                      "Val", "The value returned by argument.");
00206             to->methods()->addMethod(method("front", &ReadBufferPort<T>::front, this),
00207                                      "Get the next to be popped value from the buffer. Returns default value if buffer is empty.");
00208             to->methods()->addMethod(method("size", &ReadBufferPort<T>::size, this),
00209                                      "Get the used size of the buffer.");
00210             to->methods()->addMethod(method("capacity", &ReadBufferPort<T>::capacity, this),
00211                                      "Get the capacity of the buffer.");
00212             to->methods()->addMethod(method("empty", &ReadBufferPort<T>::empty, this),
00213                                      "Inspect if the buffer is empty.");
00214             to->methods()->addMethod(method("full", &ReadBufferPort<T>::full, this),
00215                                      "Inspect if the buffer is full.");
00216             to->methods()->addMethod(method("clear", &ReadBufferPort<T>::clear, this),
00217                                      "Clear the contents of the buffer.");
00218             return to;
00219 #else
00220             return 0;
00221 #endif
00222         }
00223     };
00224 
00232     template<class T>
00233     class WriteBufferPort
00234         : public virtual PortInterface
00235     {
00236     protected:
00240         typename WriteConnectionInterface<T>::shared_ptr mconn;
00241 
00242         size_t buf_size;
00243 
00244         T minitial_value;
00245     public:
00253         WriteBufferPort(const std::string& name, size_t preferred_size, const T& initial_value = T() )
00254             : PortInterface(name), mconn(), buf_size(preferred_size), minitial_value(initial_value) {}
00255 
00256         ~WriteBufferPort() {
00257             if (mconn) 
00258                 mconn->removeWriter(this);
00259         }
00260 
00266         void setBufferSize(size_t b_size) { buf_size = b_size; }
00267 
00274         bool Push(const T& data)
00275         {
00276             if (mconn)
00277                 return mconn->write()->Push(data);
00278             return false;
00279         }
00280 
00287         void Set(const T& data)
00288         {
00289             minitial_value = data;
00290         }
00291 
00295         void clear() {
00296             if (mconn)
00297                 return mconn->write()->clear();
00298         }
00299 
00305         BufferBase::size_type size() const {
00306             if (mconn)
00307                 return mconn->write()->size();
00308             return 0;
00309         }
00310 
00316         BufferBase::size_type capacity() const {
00317             if (mconn)
00318                 return mconn->write()->capacity();
00319             return 0;
00320         }
00321             
00326         bool empty() const {
00327             if (mconn)
00328                 return mconn->write()->empty();
00329             return 0;
00330         }
00331             
00336         bool full() const {
00337             if (mconn)
00338                 return mconn->write()->full();
00339             return 0;
00340         }
00341 
00342         bool connected() const { return mconn; };
00343 
00347         virtual bool connect(typename WriteConnectionInterface<T>::shared_ptr conn) { 
00348             if ( mconn  || !conn  )
00349                 return false;
00350             mconn = conn;
00351             return true;
00352         }
00353 
00354         using PortInterface::connectTo;
00355         bool connectTo( ConnectionInterface::shared_ptr other) {
00356             return other && !mconn && other->addWriter( this );
00357         }
00358 
00359         void disconnect() {
00360             mconn = 0;
00361         }
00362 
00367         virtual WriteInterface<T>* write() const { return mconn ? mconn->write() : 0; }
00368 
00369         virtual ConnectionInterface::shared_ptr connection() const { return mconn; }
00370 
00371         virtual PortType getPortType() const { return WritePort; }
00372 
00373         virtual const TypeInfo* getTypeInfo() const { return detail::DataSourceTypeInfo<T>::getTypeInfo(); }
00374 
00379         WriteBufferPort& operator=(BufferInterface<T>* impl);
00380 
00381         ConnectionInterface::shared_ptr createConnection(PortInterface* other, ConnectionTypes::ConnectionType con_type = ConnectionTypes::lockfree);
00382 
00383         ConnectionInterface::shared_ptr createConnection(ConnectionTypes::ConnectionType con_type = ConnectionTypes::lockfree);
00384 
00385         virtual PortInterface* clone() const {
00386             return new WriteBufferPort<T>( this->getName(), buf_size, minitial_value );
00387         }
00388 
00389         virtual PortInterface* antiClone() const {
00390             return new ReadBufferPort<T>( this->getName() );
00391         }
00392 
00393         virtual TaskObject* createPortObject() {
00394 #ifndef ORO_EMBEDDED
00395             TaskObject* to = new TaskObject( this->getName() );
00396             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00397                                       "Check if this port is connected and ready for use.");
00398             to->methods()->addMethod(method("Push", &WriteBufferPort<T>::Push, this),
00399                                      "Push a single value in the Buffer. Returns false if full().",
00400                                      "Val", "The value.");
00401             to->methods()->addMethod(method("size", &WriteBufferPort<T>::size, this),
00402                                      "Get the used size of the buffer.");
00403             to->methods()->addMethod(method("capacity", &WriteBufferPort<T>::capacity, this),
00404                                      "Get the capacity of the buffer.");
00405             to->methods()->addMethod(method("empty", &WriteBufferPort<T>::empty, this),
00406                                      "Inspect if the buffer is empty.");
00407             to->methods()->addMethod(method("full", &WriteBufferPort<T>::full, this),
00408                                      "Inspect if the buffer is full.");
00409             to->methods()->addMethod(method("clear", &WriteBufferPort<T>::clear, this),
00410                                      "Clear the contents of the buffer.");
00411             return to;
00412 #else
00413             return 0;
00414 #endif
00415         }
00416     };
00417 
00418 
00427     template<class T>
00428     class BufferPort
00429         : public WriteBufferPort<T>, public ReadBufferPort<T>
00430     {
00431     protected:
00435         typename BufferConnectionInterface<T>::shared_ptr mconn;
00436 
00437     public:
00438         typedef PortInterface::PortType PortType;
00439 
00444         BufferPort(const std::string& name, size_t prefered_size, const T& initial_value = T())
00445             : PortInterface(name), WriteBufferPort<T>(name,prefered_size, initial_value), ReadBufferPort<T>(name), mconn() {}
00446 
00447         ~BufferPort() {
00448             if (mconn) {
00449                 mconn->removeReader(this);
00450                 mconn->removeWriter(this);
00451             }
00452         }
00453 
00457         void clear() {
00458             if (mconn)
00459                 return mconn->buffer()->clear();
00460         }
00461 
00467         BufferBase::size_type size() const {
00468             if (mconn)
00469                 return mconn->buffer()->size();
00470             return 0;
00471         }
00472 
00478         BufferBase::size_type capacity() const {
00479             if (mconn)
00480                 return mconn->buffer()->capacity();
00481             return 0;
00482         }
00483             
00488         bool empty() const {
00489             if (mconn)
00490                 return mconn->buffer()->empty();
00491             return 0;
00492         }
00493             
00498         bool full() const {
00499             if (mconn)
00500                 return mconn->buffer()->full();
00501             return 0;
00502         }
00503 
00504         bool connected() const { return mconn; };
00505 
00509         bool connect(typename BufferConnectionInterface<T>::shared_ptr conn) { 
00510             if ( (mconn && conn != mconn) || !conn ) // allow to connect twice to same connection.
00511                 return false;
00512             mconn = conn;
00513             WriteBufferPort<T>::connect(conn);
00514             ReadBufferPort<T>::connect(conn);
00515             return true;
00516         }
00517 
00518         virtual bool connect(typename WriteConnectionInterface<T>::shared_ptr conn) { 
00519             if ( this->connect( boost::dynamic_pointer_cast<BufferConnectionInterface<T> >(conn) ) ) {
00520                  WriteBufferPort<T>::connect(mconn);
00521                  ReadBufferPort<T>::connect(mconn);
00522                  return true;
00523             }
00524             return false;
00525         }
00526 
00527         virtual bool connect(typename ReadConnectionInterface<T>::shared_ptr conn) {
00528             if ( this->connect( boost::dynamic_pointer_cast<BufferConnectionInterface<T> >(conn) ) ) {
00529                  WriteBufferPort<T>::connect(mconn);
00530                  ReadBufferPort<T>::connect(mconn);
00531                  return true;
00532             }
00533             return false;
00534         }
00535 
00536         using PortInterface::connectTo;
00537         bool connectTo( ConnectionInterface::shared_ptr other) {
00538             if ( other && !mconn ) {
00539                 return other->addWriter( this ) && other->addReader( this );
00540             }
00541             return false;
00542         }
00543 
00544         void disconnect() {
00545             mconn = 0;
00546             WriteBufferPort<T>::disconnect();
00547             ReadBufferPort<T>::disconnect();
00548         }
00549 
00554         virtual BufferInterface<T>* buffer() const { return mconn ? mconn->buffer() : 0; }
00555 
00556         virtual ConnectionInterface::shared_ptr connection() const { return mconn; }
00557 
00558         virtual PortType getPortType() const { return PortInterface::ReadWritePort; }
00559 
00560         virtual const TypeInfo* getTypeInfo() const { return detail::DataSourceTypeInfo<T>::getTypeInfo(); }
00561 
00566         BufferPort& operator=(BufferInterface<T>* impl);
00567 
00568         virtual PortInterface* clone() const {
00569             return new BufferPort<T>( this->getName(), this->buf_size, this->minitial_value );
00570         }
00571 
00572         virtual PortInterface* antiClone() const {
00573             return this->clone();
00574         }
00575 
00576         virtual TaskObject* createPortObject() {
00577 #ifndef ORO_EMBEDDED
00578             TaskObject* to = new TaskObject( this->getName() );
00579             to->methods()->addMethod( method("ready",&PortInterface::ready, this),
00580                                       "Check if this port is connected and ready for use.");
00581             to->methods()->addMethod(method("Push", &WriteBufferPort<T>::Push, this),
00582                                      "Push a single value in the Buffer. Returns false if full().",
00583                                      "Val", "The value.");
00584             to->methods()->addMethod(method("Pop", &ReadBufferPort<T>::Pop, this),
00585                                      "Pop a single value from the Buffer. Returns false if empty.",
00586                                      "Val", "The value returned by argument.");
00587             to->methods()->addMethod(method("front", &ReadBufferPort<T>::front, this),
00588                                      "Get the next to be popped value from the buffer. Returns default value if buffer is empty.");
00589             to->methods()->addMethod(method("size", &BufferPort<T>::size, this),
00590                                      "Get the used size of the buffer.");
00591             to->methods()->addMethod(method("capacity", &BufferPort<T>::capacity, this),
00592                                      "Get the capacity of the buffer.");
00593             to->methods()->addMethod(method("empty", &BufferPort<T>::empty, this),
00594                                      "Inspect if the buffer is empty.");
00595             to->methods()->addMethod(method("full", &BufferPort<T>::full, this),
00596                                      "Inspect if the buffer is full.");
00597             to->methods()->addMethod(method("clear", &BufferPort<T>::clear, this),
00598                                      "Clear the contents of the buffer.");
00599             return to;
00600 #else
00601             return 0;
00602 #endif
00603         }
00604     };
00605 }
00606 #endif
00607 
00608 #ifndef ORO_BUFFER_PORT_INLINE
00609 #define ORO_BUFFER_PORT_INLINE
00610 
00611 #include "ConnectionFactory.hpp"
00612 #include "BufferConnection.hpp"
00613 
00614 namespace RTT
00615 {
00616 
00617     template<class T>
00618     PortInterface* ReadBufferPort<T>::antiClone() const {
00619         return new WriteBufferPort<T>( this->getName(), 1 );
00620     }
00621 
00622     template<class T>
00623     ReadBufferPort<T>& ReadBufferPort<T>::operator=(BufferInterface<T>* impl)
00624     {
00625         if ( !mconn ) {
00626             ConnectionInterface::shared_ptr con = new BufferConnection<T>(impl);
00627             this->connectTo(con);
00628             con->connect();
00629         } else
00630             mconn->setImplementation(impl);
00631         return *this;
00632     }
00633 
00634     template<class T>
00635     WriteBufferPort<T>& WriteBufferPort<T>::operator=(BufferInterface<T>* impl)
00636     {
00637         if ( !mconn ) {
00638             ConnectionInterface::shared_ptr con = new BufferConnection<T>(impl);
00639             this->connectTo(con);
00640             con->connect();
00641         } else
00642             mconn->setImplementation(impl);
00643         return *this;
00644     }
00645 
00646     template<class T>
00647     BufferPort<T>& BufferPort<T>::operator=(BufferInterface<T>* impl)
00648     {
00649         if ( !connected() ) {
00650             ConnectionInterface::shared_ptr con = new BufferConnection<T>(impl);
00651             this->connectTo(con);
00652             con->connect();
00653         } else
00654             mconn->setImplementation(impl);
00655         return *this;
00656     }
00657 
00658     template<class T>
00659     ConnectionInterface::shared_ptr WriteBufferPort<T>::createConnection(PortInterface* other, ConnectionTypes::ConnectionType con_type )
00660         {
00661             ConnectionFactory<T> cf;
00662             return ConnectionInterface::shared_ptr (cf.createBuffer(this, other, buf_size, minitial_value, con_type));
00663         }
00664 
00665     template<class T>
00666     ConnectionInterface::shared_ptr WriteBufferPort<T>::createConnection(ConnectionTypes::ConnectionType con_type )
00667         {
00668             ConnectionFactory<T> cf;
00669             ConnectionInterface::shared_ptr res = cf.createBuffer(buf_size, minitial_value, con_type);
00670             res->addWriter(this);
00671             return res;
00672         }
00673 }
00674 #endif

Generated on Tue Mar 25 17:41:40 2008 for OrocosReal-TimeToolkit by  doxygen 1.5.3