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_INCLUDED__
19 #define __IGN_TRANSPORT_REQHANDLER_HH_INCLUDED__
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: 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: 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  this->reqMsg = _reqMsg;
219  }
220 
221  // Documentation inherited
222  public: bool Serialize(std::string &_buffer) const
223  {
224  if (!this->reqMsg.SerializeToString(&_buffer))
225  {
226  std::cerr << "ReqHandler::Serialize(): Error serializing the request"
227  << std::endl;
228  return false;
229  }
230 
231  return true;
232  }
233 
234  // Documentation inherited.
235  public: void NotifyResult(const std::string &_rep, const bool _result)
236  {
237  // Execute the callback (if existing).
238  if (this->cb)
239  {
240  // Instantiate the specific protobuf message associated to this topic.
241  auto msg = this->CreateMsg(_rep);
242 
243  this->cb(*msg, _result);
244  }
245  else
246  {
247  this->rep = _rep;
248  this->result = _result;
249  }
250 
251  this->repAvailable = true;
252  this->condition.notify_one();
253  }
254 
255  // Documentation inherited.
256  public: virtual std::string ReqTypeName() const
257  {
258  return Req().GetTypeName();
259  }
260 
261  // Documentation inherited.
262  public: virtual std::string RepTypeName() const
263  {
264  return Rep().GetTypeName();
265  }
266 
268  private: Req reqMsg;
269 
275  private: std::function<void(const Rep &_rep, const bool _result)> cb;
276  };
277  }
278 }
279 
280 #endif
#define IGNITION_VISIBLE
Use to represent "symbol visible" if supported.
Definition: Helpers.hh:56
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 Req &_reqMsg)
Set the REQ protobuf message for this handler.
Definition: ReqHandler.hh:216
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:222
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:262
std::string hUuid
Unique handler&#39;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:235
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
bool Result() const
Get the result of the service response.
Definition: ReqHandler.hh:86
void SetCallback(const std::function< void( const Rep &_rep, const bool _result)> &_cb)
Set the callback for this handler.
Definition: ReqHandler.hh:207
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:256
std::string Response() const
Get the service response as raw bytes.
Definition: ReqHandler.hh:79
Definition: AdvertiseOptions.hh:25
IReqHandler(const std::string &_nUuid)
Constructor.
Definition: ReqHandler.hh:48
bool result
Stores the result of the service call.
Definition: ReqHandler.hh:152