Goby v2
protobuf_node.h
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 // Community contributors (see AUTHORS file)
5 //
6 //
7 // This file is part of the Goby Underwater Autonomy Project Libraries
8 // ("The Goby Libraries").
9 //
10 // The Goby Libraries are free software: you can redistribute them and/or modify
11 // them under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 2.1 of the License, or
13 // (at your option) any later version.
14 //
15 // The Goby Libraries are distributed in the hope that they will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef PROTOBUFNODE20110418H
24 #define PROTOBUFNODE20110418H
25 
26 #include <boost/bind.hpp>
27 #include <boost/function.hpp>
28 #include <boost/unordered_map.hpp>
29 
30 #include "goby/common/core_helpers.h"
31 #include "goby/common/logger.h"
32 #include "goby/util/dynamic_protobuf_manager.h"
33 
34 #include "goby/common/node_interface.h"
35 #include "subscription.h"
36 
37 namespace goby
38 {
39 namespace pb
40 {
41 class ProtobufNode : public goby::common::NodeInterface<google::protobuf::Message>
42 {
43  protected:
46  {
47  }
48 
49  virtual ~ProtobufNode() {}
50 
51  virtual void protobuf_inbox(const std::string& protobuf_type_name, const std::string& body,
52  int socket_id, const std::string& group) = 0;
53 
54  void send(const google::protobuf::Message& msg, int socket_id, const std::string& group = "");
55  void subscribe(const std::string& identifier, int socket_id);
56  void subscribe(const std::string& protobuf_type_name, int socket_id, const std::string& group);
57 
58  private:
59  void inbox(common::MarshallingScheme marshalling_scheme, const std::string& identifier,
60  const std::string& body, int socket_id);
61 };
62 
64 {
65  public:
67 
68  virtual ~StaticProtobufNode() {}
69 
74  template <typename ProtoBufMessage>
75  void subscribe(int socket_id,
76  boost::function<void(const ProtoBufMessage&)> handler =
77  boost::function<void(const ProtoBufMessage&)>(),
78  const std::string& group = "");
79 
80  template <typename ProtoBufMessage, class C>
81  void subscribe(int socket_id, void (C::*mem_func)(const ProtoBufMessage&), C* obj,
82  const std::string& group = "")
83  {
84  subscribe<ProtoBufMessage>(socket_id, boost::bind(mem_func, obj, _1), group);
85  }
86 
87  template <typename ProtoBufMessage>
88  void on_receipt(int socket_id,
89  boost::function<void(const ProtoBufMessage&)> handler =
90  boost::function<void(const ProtoBufMessage&)>(),
91  const std::string& group = "");
92 
93  template <typename ProtoBufMessage, class C>
94  void on_receipt(int socket_id, void (C::*mem_func)(const ProtoBufMessage&), C* obj,
95  const std::string& group = "")
96  {
97  on_receipt<ProtoBufMessage>(socket_id, boost::bind(mem_func, obj, _1), group);
98  }
99 
100  void send(const google::protobuf::Message& msg, int socket_id, const std::string& group = "")
101  {
102  ProtobufNode::send(msg, socket_id, group);
103  }
104 
106 
107  // template<typename ProtoBufMessage>
111  // const ProtoBufMessage& newest() const;
112 
114 
115  private:
116  void protobuf_inbox(const std::string& protobuf_type_name, const std::string& body,
117  int socket_id, const std::string& group);
118 
119  private:
120  // key = type of var
121  // value = Subscription object for all the subscriptions, handler, newest message, etc.
122  boost::unordered_multimap<std::string, boost::shared_ptr<SubscriptionBase> > subscriptions_;
123 };
124 
126 {
127  protected:
129 
130  virtual ~DynamicProtobufNode() {}
131 
132  void subscribe(int socket_id,
133  boost::function<void(boost::shared_ptr<google::protobuf::Message> msg)> handler,
134  const std::string& group);
135 
136  template <class C>
137  void subscribe(int socket_id,
138  void (C::*mem_func)(boost::shared_ptr<google::protobuf::Message> msg), C* obj,
139  const std::string& group)
140  {
141  subscribe(socket_id, boost::bind(mem_func, obj, _1), group);
142  }
143 
144  void on_receipt(int socket_id,
145  boost::function<void(boost::shared_ptr<google::protobuf::Message> msg)> handler,
146  const std::string& group);
147 
148  template <class C>
149  void on_receipt(int socket_id,
150  void (C::*mem_func)(boost::shared_ptr<google::protobuf::Message> msg), C* obj,
151  const std::string& group)
152  {
153  on_receipt(socket_id, boost::bind(mem_func, obj, _1), group);
154  }
155 
156  // virtual void dynamic_protobuf_inbox(boost::shared_ptr<google::protobuf::Message> msg, int socket_id, const std::string& group) = 0;
157 
158  private:
159  void protobuf_inbox(const std::string& protobuf_type_name, const std::string& body,
160  int socket_id, const std::string& group);
161 
162  private:
163  // key = type of var
164  // value = Subscription object for all the subscriptions, handler, newest message, etc.
165  boost::unordered_multimap<
166  std::string, boost::function<void(boost::shared_ptr<google::protobuf::Message> msg)> >
167  subscriptions_;
168 };
169 
170 } // namespace pb
171 } // namespace goby
172 
173 template <typename ProtoBufMessage>
174 void goby::pb::StaticProtobufNode::on_receipt(
175  int socket_id,
176  boost::function<void(const ProtoBufMessage&)> handler
177  /*= boost::function<void (const ProtoBufMessage&)>()*/,
178  const std::string& group)
179 {
180  using goby::glog;
181 
182  const std::string& protobuf_type_name = ProtoBufMessage::descriptor()->full_name();
183 
184  glog.is(goby::common::logger::DEBUG1) && glog << "registering on_receipt handler for "
185  << protobuf_type_name << std::endl;
186 
187  // machinery so we can call the proper handler upon receipt of this type
188  boost::shared_ptr<SubscriptionBase> subscription(
189  new Subscription<ProtoBufMessage>(handler, protobuf_type_name, group));
190  subscriptions_.insert(std::make_pair(protobuf_type_name, subscription));
191 }
192 
193 template <typename ProtoBufMessage>
195  boost::function<void(const ProtoBufMessage&)> handler
196  /*= boost::function<void (const ProtoBufMessage&)>()*/,
197  const std::string& group)
198 {
199  const std::string& protobuf_type_name = ProtoBufMessage::descriptor()->full_name();
200  on_receipt(socket_id, handler, group);
201 
202  glog.is(goby::common::logger::DEBUG1) && glog << "subscribing for " << protobuf_type_name
203  << std::endl;
204 
205  ProtobufNode::subscribe(protobuf_type_name, socket_id, group);
206 }
207 
209 /* template<typename ProtoBufMessage> */
210 /* const ProtoBufMessage& goby::pb::StaticProtobufNode::newest() const */
211 /* { */
212 /* // RTTI needed so we can store subscriptions with a common (non-template) base but also */
213 /* // return the subclass requested */
214 /* const std::string full_name = ProtoBufMessage::descriptor()->full_name(); */
215 /* typedef boost::unordered_map<std::string, boost::shared_ptr<SubscriptionBase> > */
216 /* Map; */
217 
218 /* for(Map::const_iterator it = subscriptions_.begin(), n = subscriptions_.end(); it != n; ++it) */
219 /* { */
220 /* if(it->second->type_name() == full_name) */
221 /* return dynamic_cast<const ProtoBufMessage&>(it->second->newest()); */
222 /* } */
223 
224 /* // this shouldn't happen if we properly create our Subscriptions */
225 /* throw(std::runtime_error("Invalid message given for call to newest()")); */
226 /* } */
227 
228 #endif
common::FlexOstream glog
Access the Goby logger through this object.
The global namespace for the Goby project.
void subscribe(int socket_id, boost::function< void(const ProtoBufMessage &)> handler=boost::function< void(const ProtoBufMessage &)>(), const std::string &group="")
Subscribe to a message (of any type derived from google::protobuf::Message)