DataObjectInterfaces.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Mon Jan 19 14:11:26 CET 2004  DataObjectInterfaces.hpp
00003 
00004                         DataObjectInterfaces.hpp -  description
00005                            -------------------
00006     begin                : Mon January 19 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.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 #ifndef CORELIB_DATAOBJECTINTERFACES_HPP
00039 #define CORELIB_DATAOBJECTINTERFACES_HPP
00040 
00041 
00042 #include "os/MutexLock.hpp"
00043 #include "os/oro_atomic.h"
00044 #include <string>
00045 
00046 #include "DataSource.hpp"
00047 
00048 namespace RTT
00049 {
00050 
00063     template <class T>
00064     class DataObjectInterface
00065         : public AssignableDataSource<T>
00066     {
00067     public:
00072         typedef typename boost::intrusive_ptr<DataObjectInterface<T> > shared_ptr;
00073 
00077         DataObjectInterface() {
00078             this->ref();
00079         }
00080 
00084         virtual ~DataObjectInterface() {}
00085 
00089         typedef T DataType;
00090 
00096         virtual void Get( DataType& pull ) const = 0;
00097 
00103         virtual DataType Get() const = 0;
00104 
00110         virtual void Set( const DataType& push ) = 0;
00111 
00117         virtual const std::string& getName() const = 0;
00118 
00124         typename DataSource<T>::result_t value() const {
00125             return this->Get();
00126         }
00127 
00128         virtual typename DataSource<DataType>::result_t get() const {
00129             return this->Get();
00130         }
00131 
00132         virtual void set( typename AssignableDataSource<DataType>::param_t t ) {
00133             this->Set( t );
00134         }
00135 
00136         virtual typename AssignableDataSource<DataType>::reference_t set() {
00137             // return null reference, allowed by API.
00138             typename DataSource<DataType>::value_t* tmp = 0;
00139             return typename AssignableDataSource<DataType>::reference_t(*tmp);
00140         }
00141 
00142         virtual typename AssignableDataSource<DataType>::const_reference_t rvalue() const {
00143             // return null reference, allowed by API.
00144             typename DataSource<DataType>::value_t* tmp = 0;
00145             return typename AssignableDataSource<DataType>::const_reference_t(*tmp);
00146         }
00147 
00148     };
00149 
00150 
00160     template<class T>
00161     class DataObjectLocked
00162         : public DataObjectInterface<T>
00163     {
00164         mutable OS::Mutex lock;
00165 
00169         T data;
00170 
00171         std::string name;
00172     public:
00178         DataObjectLocked(const std::string& _name, const T& initial_value = T() )
00179             : data(initial_value), name(_name) {}
00180 
00186         const std::string& getName() const { return name;}
00187 
00188         void setName( const std::string& _name )
00189         {
00190             name = _name;
00191         }
00192 
00196         typedef T DataType;
00197 
00203         void Get( DataType& pull ) const { OS::MutexLock locker(lock); pull = data; }
00204 
00211         DataType Get() const { DataType cache;  Get(cache); return cache; }
00212 
00218         void Set( const DataType& push ) { OS::MutexLock locker(lock); data = push; }
00219 
00220         DataObjectLocked<DataType>* clone() const {
00221             return new DataObjectLocked<DataType>(name);
00222         }
00223 
00224         DataObjectLocked<DataType>* copy( std::map<const DataSourceBase*, DataSourceBase*>&  ) const {
00225             return const_cast<DataObjectLocked<DataType>*>(this);
00226         }
00227     };
00228 
00256     template<class T>
00257     class DataObjectPrioritySet
00258         : public DataObjectInterface<T>
00259     {
00260         mutable OS::Mutex lock;
00261         mutable bool dirty_flag;
00262 
00266         T data;
00267         T mcopy;
00268 
00269         std::string name;
00270     public:
00276         DataObjectPrioritySet(const std::string& _name, const T& initial_value = T() )
00277             : data(initial_value), mcopy(), name(_name) {}
00278 
00284         const std::string& getName() const { return name;}
00285 
00286         void setName( const std::string& _name )
00287         {
00288             name = _name;
00289         }
00290 
00294         typedef T DataType;
00295 
00301         void Get( DataType& pull ) const
00302         { if (dirty_flag) pull = mcopy; else {OS::MutexLock locker(lock); pull = data;} }
00303 
00309         DataType Get() const { DataType cache; Get(cache); return cache; }
00310 
00316         void Set( const DataType& push )
00317         {
00318             OS::MutexTryLock locker(lock);
00319             if (locker.isSuccessful())
00320                 {data = push; dirty_flag = false;}
00321             else
00322                 {mcopy = push; dirty_flag = true;}
00323         }
00324 
00325         DataObjectPrioritySet<DataType>* clone() const {
00326             return new DataObjectPrioritySet<DataType>(name);
00327         }
00328 
00329         DataObjectPrioritySet<DataType>* copy( std::map<const DataSourceBase*, DataSourceBase*>&  ) const {
00330             return const_cast<DataObjectPrioritySet<DataType>*>(this);
00331         }
00332     };
00333 
00364     template<class T>
00365     class DataObjectPriorityGet
00366         : public DataObjectInterface<T>
00367     {
00368         mutable OS::Mutex lock;
00369 
00373         T data;
00374         T mcopy;
00375 
00376         std::string name;
00377     public:
00383         DataObjectPriorityGet(const std::string& _name, const T& initial_value = T()  )
00384             : data(initial_value), mcopy(), name(_name) {}
00385 
00391         const std::string& getName() const { return name;}
00392 
00393         void setName( const std::string& _name )
00394         {
00395             name = _name;
00396         }
00397 
00401         typedef T DataType;
00402 
00408         void Get( DataType& pull ) const
00409         {
00410             // If two low priority gets access this method,
00411             // while Set() is in copy,
00412             // the second one will pull in the copy which
00413             // is modified by the Set().
00414             OS::MutexTryLock locker(lock);
00415             if ( locker.isSuccessful() )
00416                 {pull = data;}
00417             else
00418                 {pull = mcopy;}
00419         }
00420 
00426         DataType Get() const { DataType cache; Get(cache); return cache; }
00427 
00433         void Set( const DataType& push )
00434         {
00435             {
00436                 OS::MutexLock locker(lock);
00437                 data = push;
00438             }
00439             mcopy = data;
00440         }
00441 
00442         DataObjectPriorityGet<DataType>* clone() const {
00443             return new DataObjectPriorityGet<DataType>(name);
00444         }
00445 
00446         DataObjectPriorityGet<DataType>* copy( std::map<const DataSourceBase*, DataSourceBase*>&  ) const {
00447             return const_cast<DataObjectPriorityGet<DataType>*>(this);
00448         }
00449     };
00450 
00479     template<class T>
00480     class DataObjectLockFree
00481         : public DataObjectInterface<T>
00482     {
00483     public:
00487         typedef T DataType;
00488 
00497         static const unsigned int MAX_THREADS=8;
00498     private:
00502         static const unsigned int BUF_LEN=MAX_THREADS+2;
00503 
00511         struct DataBuf {
00512             DataBuf()
00513                 : data(), counter(), next()
00514             {
00515                 oro_atomic_set(&counter, 0);
00516             }
00517             DataType data; mutable oro_atomic_t counter; DataBuf* next;
00518         };
00519 
00520         typedef DataBuf* volatile VolPtrType;
00521         typedef DataBuf  ValueType;
00522         typedef DataBuf* PtrType;
00523 
00524         VolPtrType read_ptr;
00525         VolPtrType write_ptr;
00526 
00530         DataBuf data[BUF_LEN];
00531 
00532         std::string name;
00533 
00534     public:
00535 
00542         DataObjectLockFree(const std::string& _name, const T& initial_value = T() )
00543             : read_ptr(&data[ 0 ]),
00544               write_ptr(&data[ 1 ]),
00545               name(_name)
00546         {
00547             // prepare the buffer.
00548             for (unsigned int i = 0; i < BUF_LEN-1; ++i) {
00549                 data[i].data = initial_value;
00550                 data[i].next = &data[i+1];
00551             }
00552             data[BUF_LEN-1].next = &data[0];
00553         }
00554 
00560         const std::string& getName() const { return name;}
00561 
00562         void setName( const std::string& _name )
00563         {
00564             name = _name;
00565         }
00566 
00574         DataType Get() const {DataType cache; Get(cache); return cache; }
00575 
00583         void Get( DataType& pull ) const
00584         {
00585             PtrType reading;
00586             // loop to combine Read/Modify of counter
00587             // This avoids a race condition where read_ptr
00588             // could become write_ptr ( then we would read corrupted data).
00589             do {
00590                 reading = read_ptr;            // copy buffer location
00591                 oro_atomic_inc(&reading->counter); // lock buffer, no more writes
00592                 if ( reading != read_ptr )     // if read_ptr changed,
00593                     oro_atomic_dec(&reading->counter); // better to start over.
00594                 else
00595                     break;
00596             } while ( true );
00597             // from here on we are sure that 'reading'
00598             // is a valid buffer to read from.
00599             pull = reading->data;               // takes some time
00600             oro_atomic_dec(&reading->counter);       // release buffer
00601         }
00602 
00608         void Set( const DataType& push )
00609         {
00618             // writeout in any case
00619             write_ptr->data = push;
00620             PtrType wrote_ptr = write_ptr;
00621             // if next field is occupied (by read_ptr or counter),
00622             // go to next and check again...
00623             while ( oro_atomic_read( &write_ptr->next->counter ) != 0 || write_ptr->next == read_ptr )
00624                 {
00625                     write_ptr = write_ptr->next;
00626                     if (write_ptr == wrote_ptr)
00627                         return; // nothing found, to many readers !
00628                 }
00629 
00630             // we will be able to move, so replace read_ptr
00631             read_ptr  = wrote_ptr;
00632             write_ptr = write_ptr->next; // we checked this in the while loop
00633         }
00634 
00635         DataObjectLockFree<DataType>* clone() const {
00636             return new DataObjectLockFree<DataType>(name);
00637         }
00638 
00639         DataObjectLockFree<DataType>* copy( std::map<const DataSourceBase*, DataSourceBase*>&  ) const {
00640             return const_cast<DataObjectLockFree<DataType>*>(this);
00641         }
00642 
00643     };
00644 
00652     template<class T>
00653     class DataObject
00654         : public DataObjectInterface<T>
00655     {
00659         T data;
00660 
00661         std::string name;
00662     public:
00668         DataObject(const std::string& _name, const T& initial_value = T()  )
00669             : data(initial_value), name(_name) {}
00670 
00676         const std::string& getName() const { return name;}
00677 
00678         void setName( const std::string& _name )
00679         {
00680             name = _name;
00681         }
00682 
00686         typedef T DataType;
00687 
00693         void Get( DataType& pull ) const { pull = data; }
00694 
00700         DataType Get() const { return data; }
00701 
00707         void Set( const DataType& push ) { data = push; }
00708 
00709         DataObject<DataType>* clone() const {
00710             return new DataObject<DataType>(name);
00711         }
00712 
00713         DataObject<DataType>* copy( std::map<const DataSourceBase*, DataSourceBase*>&  ) const {
00714             return const_cast<DataObject<DataType>*>(this);
00715         }
00716 
00717     };
00718 }
00719 
00720 #endif
00721 
Generated on Thu Dec 23 13:22:37 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3