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 Project Download Mailing lists
|
providerWithDescriptionImpl.h00001 /* 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)