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
|
providerImpl.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_IMPL_H 00012 #define ORCA_PROVIDER_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 00037 // template<class ProviderType, class ProviderPrxType, class ConsumerType, class ConsumerPrxType, class DataType> 00038 template<class ProviderType, class ConsumerType, class DataType> 00039 class ProviderImpl : public IceUtil::Shared 00040 { 00041 typedef typename ProviderType::ProxyType ProviderPrxType; 00042 typedef typename ConsumerType::ProxyType ConsumerPrxType; 00043 00044 friend class ProviderTypeI; 00045 00046 public: 00048 ProviderImpl( const std::string& interfaceTag, const orcaice::Context& context ) : 00049 isDataSet_(false), 00050 interfaceName_(orcaice::getProvidedInterface(context,interfaceTag).iface), 00051 context_(context) 00052 { 00053 init(); 00054 } 00055 00057 ProviderImpl( const orcaice::Context& context, const std::string& interfaceName ) : 00058 isDataSet_(false), 00059 interfaceName_(interfaceName), 00060 context_(context) 00061 { 00062 init(); 00063 } 00064 00065 ~ProviderImpl() 00066 { 00067 orcaice::tryRemoveInterface( context_, interfaceName_ ); 00068 } 00069 00070 // local interface: 00073 void initInterface() 00074 { 00075 topicHandler_->connectToTopic(); 00076 orcaice::createInterfaceWithString( context_, ptr_, interfaceName_ ); 00077 } 00079 void initInterface( const DataType& data ) 00080 { 00081 // by setting the data first we avoid the possibility of initializing the interface 00082 // but not having the data in it. 00083 localSet( data ); 00084 00085 topicHandler_->connectToTopic(); 00086 topicHandler_->publish( data ); 00087 orcaice::createInterfaceWithString( context_, ptr_, interfaceName_ ); 00088 } 00089 00092 void initInterface( gbxutilacfr::Stoppable* activity, const std::string& subsysName="", int retryInterval=2 ) 00093 { 00094 topicHandler_->connectToTopic( activity, subsysName, retryInterval ); 00095 orcaice::createInterfaceWithString( context_, ptr_, interfaceName_, activity, subsysName, retryInterval ); 00096 } 00098 void initInterface( const DataType& data, 00099 gbxutilacfr::Stoppable* activity, const std::string& subsysName="", int retryInterval=2 ) 00100 { 00101 // by setting the data first we avoid the possibility of initializing the interface 00102 // but not having the data in it. 00103 localSet( data ); 00104 00105 topicHandler_->connectToTopic( activity, subsysName, retryInterval ); 00106 topicHandler_->publish( data ); 00107 orcaice::createInterfaceWithString( context_, ptr_, interfaceName_, activity, subsysName, retryInterval ); 00108 } 00109 00111 void localSend( const DataType& data ) 00112 { 00113 topicHandler_->publish(data); 00114 } 00115 00117 void localSet( const DataType& data ) 00118 { 00119 IceUtil::Mutex::Lock lock(mutex_); 00120 data_ = data; 00121 isDataSet_ = true; 00122 } 00123 00126 void localSetAndSend( const DataType& data ) 00127 { 00128 { 00129 IceUtil::Mutex::Lock lock(mutex_); 00130 data_ = data; 00131 isDataSet_ = true; 00132 } 00133 topicHandler_->publish( data ); 00134 } 00135 00140 void localSetAndSend( const DataType& dataToSet, const DataType& dataToSend ) 00141 { 00142 // By sending first, we avoid the possibility that a client 00143 // gets our data on subscription then gets pushed the update. 00144 topicHandler_->publish( dataToSend ); 00145 { 00146 IceUtil::Mutex::Lock lock(mutex_); 00147 data_ = dataToSet; 00148 isDataSet_ = true; 00149 } 00150 } 00151 00152 private: 00153 // 00154 // This is the implementation of the slice-defined interface 00155 // 00156 class ProviderTypeI : public ProviderType 00157 { 00158 public: 00159 ProviderTypeI( ProviderImpl &impl ) 00160 : impl_(impl) {} 00161 DataType getData(const Ice::Current&) 00162 { return impl_.internalGetData(); } 00163 virtual IceStorm::TopicPrx subscribe(const ConsumerPrxType& subscriber, const ::Ice::Current& = ::Ice::Current()) 00164 { return impl_.internalSubscribe(subscriber); } 00165 private: 00166 ProviderImpl &impl_; 00167 }; 00169 00170 // Holds the current data 00171 DataType data_; 00172 bool isDataSet_; 00173 // Protects the data_ 00174 IceUtil::Mutex mutex_; 00175 00176 typedef orcaice::TopicHandler<ConsumerPrxType,DataType> TopicHandlerType; 00177 std::auto_ptr<TopicHandlerType> topicHandler_; 00178 00179 Ice::ObjectPtr ptr_; 00180 const std::string interfaceName_; 00181 orcaice::Context context_; 00182 00183 void init() 00184 { 00185 ptr_ = new ProviderTypeI( *this ); 00186 00187 topicHandler_.reset( new TopicHandlerType( orcaice::toTopicAsString(context_.name(),interfaceName_), context_ ) ); 00188 } 00189 00190 // remote call implementations, mimic (but do not inherit) the orca interface 00191 DataType internalGetData() const 00192 { 00193 context_.tracer().debug( "ProviderImpl::internalGetData()", 5 ); 00194 00195 IceUtil::Mutex::Lock lock(mutex_); 00196 if ( !isDataSet_ ) 00197 { 00198 std::stringstream ss; 00199 ss << "No data available! (interface="<<interfaceName_<<")"; 00200 throw orca::DataNotExistException( ss.str() ); 00201 } 00202 return data_; 00203 } 00204 00205 IceStorm::TopicPrx internalSubscribe(const ConsumerPrxType& subscriber) 00206 { 00207 if ( !topicHandler_.get() ) 00208 { 00209 throw orca::SubscriptionFailedException("topicHandler_ does not exist."); 00210 } 00211 00212 // Grab the data in a crit section 00213 DataType data; 00214 bool gotData = false; 00215 { 00216 IceUtil::Mutex::Lock lock(mutex_); 00217 if ( isDataSet_ ) 00218 { 00219 data = data_; 00220 gotData = true; 00221 } 00222 } 00223 00224 // EXPERIMENTAL! 00225 IceStorm::QoS qos; 00226 qos["reliability"] = "ordered"; 00227 00228 // if we have data, send all the information we have to the new subscriber (and to no one else) 00229 if ( gotData ) 00230 { 00231 return topicHandler_->subscribe( subscriber, data, qos ); 00232 } 00233 else 00234 { 00235 return topicHandler_->subscribe( subscriber, qos ); 00236 } 00237 } 00238 }; 00239 00240 } 00241 00242 #endif |
Webmaster: Tobias Kaupp (tobasco at users.sourceforge.net)