00001 #ifndef MESSAGE_TRANSPORT_PUBLISHER_IMPL_H
00002 #define MESSAGE_TRANSPORT_PUBLISHER_IMPL_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "message_transport/publisher.h"
00039 #include "message_transport/publisher_plugin.h"
00040 #include <pluginlib/class_loader.h>
00041 #include <boost/ptr_container/ptr_vector.hpp>
00042 #include <boost/foreach.hpp>
00043 #include <boost/algorithm/string/erase.hpp>
00044
00045 namespace message_transport {
00046
00047 class PublisherImplGen
00048 {
00049 public:
00050 PublisherImplGen(const std::string & topic) :
00051 base_topic_(topic), unadvertised_(false) { }
00052
00053 virtual ~PublisherImplGen()
00054 {
00055 }
00056
00057 virtual uint32_t getNumSubscribers() const = 0;
00058 uint32_t getNumSubscribersBindable() const {
00059 return this->getNumSubscribers();
00060 }
00061
00062 std::string getTopic() const
00063 {
00064 return base_topic_;
00065 }
00066
00067 bool isValid() const
00068 {
00069 return !unadvertised_;
00070 }
00071
00072 void shutdown() {
00073 this->shutdownImpl();
00074 }
00075
00076 virtual void shutdownImpl() = 0;
00077
00078 template <class M>
00079 void subscriberCB(const SingleSubscriberPublisher<M>& plugin_pub,
00080 const typename SingleSubscriberPublisher<M>::StatusCB& user_cb)
00081 {
00082 SingleSubscriberPublisher<M> ssp(plugin_pub.getSubscriberName(), this->getTopic(),
00083 boost::bind(&PublisherImplGen::getNumSubscribersBindable, this),
00084 plugin_pub.publish_fn_);
00085 user_cb(ssp);
00086 }
00087
00088 virtual std::vector<std::string> getDeclaredClasses() = 0;
00089
00090
00091 template <class M>
00092 void publish(const M& message) const;
00093
00094 template <class M>
00095 void publish(const typename M::ConstPtr& message) const;
00096
00097 protected :
00098 std::string base_topic_;
00099 bool unadvertised_;
00100
00101 };
00102
00103 template <class M>
00104 class PublisherImpl : public PublisherImplGen
00105 {
00106 public :
00107 PublisherImpl(const std::string & topic,
00108 const std::string & packageName,
00109 const std::string & className) : PublisherImplGen(topic),
00110 loader_(packageName,
00111 std::string("message_transport::PublisherPlugin<")+className+">")
00112 {
00113 }
00114
00115 virtual ~PublisherImpl() {
00116 shutdownImpl();
00117 }
00118
00119 virtual uint32_t getNumSubscribers() const
00120 {
00121 uint32_t count = 0;
00122 BOOST_FOREACH(const PublisherPlugin<M>& pub, publishers_)
00123 count += pub.getNumSubscribers();
00124 return count;
00125 }
00126
00127 virtual void shutdownImpl()
00128 {
00129 if (!unadvertised_) {
00130 unadvertised_ = true;
00131 BOOST_FOREACH(PublisherPlugin<M>& pub, publishers_)
00132 pub.shutdown();
00133 publishers_.clear();
00134 }
00135 }
00136
00137 virtual std::vector<std::string> getDeclaredClasses() {
00138 return loader_.getDeclaredClasses();
00139 }
00140
00141 PublisherPlugin<M> * addInstance(const std::string & name) {
00142 PublisherPlugin<M> * pub = loader_.createClassInstance(name);
00143 publishers_.push_back(pub);
00144 return pub;
00145 }
00146
00147 uint32_t getNumPublishers() const {
00148 return publishers_.size();
00149 }
00150
00151 void publish(const M& message) const {
00152 BOOST_FOREACH(const PublisherPlugin<M>& pub, publishers_) {
00153 if (pub.getNumSubscribers() > 0) {
00154 pub.publish(message);
00155 }
00156 }
00157 }
00158
00159 void publish(const typename M::ConstPtr& message) const {
00160 BOOST_FOREACH(const PublisherPlugin<M>& pub, publishers_) {
00161 if (pub.getNumSubscribers() > 0) {
00162 pub.publish(message);
00163 }
00164 }
00165 }
00166 protected:
00167 pluginlib::ClassLoader< PublisherPlugin<M> > loader_;
00168 boost::ptr_vector< PublisherPlugin<M> > publishers_;
00169 };
00170
00171 template <class M>
00172 void PublisherImplGen::publish(const M& message) const
00173 {
00174 (dynamic_cast<const PublisherImpl<M>* const>(this))->publish(message);
00175 }
00176
00177 template <class M>
00178 void PublisherImplGen::publish(const typename M::ConstPtr& message) const
00179 {
00180 (dynamic_cast<const PublisherImpl<M>* const>(this))->publish(message);
00181 }
00182 };
00183 #endif // MESSAGE_TRANSPORT_PUBLISHER_IMPL_H