All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ReqHandler.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #ifndef IGN_TRANSPORT_REQHANDLER_HH_
19 #define IGN_TRANSPORT_REQHANDLER_HH_
20 
21 #ifdef _MSC_VER
22 #pragma warning(push, 0)
23 #endif
24 #include <google/protobuf/message.h>
25 #ifdef _MSC_VER
26 #pragma warning(pop)
27 #endif
28 
29 #include <condition_variable>
30 #include <functional>
31 #include <memory>
32 #include <string>
33 
37 
38 namespace ignition
39 {
40  namespace transport
41  {
45  {
48  public: explicit IReqHandler(const std::string &_nUuid)
49  : rep(""),
50  result(false),
51  hUuid(Uuid().ToString()),
52  nUuid(_nUuid),
53  requested(false),
54  repAvailable(false)
55  {
56  }
57 
59  public: virtual ~IReqHandler() = default;
60 
67  public: virtual void NotifyResult(const std::string &_rep,
68  const bool _result) = 0;
69 
72  public: std::string NodeUuid() const
73  {
74  return this->nUuid;
75  }
76 
79  public: std::string Response() const
80  {
81  return this->rep;
82  }
83 
86  public: bool Result() const
87  {
88  return this->result;
89  }
90 
93  public: bool Requested() const
94  {
95  return this->requested;
96  }
97 
100  public: void Requested(const bool _value)
101  {
102  this->requested = _value;
103  }
104 
108  public: virtual bool Serialize(std::string &_buffer) const = 0;
109 
112  public: std::string HandlerUuid() const
113  {
114  return this->hUuid;
115  }
116 
124  public: template<typename Lock> bool WaitUntil(Lock &_lock,
125  const unsigned int _timeout)
126  {
127  auto now = std::chrono::system_clock::now();
128  return this->condition.wait_until(_lock,
129  now + std::chrono::milliseconds(_timeout),
130  [this]
131  {
132  return this->repAvailable;
133  });
134  }
135 
138  public: virtual std::string ReqTypeName() const = 0;
139 
142  public: virtual std::string RepTypeName() const = 0;
143 
146  protected: std::condition_variable_any condition;
147 
149  protected: std::string rep;
150 
152  protected: bool result;
153 
155  protected: std::string hUuid;
156 
158  private: std::string nUuid;
159 
162  private: bool requested;
163 
167  public: bool repAvailable;
168  };
169 
175  template <typename Req, typename Rep> class ReqHandler
176  : public IReqHandler
177  {
178  // Documentation inherited.
179  public: explicit ReqHandler(const std::string &_nUuid)
180  : IReqHandler(_nUuid)
181  {
182  }
183 
187  public: std::shared_ptr<Rep> CreateMsg(const std::string &_data) const
188  {
189  // Instantiate a specific protobuf message
190  std::shared_ptr<Rep> msgPtr(new Rep());
191 
192  // Create the message using some serialized data
193  if (!msgPtr->ParseFromString(_data))
194  {
195  std::cerr << "ReqHandler::CreateMsg() error: ParseFromString failed"
196  << std::endl;
197  }
198 
199  return msgPtr;
200  }
201 
207  public: void SetCallback(const std::function <void(
208  const Rep &_rep, const bool _result)> &_cb)
209  {
210  this->cb = _cb;
211  }
212 
216  public: void SetMessage(const Req *_reqMsg)
217  {
218  if (!_reqMsg)
219  {
220  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
221  return;
222  }
223 
224  this->reqMsg.CopyFrom(*_reqMsg);
225  }
226 
232  public: void SetResponse(const Rep * /*_repMsg*/)
233  {
234  }
235 
236  // Documentation inherited
237  public: bool Serialize(std::string &_buffer) const
238  {
239  if (!this->reqMsg.SerializeToString(&_buffer))
240  {
241  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
242  << std::endl;
243  return false;
244  }
245 
246  return true;
247  }
248 
249  // Documentation inherited.
250  public: void NotifyResult(const std::string &_rep, const bool _result)
251  {
252  // Execute the callback (if existing).
253  if (this->cb)
254  {
255  // Instantiate the specific protobuf message associated to this topic.
256  auto msg = this->CreateMsg(_rep);
257 
258  this->cb(*msg, _result);
259  }
260  else
261  {
262  this->rep = _rep;
263  this->result = _result;
264  }
265 
266  this->repAvailable = true;
267  this->condition.notify_one();
268  }
269 
270  // Documentation inherited.
271  public: virtual std::string ReqTypeName() const
272  {
273  return Req().GetTypeName();
274  }
275 
276  // Documentation inherited.
277  public: virtual std::string RepTypeName() const
278  {
279  return Rep().GetTypeName();
280  }
281 
283  private: Req reqMsg;
284 
290  private: std::function<void(const Rep &_rep, const bool _result)> cb;
291  };
292 
296  template <> class ReqHandler<google::protobuf::Message,
297  google::protobuf::Message>
298  : public IReqHandler
299  {
300  // Documentation inherited.
301  public: explicit ReqHandler(const std::string &_nUuid)
302  : IReqHandler(_nUuid)
303  {
304  }
305 
309  public: void SetMessage(const google::protobuf::Message *_reqMsg)
310  {
311  if (!_reqMsg)
312  {
313  std::cerr << "ReqHandler::SetMessage() _reqMsg is null" << std::endl;
314  return;
315  }
316 
317  this->reqMsg = _reqMsg->New();
318  this->reqMsg->CopyFrom(*_reqMsg);
319  }
320 
325  public: void SetResponse(const google::protobuf::Message *_repMsg)
326  {
327  if (!_repMsg)
328  {
329  std::cerr << "ReqHandler::SetResponse() _repMsg is null" << std::endl;
330  return;
331  }
332 
333  this->repMsg = _repMsg->New();
334  this->repMsg->CopyFrom(*_repMsg);
335  }
336 
337  // Documentation inherited
338  public: bool Serialize(std::string &_buffer) const
339  {
340  if (!this->reqMsg)
341  {
342  std::cerr << "ReqHandler::Serialize() reqMsg is null" << std::endl;
343  return false;
344  }
345 
346  if (!this->reqMsg->SerializeToString(&_buffer))
347  {
348  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
349  << std::endl;
350  return false;
351  }
352 
353  return true;
354  }
355 
356  // Documentation inherited.
357  public: void NotifyResult(const std::string &_rep, const bool _result)
358  {
359  this->rep = _rep;
360  this->result = _result;
361 
362  this->repAvailable = true;
363  this->condition.notify_one();
364  }
365 
366  // Documentation inherited.
367  public: virtual std::string ReqTypeName() const
368  {
369  if (this->reqMsg)
370  return this->reqMsg->GetTypeName();
371  else
372  {
373  std::cerr << "ReqHandler::ReqTypeName() Warning: Using ReqTypeName() "
374  << "without type information" << std::endl;
375  return "";
376  }
377  }
378 
380  public: virtual std::string RepTypeName() const
381  {
382  if (this->repMsg)
383  return this->repMsg->GetTypeName();
384  else
385  {
386  std::cerr << "ReqHandler::RepTypeName() Warning: Using RepTypeName() "
387  << "without type information" << std::endl;
388  return "";
389  }
390  }
391 
393  private: google::protobuf::Message *reqMsg = nullptr;
394 
396  private: google::protobuf::Message *repMsg = nullptr;
397  };
398  }
399 }
400 
401 #endif
void SetResponse(const Rep *)
This function is only used for compatibility with SetResponse() when [REP = google::protobuf::Message...
Definition: ReqHandler.hh:232
ReqHandler(const std::string &_nUuid)
Definition: ReqHandler.hh:301
std::string rep
Stores the service response as raw bytes.
Definition: ReqHandler.hh:149
ReqHandler(const std::string &_nUuid)
Definition: ReqHandler.hh:179
void SetMessage(const google::protobuf::Message *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:309
void SetMessage(const Req *_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:216
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: ReqHandler.hh:367
It creates a reply handler for the specific protobuf messages used.
Definition: ReqHandler.hh:175
std::condition_variable_any condition
Condition variable used to wait until a service call REP is available.
Definition: ReqHandler.hh:146
std::string HandlerUuid() const
Returns the unique handler UUID.
Definition: ReqHandler.hh:112
bool repAvailable
When there is a blocking service call request, the call can be unlocked when a service call REP is av...
Definition: ReqHandler.hh:167
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: ReqHandler.hh:237
bool Serialize(std::string &_buffer) const
Serialize the Req protobuf message stored.
Definition: ReqHandler.hh:338
std::shared_ptr< Rep > CreateMsg(const std::string &_data) const
Create a specific protobuf message given its serialized data.
Definition: ReqHandler.hh:187
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:277
void SetCallback(const std::function< void(const Rep &_rep, const bool _result)> &_cb)
Set the callback for this handler.
Definition: ReqHandler.hh:207
std::string hUuid
Unique handler's UUID.
Definition: ReqHandler.hh:155
A portable class for representing a Universally Unique Identifier.
Definition: Uuid.hh:41
Interface class used to manage a request handler.
Definition: ReqHandler.hh:44
void NotifyResult(const std::string &_rep, const bool _result)
Executes the callback registered for this handler and notify a potential requester waiting on a block...
Definition: ReqHandler.hh:250
bool WaitUntil(Lock &_lock, const unsigned int _timeout)
Block the current thread until the response to the service request is available or until the timeout ...
Definition: ReqHandler.hh:124
#define IGNITION_TRANSPORT_VISIBLE
Use to represent "symbol visible" if supported.
Definition: Helpers.hh:57
virtual std::string RepTypeName() const
Get the message type name used in the service response.
Definition: ReqHandler.hh:380
bool Result() const
Get the result of the service response.
Definition: ReqHandler.hh:86
void SetResponse(const google::protobuf::Message *_repMsg)
Set the REP protobuf message for this handler.
Definition: ReqHandler.hh:325
void Requested(const bool _value)
Mark the service call as requested (or not).
Definition: ReqHandler.hh:100
bool Requested() const
Returns if this service call request has already been requested.
Definition: ReqHandler.hh:93
std::string NodeUuid() const
Get the node UUID.
Definition: ReqHandler.hh:72
virtual std::string ReqTypeName() const
Get the message type name used in the service request.
Definition: ReqHandler.hh:271
std::string Response() const
Get the service response as raw bytes.
Definition: ReqHandler.hh:79
IReqHandler(const std::string &_nUuid)
Constructor.
Definition: ReqHandler.hh:48
void NotifyResult(const std::string &_rep, const bool _result)
Executes the callback registered for this handler and notify a potential requester waiting on a block...
Definition: ReqHandler.hh:357
bool result
Stores the result of the service call.
Definition: ReqHandler.hh:152