Robot Raconteur Core C++ Library
Generator.h
Go to the documentation of this file.
1 
24 #pragma once
25 
28 #include "RobotRaconteur/Client.h"
29 #include "RobotRaconteur/Service.h"
30 
31 namespace RobotRaconteur
32 {
67 template <typename Return, typename Param>
68 class Generator : private boost::noncopyable
69 {
70  public:
80  virtual Return Next(const Param& v) = 0;
92  virtual bool TryNext(const Param& v, Return& ret)
93  {
94  // TODO: This is not the most efficient implementation
95  try
96  {
97  ret = Next(v);
98  return true;
99  }
100  catch (StopIterationException&)
101  {
102  return false;
103  }
104  }
114  virtual void AsyncNext(
115  const Param& v, boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
116  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
124  virtual void Abort() = 0;
133  virtual void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
134  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
143  virtual void Close() = 0;
152  virtual void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
153  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
154  virtual ~Generator() {}
155 };
156 
163 template <typename Return>
164 class Generator<Return, void> : private boost::noncopyable
165 {
166  public:
175  virtual Return Next() = 0;
176 
187  virtual bool TryNext(Return& ret)
188  {
189  try
190  {
191  ret = Next();
192  return true;
193  }
194  catch (StopIterationException&)
195  {
196  return false;
197  }
198  }
207  virtual void AsyncNext(
208  boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
209  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
211  virtual void Abort() = 0;
213  virtual void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
214  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
216  virtual void Close() = 0;
218  virtual void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
219  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
225  virtual std::vector<Return> NextAll()
226  {
227  std::vector<Return> ret;
228  try
229  {
230  while (true)
231  {
232  ret.push_back(Next());
233  }
234  }
235  catch (StopIterationException&)
236  {}
237  return ret;
238  }
239  virtual ~Generator() {}
240 };
241 
248 template <typename Param>
249 class Generator<void, Param> : private boost::noncopyable
250 {
251  public:
260  virtual void Next(const Param& v) = 0;
261 
272  virtual bool TryNext(const Param& v)
273  {
274  try
275  {
276  Next(v);
277  }
278  catch (StopIterationException&)
279  {
280  return false;
281  }
282  return true;
283  }
293  virtual void AsyncNext(const Param& v,
294  boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
295  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
297  virtual void Abort() = 0;
299  virtual void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
300  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
302  virtual void Close() = 0;
304  virtual void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
305  int32_t timeout = RR_TIMEOUT_INFINITE) = 0;
306  virtual ~Generator() {}
307 };
308 
309 class ROBOTRACONTEUR_CORE_API GeneratorClientBase
310 {
311  protected:
312  std::string name;
313  int32_t id;
314  RR_WEAK_PTR<ServiceStub> stub;
315  RR_WEAK_PTR<RobotRaconteurNode> node;
316  uint32_t endpoint;
317  std::string service_path;
318 
319  GeneratorClientBase(boost::string_ref name, int32_t id, const RR_SHARED_PTR<ServiceStub>& stub);
320 
321  virtual RR_INTRUSIVE_PTR<MessageElement> NextBase(const RR_INTRUSIVE_PTR<MessageElement>& v);
322  virtual void AsyncNextBase(
323  const RR_INTRUSIVE_PTR<MessageElement>& v,
324  boost::function<void(const RR_INTRUSIVE_PTR<MessageElement>&, const RR_SHARED_PTR<RobotRaconteurException>&,
325  const RR_SHARED_PTR<RobotRaconteurNode>&)>
326  handler,
327  int32_t timeout);
328 
329  static void AsyncNextBase1(
330  const RR_INTRUSIVE_PTR<MessageEntry>& ret, const RR_SHARED_PTR<RobotRaconteurException>& err,
331  boost::function<void(const RR_INTRUSIVE_PTR<MessageElement>&, const RR_SHARED_PTR<RobotRaconteurException>&,
332  const RR_SHARED_PTR<RobotRaconteurNode>&)>
333  handler,
334  const RR_WEAK_PTR<RobotRaconteurNode>& node);
335 
336  public:
337  RR_SHARED_PTR<ServiceStub> GetStub();
338 
339  virtual void Abort();
340  virtual void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
341  int32_t timeout = RR_TIMEOUT_INFINITE);
342  virtual void Close();
343  virtual void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
344  int32_t timeout = RR_TIMEOUT_INFINITE);
345  std::string GetMemberName();
346 
347  virtual ~GeneratorClientBase() {}
348 };
349 
350 namespace detail
351 {
352 template <typename Return>
353 static void GeneratorClient_AsyncNext1(
354  const RR_INTRUSIVE_PTR<MessageElement>& v2, const RR_SHARED_PTR<RobotRaconteurException>& err,
355  const RR_SHARED_PTR<RobotRaconteurNode>& node,
356  boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>&)> handler)
357 {
358  if (err)
359  {
360  detail::InvokeHandlerWithException(node, handler, err);
361  return;
362  }
363  Return ret;
364  try
365  {
366  ret = RRPrimUtil<Return>::PreUnpack(node->UnpackAnyType<typename RRPrimUtil<Return>::BoxedType>(v2));
367  }
368  catch (std::exception& e)
369  {
370  detail::InvokeHandlerWithException(node, handler, e);
371  return;
372  }
373  detail::InvokeHandler<Return>(node, handler, ret);
374 }
375 
376 ROBOTRACONTEUR_CORE_API void GeneratorClient_AsyncNext2(
377  const RR_INTRUSIVE_PTR<MessageElement>& v2, const RR_SHARED_PTR<RobotRaconteurException>& err,
378  const RR_SHARED_PTR<RobotRaconteurNode>& node,
379  boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler);
380 } // namespace detail
381 
382 template <typename Return, typename Param>
383 class GeneratorClient : public Generator<Return, Param>, public GeneratorClientBase
384 {
385  public:
386  GeneratorClient(boost::string_ref name, int32_t id, const RR_SHARED_PTR<ServiceStub>& stub)
387  : GeneratorClientBase(name, id, stub)
388  {}
389 
390  RR_OVIRTUAL Return Next(const Param& v) RR_OVERRIDE
391  {
392  RR_INTRUSIVE_PTR<MessageElement> v1 = CreateMessageElement(
393  "", GetStub()->RRGetNode()->template PackAnyType<typename RRPrimUtil<Param>::BoxedType>(
394  RRPrimUtil<Param>::PrePack(v)));
395  RR_INTRUSIVE_PTR<MessageElement> v2 = NextBase(v1);
396  return RRPrimUtil<Return>::PreUnpack(
397  GetStub()->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Return>::BoxedType>(v2));
398  }
399  RR_OVIRTUAL void AsyncNext(
400  const Param& v, boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
401  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
402  {
403  RR_INTRUSIVE_PTR<MessageElement> v1 = CreateMessageElement(
404  "", GetStub()->RRGetNode()->template PackAnyType<typename RRPrimUtil<Param>::BoxedType>(
405  RRPrimUtil<Param>::PrePack(v)));
406  AsyncNextBase(v1,
407  boost::bind<void>(&detail::GeneratorClient_AsyncNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
408  RR_BOOST_PLACEHOLDERS(_2), RR_BOOST_PLACEHOLDERS(_3), handler),
409  timeout);
410  }
411  RR_OVIRTUAL void Abort() RR_OVERRIDE { GeneratorClientBase::Abort(); }
412  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
413  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
414  {
415  GeneratorClientBase::AsyncAbort(handler, timeout);
416  }
417  RR_OVIRTUAL void Close() RR_OVERRIDE { GeneratorClientBase::Close(); }
418  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
419  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
420  {
421  GeneratorClientBase::AsyncAbort(handler, timeout);
422  }
423 };
424 
425 template <typename Return>
426 class GeneratorClient<Return, void> : public Generator<Return, void>, public GeneratorClientBase
427 {
428  public:
429  GeneratorClient(boost::string_ref name, int32_t id, const RR_SHARED_PTR<ServiceStub>& stub)
430  : GeneratorClientBase(name, id, stub)
431  {}
432 
433  RR_OVIRTUAL Return Next() RR_OVERRIDE
434  {
435  RR_INTRUSIVE_PTR<MessageElement> v2 = NextBase(RR_INTRUSIVE_PTR<MessageElement>());
436  return RRPrimUtil<Return>::PreUnpack(
437  GetStub()->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Return>::BoxedType>(v2));
438  }
439  RR_OVIRTUAL void AsyncNext(
440  boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
441  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
442  {
443  AsyncNextBase(RR_INTRUSIVE_PTR<MessageElement>(),
444  boost::bind<void>(&detail::GeneratorClient_AsyncNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
445  RR_BOOST_PLACEHOLDERS(_2), RR_BOOST_PLACEHOLDERS(_3), handler),
446  timeout);
447  }
448  RR_OVIRTUAL void Abort() RR_OVERRIDE { GeneratorClientBase::Abort(); }
449  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
450  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
451  {
452  GeneratorClientBase::AsyncAbort(handler, timeout);
453  }
454  RR_OVIRTUAL void Close() RR_OVERRIDE { GeneratorClientBase::Close(); }
455  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
456  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
457  {
458  GeneratorClientBase::AsyncAbort(handler, timeout);
459  }
460 };
461 
462 template <typename Param>
463 class GeneratorClient<void, Param> : public Generator<void, Param>, public GeneratorClientBase
464 {
465  public:
466  GeneratorClient(boost::string_ref name, int32_t id, const RR_SHARED_PTR<ServiceStub>& stub)
467  : GeneratorClientBase(name, id, stub)
468  {}
469 
470  RR_OVIRTUAL void Next(const Param& v) RR_OVERRIDE
471  {
472  RR_INTRUSIVE_PTR<MessageElement> v1 = CreateMessageElement(
473  "", GetStub()->RRGetNode()->template PackAnyType<typename RRPrimUtil<Param>::BoxedType>(
474  RRPrimUtil<Param>::PrePack(v)));
475  NextBase(v1);
476  }
477  RR_OVIRTUAL void AsyncNext(const Param& v,
478  boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
479  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
480  {
481  RR_INTRUSIVE_PTR<MessageElement> v1 = CreateMessageElement(
482  "", GetStub()->RRGetNode()->template PackAnyType<typename RRPrimUtil<Param>::BoxedType>(
483  RRPrimUtil<Param>::PrePack(v)));
484  AsyncNextBase(v1,
485  boost::bind<void>(&detail::GeneratorClient_AsyncNext2, RR_BOOST_PLACEHOLDERS(_1),
486  RR_BOOST_PLACEHOLDERS(_2), RR_BOOST_PLACEHOLDERS(_3), RR_MOVE(handler)),
487  timeout);
488  }
489  RR_OVIRTUAL void Abort() RR_OVERRIDE { GeneratorClientBase::Abort(); }
490  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
491  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
492  {
493  GeneratorClientBase::AsyncAbort(handler, timeout);
494  }
495  RR_OVIRTUAL void Close() RR_OVERRIDE { GeneratorClientBase::Close(); }
496  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
497  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
498  {
499  GeneratorClientBase::AsyncAbort(handler, timeout);
500  }
501 };
502 
503 class ServerEndpoint;
504 
505 class ROBOTRACONTEUR_CORE_API GeneratorServerBase : private boost::noncopyable
506 {
507  protected:
508  std::string name;
509  int32_t index;
510  RR_WEAK_PTR<ServiceSkel> skel;
511  RR_INTRUSIVE_PTR<MessageElement> m;
512  RR_SHARED_PTR<ServerEndpoint> ep;
513  RR_WEAK_PTR<RobotRaconteurNode> node;
514  std::string service_path;
515 
516  boost::posix_time::ptime last_access_time;
517 
518  GeneratorServerBase(boost::string_ref name, int32_t index, const RR_SHARED_PTR<ServiceSkel>& skel,
519  const RR_SHARED_PTR<ServerEndpoint>& ep);
520 
521  public:
522  friend class ServiceSkel;
523 
524  virtual void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) = 0;
525 
526  virtual uint32_t GetEndpoint();
527 
528  virtual ~GeneratorServerBase() {}
529 
530  protected:
531  static void EndAsyncCallNext(const RR_WEAK_PTR<ServiceSkel>& skel, const RR_INTRUSIVE_PTR<MessageElement>& ret,
532  const RR_SHARED_PTR<RobotRaconteurException>& err, int32_t index,
533  const RR_INTRUSIVE_PTR<MessageEntry>& m, const RR_SHARED_PTR<ServerEndpoint>& ep);
534 
535  template <typename Return>
536  static void CallNext1(Return v2, const RR_SHARED_PTR<RobotRaconteurException>& err, int32_t index,
537  const RR_WEAK_PTR<ServiceSkel>& skel, const RR_INTRUSIVE_PTR<MessageEntry>& m,
538  const RR_SHARED_PTR<ServerEndpoint>& ep)
539  {
540  RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
541  RR_SHARED_PTR<RobotRaconteurException> err2 = err;
542  // TODO: Improve null handling
543  if (!skel1 && !err2)
544  {
545  err2 = RR_MAKE_SHARED<InvalidOperationException>("Service skel released");
546  }
547  if (err2)
548  {
549  GeneratorServerBase::EndAsyncCallNext(skel, RR_INTRUSIVE_PTR<MessageElement>(), err2, index, m, ep);
550  }
551 
552  RR_INTRUSIVE_PTR<MessageElement> v3 =
553  CreateMessageElement("", skel1->RRGetNode()->template PackAnyType<typename RRPrimUtil<Return>::BoxedType>(
554  RRPrimUtil<Return>::PrePack(v2)));
555  GeneratorServerBase::EndAsyncCallNext(skel, v3, err, index, m, ep);
556  }
557 
558  static void CallNext2(const RR_SHARED_PTR<RobotRaconteurException>& err, int32_t index,
559  const RR_WEAK_PTR<ServiceSkel>& skel, const RR_INTRUSIVE_PTR<MessageEntry>& m,
560  const RR_SHARED_PTR<ServerEndpoint>& ep)
561  {
562  RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
563  RR_SHARED_PTR<RobotRaconteurException> err2 = err;
564  // TODO: Improve null handling
565  if (!skel1 && !err2)
566  {
567  err2 = RR_MAKE_SHARED<InvalidOperationException>("Service skel released");
568  }
569  if (err2)
570  {
571  GeneratorServerBase::EndAsyncCallNext(skel, RR_INTRUSIVE_PTR<MessageElement>(), err2, index, m, ep);
572  }
573 
574  RR_INTRUSIVE_PTR<MessageElement> v3;
575  GeneratorServerBase::EndAsyncCallNext(skel, v3, err2, index, m, ep);
576  }
577 };
578 
579 template <typename Return, typename Param>
580 class GeneratorServer : public GeneratorServerBase
581 {
582  protected:
583  RR_SHARED_PTR<Generator<Return, Param> > generator;
584 
585  public:
586  GeneratorServer(const RR_SHARED_PTR<Generator<Return, Param> >& generator, boost::string_ref name, int32_t id,
587  const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
588  : GeneratorServerBase(name, id, skel, ep)
589  {
590  if (!generator)
591  throw InvalidOperationException("Generator must not be null");
592  this->generator = generator;
593  }
594 
595  RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
596  {
597  ROBOTRACONTEUR_LOG_TRACE_COMPONENT_PATH(node, Service, ep->GetLocalEndpoint(), service_path, name,
598  "Generator CallNext with id " << index);
599  RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
600  if (!skel1)
601  {
602  throw InvalidOperationException("Skel has been released");
603  }
604 
605  if (m->Error != MessageErrorType_None)
606  {
607  if (m->Error == MessageErrorType_StopIteration)
608  {
609  generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
610  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
611  }
612  else
613  {
614  generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
615  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
616  }
617  }
618  else
619  {
620  Param v = RRPrimUtil<Param>::PreUnpack(
621  skel1->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Param>::BoxedType>(
622  m->FindElement("parameter")));
623  generator->AsyncNext(v,
624  boost::bind<void>(&GeneratorServerBase::CallNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
625  RR_BOOST_PLACEHOLDERS(_2), index, skel, m, ep));
626  }
627  }
628 
629  RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
630 };
631 
632 template <typename Return>
633 class GeneratorServer<Return, void> : public GeneratorServerBase
634 {
635  protected:
636  RR_SHARED_PTR<Generator<Return, void> > generator;
637 
638  public:
639  GeneratorServer(RR_SHARED_PTR<Generator<Return, void> > generator, boost::string_ref name, int32_t id,
640  const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
641  : GeneratorServerBase(name, id, skel, ep)
642  {
643  if (!generator)
644  throw InvalidOperationException("Generator must not be null");
645  this->generator = generator;
646  }
647 
648  RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
649  {
650  RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
651  if (!skel1)
652  {
653  throw InvalidOperationException("Skel has been released");
654  }
655 
656  if (m->Error != MessageErrorType_None)
657  {
658  if (m->Error == MessageErrorType_StopIteration)
659  {
660  generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
661  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
662  }
663  else
664  {
665  generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
666  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
667  }
668  }
669  else
670  {
671  generator->AsyncNext(boost::bind<void>(&GeneratorServerBase::CallNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
672  RR_BOOST_PLACEHOLDERS(_2), index, skel, m, ep));
673  }
674  }
675  RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
676 };
677 
678 template <typename Param>
679 class GeneratorServer<void, Param> : public GeneratorServerBase
680 {
681  protected:
682  RR_SHARED_PTR<Generator<void, Param> > generator;
683 
684  public:
685  GeneratorServer(RR_SHARED_PTR<Generator<void, Param> > generator, boost::string_ref name, int32_t id,
686  const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
687  : GeneratorServerBase(name, id, skel, ep)
688  {
689  if (!generator)
690  throw InvalidOperationException("Generator must not be null");
691  this->generator = generator;
692  }
693 
694  RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
695  {
696  RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
697  if (!skel1)
698  {
699  throw InvalidOperationException("Skel has been released");
700  }
701 
702  if (m->Error != MessageErrorType_None)
703  {
704  if (m->Error == MessageErrorType_StopIteration)
705  {
706  generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
707  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
708  }
709  else
710  {
711  generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
712  RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
713  }
714  }
715  else
716  {
717  Param v = RRPrimUtil<Param>::PreUnpack(
718  skel1->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Param>::BoxedType>(
719  m->FindElement("parameter")));
720  generator->AsyncNext(
721  v, boost::bind<void>(&GeneratorServerBase::CallNext2, RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
722  }
723  }
724  RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
725 };
726 
727 // NOLINTBEGIN(cppcoreguidelines-virtual-class-destructor)
728 
737 template <typename Return, typename Param>
738 class SyncGenerator : public Generator<Return, Param>
739 {
740  public:
742  RR_OVIRTUAL Return Next(const Param& v) RR_OVERRIDE = 0;
744  RR_OVIRTUAL void AsyncNext(
745  const Param& v, boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
746  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
747  {
748  RR_UNUSED(timeout);
749  Return r;
750  RR_WEAK_PTR<RobotRaconteurNode> node;
751  try
752  {
753  r = Next(v);
754  }
755  catch (std::exception& exp)
756  {
757  detail::InvokeHandlerWithException(node, handler, exp);
758  return;
759  }
760  detail::InvokeHandler(node, handler, r);
761  }
763  RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
765  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
766  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
767  {
768  RR_UNUSED(timeout);
769  RR_WEAK_PTR<RobotRaconteurNode> node;
770  try
771  {
772  Abort();
773  }
774  catch (std::exception& exp)
775  {
776  detail::InvokeHandlerWithException(node, handler, exp);
777  return;
778  }
779  detail::InvokeHandler(node, handler);
780  }
782  RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
784  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
785  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
786  {
787  RR_UNUSED(timeout);
788  RR_WEAK_PTR<RobotRaconteurNode> node;
789  try
790  {
791  Close();
792  }
793  catch (std::exception& exp)
794  {
795  detail::InvokeHandlerWithException(node, handler, exp);
796  return;
797  }
798  detail::InvokeHandler(node, handler);
799  }
800  RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
801 };
802 
804 template <typename Return>
805 class SyncGenerator<Return, void> : public Generator<Return, void>
806 {
807  public:
809  RR_OVIRTUAL Return Next() RR_OVERRIDE = 0;
811  RR_OVIRTUAL void AsyncNext(
812  boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
813  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
814  {
815  RR_UNUSED(timeout);
816  Return r;
817  RR_WEAK_PTR<RobotRaconteurNode> node;
818  try
819  {
820  r = Next();
821  }
822  catch (std::exception& exp)
823  {
824  detail::InvokeHandlerWithException(node, handler, exp);
825  return;
826  }
827  detail::InvokeHandler(node, handler, r);
828  }
830  RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
832  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
833  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
834  {
835  RR_UNUSED(timeout);
836  RR_WEAK_PTR<RobotRaconteurNode> node;
837  try
838  {
839  Abort();
840  }
841  catch (std::exception& exp)
842  {
843  detail::InvokeHandlerWithException(node, handler, exp);
844  return;
845  }
846  detail::InvokeHandler(node, handler);
847  }
849  RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
851  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
852  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
853  {
854  RR_UNUSED(timeout);
855  RR_WEAK_PTR<RobotRaconteurNode> node;
856  try
857  {
858  Close();
859  }
860  catch (std::exception& exp)
861  {
862  detail::InvokeHandlerWithException(node, handler, exp);
863  return;
864  }
865  detail::InvokeHandler(node, handler);
866  }
867  RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
868 };
869 
871 template <typename Param>
872 class SyncGenerator<void, Param> : public Generator<void, Param>
873 {
874  public:
876  RR_OVIRTUAL void Next(const Param& v) RR_OVERRIDE = 0;
878  RR_OVIRTUAL void AsyncNext(const Param& v,
879  boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
880  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
881  {
882  RR_UNUSED(timeout);
883  RR_WEAK_PTR<RobotRaconteurNode> node;
884  try
885  {
886  Next(v);
887  }
888  catch (std::exception& exp)
889  {
890  detail::InvokeHandlerWithException(node, handler, exp);
891  return;
892  }
893  detail::InvokeHandler(node, handler);
894  }
896  RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
898  RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
899  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
900  {
901  RR_UNUSED(timeout);
902  RR_WEAK_PTR<RobotRaconteurNode> node;
903  try
904  {
905  Abort();
906  }
907  catch (std::exception& exp)
908  {
909  detail::InvokeHandlerWithException(node, handler, exp);
910  return;
911  }
912  detail::InvokeHandler(node, handler);
913  }
915  RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
917  RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
918  int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
919  {
920  RR_UNUSED(timeout);
921  RR_WEAK_PTR<RobotRaconteurNode> node;
922  try
923  {
924  Close();
925  }
926  catch (std::exception& exp)
927  {
928  detail::InvokeHandlerWithException(node, handler, exp);
929  return;
930  }
931  detail::InvokeHandler(node, handler);
932  }
933  RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
934 };
935 
936 // NOLINTEND(cppcoreguidelines-virtual-class-destructor)
937 
947 template <typename T>
948 class RangeGenerator : public SyncGenerator<typename T::value_type, void>
949 {
950  protected:
951  T range;
952  typename T::iterator iter;
953  boost::mutex range_lock;
954  bool aborted;
955 
956  public:
957  RangeGenerator(const T& range)
958  {
959  this->range = range;
960  aborted = false;
961  this->iter = this->range.begin();
962  }
963 
965  RR_OVIRTUAL typename T::value_type Next() RR_OVERRIDE
966  {
967  boost::mutex::scoped_lock lock(range_lock);
968 
969  if (aborted)
970  {
971  throw OperationAbortedException("");
972  }
973 
974  if (iter == range.end())
975  {
976  throw StopIterationException("");
977  }
978 
979  return *iter++;
980  }
982  RR_OVIRTUAL void Abort() RR_OVERRIDE
983  {
984  boost::mutex::scoped_lock lock(range_lock);
985  iter = range.end();
986  aborted = true;
987  }
989  RR_OVIRTUAL void Close() RR_OVERRIDE
990  {
991  boost::mutex::scoped_lock lock(range_lock);
992  iter = range.end();
993  }
994  RR_OVIRTUAL ~RangeGenerator() RR_OVERRIDE {}
995 };
996 
1004 template <typename T>
1005 RR_SHARED_PTR<RangeGenerator<T> > CreateRangeGenerator(const T& range)
1006 {
1007  return RR_MAKE_SHARED<RangeGenerator<T> >(range);
1008 }
1009 
1010 #ifndef ROBOTRACONTEUR_NO_CXX11_TEMPLATE_ALIASES
1011 template <typename Return, typename Param>
1012 using GeneratorPtr = RR_SHARED_PTR<Generator<Return, Param> >;
1013 template <typename Return, typename Param>
1014 using GeneratorConstPtr = RR_SHARED_PTR<const Generator<Return, Param> >;
1015 template <typename T>
1016 using RangeGeneratorPtr = RR_SHARED_PTR<RangeGenerator<T> >;
1017 template <typename T>
1018 using RangeGeneratorConstPtr = RR_SHARED_PTR<const RangeGenerator<T> >;
1019 #endif
1020 
1021 } // namespace RobotRaconteur
boost::shared_ptr< RangeGenerator< T > > CreateRangeGenerator(const T &range)
Create a RangeGenerator from a range.
Definition: Generator.h:1005
#define RR_TIMEOUT_INFINITE
Disable timeout for asynchronous operations.
Definition: RobotRaconteurConstants.h:566
virtual bool TryNext(Return &ret)
Try to advance the generator. Return false if no more values are available.
Definition: Generator.h:187
virtual void AsyncClose(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously closes the generator.
virtual std::vector< Return > NextAll()
Automatically call Next() repeatedly and return std::vector of results.
Definition: Generator.h:225
virtual void Close()=0
Close the generator.
virtual void AsyncNext(boost::function< void(const Return &, const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously advance the generator.
virtual void AsyncAbort(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously abort the generator.
virtual Return Next()=0
Advance the generator.
virtual void Abort()=0
Abort the generator.
virtual void AsyncClose(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously closes the generator.
virtual void AsyncNext(const Param &v, boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously advance the generator.
virtual void Close()=0
Close the generator.
virtual void AsyncAbort(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously abort the generator.
virtual void Next(const Param &v)=0
Advance the generator.
virtual void Abort()=0
Abort the generator.
virtual bool TryNext(const Param &v)
Try to advance the generator. Return false if no more values are available.
Definition: Generator.h:272
Generator type for use with generator functions, with parameter and return.
Definition: Generator.h:69
virtual void Abort()=0
Abort the generator.
virtual void Close()=0
Close the generator.
virtual bool TryNext(const Param &v, Return &ret)
Try to advance the generator. Return false if no more values are available.
Definition: Generator.h:92
virtual void AsyncAbort(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously abort the generator.
virtual void AsyncNext(const Param &v, boost::function< void(const Return &, const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously advance the generator.
virtual void AsyncClose(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE)=0
Asynchronously closes the generator.
virtual Return Next(const Param &v)=0
Advance the generator.
Exception thrown when an operation is aborted.
Definition: Error.h:1194
Utility class to use a C++ range with Generator<Return,void>.
Definition: Generator.h:949
RR_OVIRTUAL void Close() RR_OVERRIDE
Close the generator.
Definition: Generator.h:989
RR_OVIRTUAL T::value_type Next() RR_OVERRIDE
Advance the generator.
Definition: Generator.h:965
RR_OVIRTUAL void Abort() RR_OVERRIDE
Abort the generator.
Definition: Generator.h:982
Base class for Robot Raconteur exceptions.
Definition: Error.h:50
Exception thrown when a generator has finished sending results.
Definition: Error.h:1219
Helper class for synchronous service generators.
Definition: Generator.h:739
RR_OVIRTUAL void AsyncClose(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &)> handler, int32_t timeout=RR_TIMEOUT_INFINITE) RR_OVERRIDE
Asynchronously closes the generator.
Definition: Generator.h:784
RR_OVIRTUAL void Close() RR_OVERRIDE=0
Close the generator.
RR_OVIRTUAL void AsyncNext(const Param &v, boost::function< void(const Return &, const boost::shared_ptr< RobotRaconteurException > &err)> handler, int32_t timeout=RR_TIMEOUT_INFINITE) RR_OVERRIDE
Asynchronously advance the generator.
Definition: Generator.h:744
RR_OVIRTUAL Return Next(const Param &v) RR_OVERRIDE=0
Advance the generator.
RR_OVIRTUAL void Abort() RR_OVERRIDE=0
Abort the generator.
RR_OVIRTUAL void AsyncAbort(boost::function< void(const boost::shared_ptr< RobotRaconteurException > &)> handler, int32_t timeout=RR_TIMEOUT_INFINITE) RR_OVERRIDE
Asynchronously abort the generator.
Definition: Generator.h:765