INTRODUCTION
Overview
Download and Install
Quick Start
Documentation
Publications

NONFRAMEWORK CODE
Driver Interfaces
Drivers
Libraries
Utilities

FRAMEWORK CODE
Interfaces
Components
Libraries
Utilities

Full Software Listings

DEVELOPER
Tutorials
Examples
Dev Guide
Dashboard

PEOPLE
Contributors
Users

SourceForge.net Logo
Project
Download
Mailing lists

 

         

providerWithDescriptionImpl.h

00001 /*
00002  * Orca-Robotics Project: Components for robotics 
00003  *               http://orca-robotics.sf.net/
00004  * Copyright (c) 2004-2009 Alex Brooks, Alexei Makarenko, Tobias Kaupp
00005  *
00006  * This copy of Orca is licensed to you under the terms described in
00007  * the LICENSE file included in this distribution.
00008  *
00009  */
00010 
00011 #ifndef ORCA_PROVIDER_WITH_DESCRIPTION_IMPL_H
00012 #define ORCA_PROVIDER_WITH_DESCRIPTION_IMPL_H
00013 
00014 #include <memory>
00015 #include <orcaice/context.h>
00016 #include <orcaice/topichandler.h>
00017 #include <orcaice/configutils.h>
00018 #include <orcaice/convertutils.h>
00019 #include <orcaice/iceutils.h>
00020 #include <orcaice/multiiceutils.h>
00021 #include <IceUtil/Mutex.h>
00022 
00023 namespace gbxutilacfr { class Stoppable; }
00024 
00025 namespace orcaifaceimpl {
00026 
00038 // template<class ProviderType, class ProviderPrxType, class ConsumerType, class ConsumerPrxType, class DataType, class DescriptionType>
00039 template<class ProviderType, class ConsumerType, class DataType, class DescriptionType>
00040 class ProviderWithDescriptionImpl : public IceUtil::Shared
00041 {
00042 typedef typename ProviderType::ProxyType ProviderPrxType;
00043 typedef typename ConsumerType::ProxyType ConsumerPrxType;
00044 
00045 friend class ProviderTypeI;
00046 
00047 public:
00051     ProviderWithDescriptionImpl( const DescriptionType& descr, const std::string& interfaceTag, const orcaice::Context& context ) :
00052         descr_(descr),
00053         isDataSet_(false),
00054         interfaceName_(orcaice::getProvidedInterface(context,interfaceTag).iface),
00055         context_(context)
00056     {
00057         init();
00058     }
00059 
00061     ProviderWithDescriptionImpl( const DescriptionType& descr, const orcaice::Context& context, const std::string& interfaceName ) :
00062         descr_(descr),
00063         isDataSet_(false),
00064         interfaceName_(interfaceName),
00065         context_(context)
00066     {
00067         init();
00068     }           
00069 
00070     ~ProviderWithDescriptionImpl()
00071     {
00072         orcaice::tryRemoveInterface( context_, interfaceName_ );
00073     }
00074 
00075     // local interface:
00078     void initInterface()
00079     {
00080         // Set up the topic before creating the interface, so no-one
00081         // can subscribe before the topic is kosher.
00082         topicHandler_->connectToTopic();
00083         orcaice::createInterfaceWithString( context_, ptr_, interfaceName_ );    
00084     }
00086     void initInterface( const DataType& data )
00087     {
00088         // by setting the data first we avoid the possibility of initializing the interface
00089         // but not having the data in it.
00090         localSet( data );
00091 
00092         // Set up the topic before creating the interface, so no-one
00093         // can subscribe before the topic is kosher.
00094         topicHandler_->connectToTopic();
00095         topicHandler_->publish( data );
00096         orcaice::createInterfaceWithString( context_, ptr_, interfaceName_ );    
00097     }
00098 
00101     void initInterface( gbxutilacfr::Stoppable* activity, const std::string& subsysName="", int retryInterval=2 )
00102     {
00103         topicHandler_->connectToTopic( activity, subsysName, retryInterval );
00104         orcaice::createInterfaceWithString( context_, ptr_, interfaceName_, activity, subsysName, retryInterval );
00105     }
00107     void initInterface( const DataType& data, 
00108                         gbxutilacfr::Stoppable* activity, const std::string& subsysName="", int retryInterval=2 )
00109     {
00110         // by setting the data first we avoid the possibility of initializing the interface
00111         // but not having the data in it.
00112         localSet( data );
00113 
00114         topicHandler_->connectToTopic( activity, subsysName, retryInterval );
00115         topicHandler_->publish( data );
00116         orcaice::createInterfaceWithString( context_, ptr_, interfaceName_, activity, subsysName, retryInterval );
00117     }
00118 
00120     void localSet( const DataType& data )
00121     {
00122         IceUtil::Mutex::Lock lock(mutex_);
00123         data_ = data;
00124         isDataSet_ = true;
00125     }
00126 
00128     void localSend( const DataType& data )
00129     {
00130         topicHandler_->publish(data);
00131     }
00132 
00135     void localSetAndSend( const DataType& data )
00136     {
00137         {
00138             IceUtil::Mutex::Lock lock(mutex_);
00139             data_ = data;
00140             isDataSet_ = true;
00141         }
00142         topicHandler_->publish( data );
00143     }
00144 
00149     void localSetAndSend( const DataType& dataToSet, const DataType& dataToSend )
00150     {
00151         // By sending first, we avoid the possibility that a client
00152         // gets our data on subscription then gets pushed the update.
00153         topicHandler_->publish( dataToSend );
00154         {
00155             IceUtil::Mutex::Lock lock(mutex_);
00156             data_ = dataToSet;
00157             isDataSet_ = true;
00158         }
00159     }
00160 
00161 private:    
00162     //
00163     // This is the implementation of the slice-defined interface
00164     //
00165     class ProviderTypeI : public ProviderType
00166     {
00167     public:
00168         ProviderTypeI( ProviderWithDescriptionImpl &impl )
00169             : impl_(impl) {}
00170         virtual DescriptionType getDescription(const ::Ice::Current&)
00171             { return impl_.internalGetDescription(); }
00172         virtual DataType getData(const Ice::Current&)
00173             { return impl_.internalGetData(); }
00174         virtual IceStorm::TopicPrx subscribe(const ConsumerPrxType& subscriber, const ::Ice::Current& = ::Ice::Current())
00175             { return impl_.internalSubscribe(subscriber); }
00176     private:
00177         ProviderWithDescriptionImpl &impl_;
00178     };
00180 
00181     DescriptionType descr_;
00182 
00183     // Holds the current data
00184     DataType data_;
00185     bool isDataSet_;
00186     // Protects the data_
00187     IceUtil::Mutex mutex_;
00188 
00189     typedef orcaice::TopicHandler<ConsumerPrxType,DataType> TopicHandlerType;
00190     std::auto_ptr<TopicHandlerType> topicHandler_;
00191 
00192     Ice::ObjectPtr ptr_;
00193     const std::string interfaceName_;
00194     orcaice::Context context_;
00195 
00196     void init()
00197     {
00198         topicHandler_.reset( new TopicHandlerType( orcaice::toTopicAsString(context_.name(),interfaceName_), context_ ) );    
00199         ptr_ = new ProviderTypeI( *this );
00200     }
00201 
00202     // remote call implementations, mimic (but do not inherit) the orca interface
00203     DescriptionType internalGetDescription() const
00204     {
00205         return descr_;
00206     }
00207 
00208     DataType internalGetData() const
00209     {
00210         context_.tracer().debug( "ProviderWithDescriptionImpl::internalGetData()", 5 );
00211     
00212         IceUtil::Mutex::Lock lock(mutex_);
00213         if ( !isDataSet_ )
00214         {
00215             std::stringstream ss;
00216             ss << "No data available! (interface="<<interfaceName_<<")";
00217             throw orca::DataNotExistException( ss.str() );
00218         }
00219         return data_;
00220     }
00221 
00222     IceStorm::TopicPrx internalSubscribe( const ConsumerPrxType& subscriber )
00223     {
00224         if ( !topicHandler_.get() ) 
00225         {
00226             throw orca::SubscriptionFailedException("topicHandler_ is not initialised!");
00227         }
00228         
00229         // Grab the data in a crit section
00230         DataType data;
00231         bool gotData = false;
00232         {        
00233             IceUtil::Mutex::Lock lock(mutex_);
00234             if ( isDataSet_ )
00235             {
00236                 data = data_;
00237                 gotData = true;
00238             }
00239         }
00240 
00241         // EXPERIMENTAL!
00242         IceStorm::QoS qos;
00243         qos["reliability"] = "ordered";
00244 
00245         // if we have data, send all the information we have to the new subscriber (and to no one else)
00246         if ( gotData )
00247         {
00248             return topicHandler_->subscribe( subscriber, data, qos );
00249         }
00250         else
00251         {
00252             return topicHandler_->subscribe( subscriber, qos );
00253         }
00254     }
00255 };
00256 
00257 }
00258 
00259 #endif
 

Webmaster: Tobias Kaupp (tobasco at users.sourceforge.net)


Generated for Orca Robotics by  doxygen 1.4.5