Robot Raconteur Core C++ Library
Loading...
Searching...
No Matches
Generator.h
Go to the documentation of this file.
1
23
24#pragma once
25
30
31namespace RobotRaconteur
32{
66
67template <typename Return, typename Param>
68class 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 }
101 {
102 return false;
103 }
104 }
105
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
163template <typename Return>
164class 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 }
195 {
196 return false;
197 }
198 }
199
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 }
236 {}
237 return ret;
238 }
239 virtual ~Generator() {}
240};
241
248template <typename Param>
249class 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 }
279 {
280 return false;
281 }
282 return true;
283 }
284
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
309class 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
350namespace detail
351{
352template <typename Return>
353static 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
376ROBOTRACONTEUR_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
382template <typename Return, typename Param>
383class 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
425template <typename Return>
426class 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
462template <typename Param>
463class 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
503class ServerEndpoint;
504
505class 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 return;
551 }
552
553 RR_INTRUSIVE_PTR<MessageElement> v3 =
554 CreateMessageElement("", skel1->RRGetNode()->template PackAnyType<typename RRPrimUtil<Return>::BoxedType>(
555 RRPrimUtil<Return>::PrePack(v2)));
556 GeneratorServerBase::EndAsyncCallNext(skel, v3, err, index, m, ep);
557 }
558
559 static void CallNext2(const RR_SHARED_PTR<RobotRaconteurException>& err, int32_t index,
560 const RR_WEAK_PTR<ServiceSkel>& skel, const RR_INTRUSIVE_PTR<MessageEntry>& m,
561 const RR_SHARED_PTR<ServerEndpoint>& ep)
562 {
563 RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
564 RR_SHARED_PTR<RobotRaconteurException> err2 = err;
565 // TODO: Improve null handling
566 if (!skel1 && !err2)
567 {
568 err2 = RR_MAKE_SHARED<InvalidOperationException>("Service skel released");
569 }
570 if (err2)
571 {
572 GeneratorServerBase::EndAsyncCallNext(skel, RR_INTRUSIVE_PTR<MessageElement>(), err2, index, m, ep);
573 return;
574 }
575
576 RR_INTRUSIVE_PTR<MessageElement> v3;
577 GeneratorServerBase::EndAsyncCallNext(skel, v3, err2, index, m, ep);
578 }
579};
580
581template <typename Return, typename Param>
582class GeneratorServer : public GeneratorServerBase
583{
584 protected:
585 RR_SHARED_PTR<Generator<Return, Param> > generator;
586
587 public:
588 GeneratorServer(const RR_SHARED_PTR<Generator<Return, Param> >& generator, boost::string_ref name, int32_t id,
589 const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
590 : GeneratorServerBase(name, id, skel, ep)
591 {
592 if (!generator)
593 throw InvalidOperationException("Generator must not be null");
594 this->generator = generator;
595 }
596
597 RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
598 {
599 ROBOTRACONTEUR_LOG_TRACE_COMPONENT_PATH(node, Service, ep->GetLocalEndpoint(), service_path, name,
600 "Generator CallNext with id " << index);
601 RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
602 if (!skel1)
603 {
604 throw InvalidOperationException("Skel has been released");
605 }
606
607 if (m->Error != MessageErrorType_None)
608 {
609 if (m->Error == MessageErrorType_StopIteration)
610 {
611 generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
612 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
613 }
614 else
615 {
616 generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
617 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
618 }
619 }
620 else
621 {
622 Param v = RRPrimUtil<Param>::PreUnpack(
623 skel1->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Param>::BoxedType>(
624 m->FindElement("parameter")));
625 generator->AsyncNext(v,
626 boost::bind<void>(&GeneratorServerBase::CallNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
627 RR_BOOST_PLACEHOLDERS(_2), index, skel, m, ep));
628 }
629 }
630
631 RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
632};
633
634template <typename Return>
635class GeneratorServer<Return, void> : public GeneratorServerBase
636{
637 protected:
638 RR_SHARED_PTR<Generator<Return, void> > generator;
639
640 public:
641 GeneratorServer(RR_SHARED_PTR<Generator<Return, void> > generator, boost::string_ref name, int32_t id,
642 const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
643 : GeneratorServerBase(name, id, skel, ep)
644 {
645 if (!generator)
646 throw InvalidOperationException("Generator must not be null");
647 this->generator = generator;
648 }
649
650 RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
651 {
652 RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
653 if (!skel1)
654 {
655 throw InvalidOperationException("Skel has been released");
656 }
657
658 if (m->Error != MessageErrorType_None)
659 {
660 if (m->Error == MessageErrorType_StopIteration)
661 {
662 generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
663 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
664 }
665 else
666 {
667 generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
668 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
669 }
670 }
671 else
672 {
673 generator->AsyncNext(boost::bind<void>(&GeneratorServerBase::CallNext1<Return>, RR_BOOST_PLACEHOLDERS(_1),
674 RR_BOOST_PLACEHOLDERS(_2), index, skel, m, ep));
675 }
676 }
677 RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
678};
679
680template <typename Param>
681class GeneratorServer<void, Param> : public GeneratorServerBase
682{
683 protected:
684 RR_SHARED_PTR<Generator<void, Param> > generator;
685
686 public:
687 GeneratorServer(RR_SHARED_PTR<Generator<void, Param> > generator, boost::string_ref name, int32_t id,
688 const RR_SHARED_PTR<ServiceSkel>& skel, const RR_SHARED_PTR<ServerEndpoint>& ep)
689 : GeneratorServerBase(name, id, skel, ep)
690 {
691 if (!generator)
692 throw InvalidOperationException("Generator must not be null");
693 this->generator = generator;
694 }
695
696 RR_OVIRTUAL void CallNext(const RR_INTRUSIVE_PTR<MessageEntry>& m) RR_OVERRIDE
697 {
698 RR_SHARED_PTR<ServiceSkel> skel1 = skel.lock();
699 if (!skel1)
700 {
701 throw InvalidOperationException("Skel has been released");
702 }
703
704 if (m->Error != MessageErrorType_None)
705 {
706 if (m->Error == MessageErrorType_StopIteration)
707 {
708 generator->AsyncClose(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
709 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
710 }
711 else
712 {
713 generator->AsyncAbort(boost::bind<void>(&GeneratorServerBase::CallNext1<int32_t>, 0,
714 RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
715 }
716 }
717 else
718 {
719 Param v = RRPrimUtil<Param>::PreUnpack(
720 skel1->RRGetNode()->template UnpackAnyType<typename RRPrimUtil<Param>::BoxedType>(
721 m->FindElement("parameter")));
722 generator->AsyncNext(
723 v, boost::bind<void>(&GeneratorServerBase::CallNext2, RR_BOOST_PLACEHOLDERS(_1), index, skel, m, ep));
724 }
725 }
726 RR_OVIRTUAL ~GeneratorServer() RR_OVERRIDE {}
727};
728
729// NOLINTBEGIN(cppcoreguidelines-virtual-class-destructor)
730
739template <typename Return, typename Param>
740class SyncGenerator : public Generator<Return, Param>
741{
742 public:
744 RR_OVIRTUAL Return Next(const Param& v) RR_OVERRIDE = 0;
746 RR_OVIRTUAL void AsyncNext(
747 const Param& v, boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
748 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
749 {
750 RR_UNUSED(timeout);
751 Return r;
752 RR_WEAK_PTR<RobotRaconteurNode> node;
753 try
754 {
755 r = Next(v);
756 }
757 catch (std::exception& exp)
758 {
759 detail::InvokeHandlerWithException(node, handler, exp);
760 return;
761 }
762 detail::InvokeHandler(node, handler, r);
763 }
764
765 RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
767 RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
768 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
769 {
770 RR_UNUSED(timeout);
771 RR_WEAK_PTR<RobotRaconteurNode> node;
772 try
773 {
774 Abort();
775 }
776 catch (std::exception& exp)
777 {
778 detail::InvokeHandlerWithException(node, handler, exp);
779 return;
780 }
781 detail::InvokeHandler(node, handler);
782 }
783
784 RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
786 RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
787 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
788 {
789 RR_UNUSED(timeout);
790 RR_WEAK_PTR<RobotRaconteurNode> node;
791 try
792 {
793 Close();
794 }
795 catch (std::exception& exp)
796 {
797 detail::InvokeHandlerWithException(node, handler, exp);
798 return;
799 }
800 detail::InvokeHandler(node, handler);
801 }
802 RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
803};
804
806template <typename Return>
807class SyncGenerator<Return, void> : public Generator<Return, void>
808{
809 public:
811 RR_OVIRTUAL Return Next() RR_OVERRIDE = 0;
813 RR_OVIRTUAL void AsyncNext(
814 boost::function<void(const Return&, const RR_SHARED_PTR<RobotRaconteurException>& err)> handler,
815 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
816 {
817 RR_UNUSED(timeout);
818 Return r;
819 RR_WEAK_PTR<RobotRaconteurNode> node;
820 try
821 {
822 r = Next();
823 }
824 catch (std::exception& exp)
825 {
826 detail::InvokeHandlerWithException(node, handler, exp);
827 return;
828 }
829 detail::InvokeHandler(node, handler, r);
830 }
831
832 RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
834 RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
835 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
836 {
837 RR_UNUSED(timeout);
838 RR_WEAK_PTR<RobotRaconteurNode> node;
839 try
840 {
841 Abort();
842 }
843 catch (std::exception& exp)
844 {
845 detail::InvokeHandlerWithException(node, handler, exp);
846 return;
847 }
848 detail::InvokeHandler(node, handler);
849 }
850
851 RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
853 RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
854 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
855 {
856 RR_UNUSED(timeout);
857 RR_WEAK_PTR<RobotRaconteurNode> node;
858 try
859 {
860 Close();
861 }
862 catch (std::exception& exp)
863 {
864 detail::InvokeHandlerWithException(node, handler, exp);
865 return;
866 }
867 detail::InvokeHandler(node, handler);
868 }
869 RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
870};
871
873template <typename Param>
874class SyncGenerator<void, Param> : public Generator<void, Param>
875{
876 public:
878 RR_OVIRTUAL void Next(const Param& v) RR_OVERRIDE = 0;
880 RR_OVIRTUAL void AsyncNext(const Param& v,
881 boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
882 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
883 {
884 RR_UNUSED(timeout);
885 RR_WEAK_PTR<RobotRaconteurNode> node;
886 try
887 {
888 Next(v);
889 }
890 catch (std::exception& exp)
891 {
892 detail::InvokeHandlerWithException(node, handler, exp);
893 return;
894 }
895 detail::InvokeHandler(node, handler);
896 }
897
898 RR_OVIRTUAL void Abort() RR_OVERRIDE = 0;
900 RR_OVIRTUAL void AsyncAbort(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
901 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
902 {
903 RR_UNUSED(timeout);
904 RR_WEAK_PTR<RobotRaconteurNode> node;
905 try
906 {
907 Abort();
908 }
909 catch (std::exception& exp)
910 {
911 detail::InvokeHandlerWithException(node, handler, exp);
912 return;
913 }
914 detail::InvokeHandler(node, handler);
915 }
916
917 RR_OVIRTUAL void Close() RR_OVERRIDE = 0;
919 RR_OVIRTUAL void AsyncClose(boost::function<void(const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
920 int32_t timeout = RR_TIMEOUT_INFINITE) RR_OVERRIDE
921 {
922 RR_UNUSED(timeout);
923 RR_WEAK_PTR<RobotRaconteurNode> node;
924 try
925 {
926 Close();
927 }
928 catch (std::exception& exp)
929 {
930 detail::InvokeHandlerWithException(node, handler, exp);
931 return;
932 }
933 detail::InvokeHandler(node, handler);
934 }
935 RR_OVIRTUAL ~SyncGenerator() RR_OVERRIDE {}
936};
937
938// NOLINTEND(cppcoreguidelines-virtual-class-destructor)
939
949template <typename T>
950class RangeGenerator : public SyncGenerator<typename T::value_type, void>
951{
952 protected:
953 T range;
954 typename T::iterator iter;
955 boost::mutex range_lock;
956 bool aborted;
957
958 public:
959 RangeGenerator(const T& range)
960 {
961 this->range = range;
962 aborted = false;
963 this->iter = this->range.begin();
964 }
965
967 RR_OVIRTUAL typename T::value_type Next() RR_OVERRIDE
968 {
969 boost::mutex::scoped_lock lock(range_lock);
970
971 if (aborted)
972 {
974 }
975
976 if (iter == range.end())
977 {
978 throw StopIterationException("");
979 }
980
981 return *iter++;
982 }
983
984 RR_OVIRTUAL void Abort() RR_OVERRIDE
985 {
986 boost::mutex::scoped_lock lock(range_lock);
987 iter = range.end();
988 aborted = true;
989 }
990
991 RR_OVIRTUAL void Close() RR_OVERRIDE
992 {
993 boost::mutex::scoped_lock lock(range_lock);
994 iter = range.end();
995 }
996 RR_OVIRTUAL ~RangeGenerator() RR_OVERRIDE {}
997};
998
1006template <typename T>
1007RR_SHARED_PTR<RangeGenerator<T> > CreateRangeGenerator(const T& range)
1008{
1009 return RR_MAKE_SHARED<RangeGenerator<T> >(range);
1010}
1011
1012#ifndef ROBOTRACONTEUR_NO_CXX11_TEMPLATE_ALIASES
1013template <typename Return, typename Param>
1014using GeneratorPtr = RR_SHARED_PTR<Generator<Return, Param> >;
1015template <typename Return, typename Param>
1016using GeneratorConstPtr = RR_SHARED_PTR<const Generator<Return, Param> >;
1017template <typename T>
1018using RangeGeneratorPtr = RR_SHARED_PTR<RangeGenerator<T> >;
1019template <typename T>
1020using RangeGeneratorConstPtr = RR_SHARED_PTR<const RangeGenerator<T> >;
1021#endif
1022
1023} // namespace RobotRaconteur
boost::shared_ptr< RangeGenerator< T > > CreateRangeGenerator(const T &range)
Create a RangeGenerator from a range.
Definition Generator.h:1007
#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 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 std::vector< Return > NextAll()
Automatically call Next() repeatedly and return std::vector of results.
Definition Generator.h:225
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.
InvalidOperationException(const std::string &message, std::string sub_name="", const boost::intrusive_ptr< RRValue > &param_=boost::intrusive_ptr< RRValue >())
Construct an InvalidOperationException.
OperationAbortedException(const std::string &message, std::string sub_name="", const boost::intrusive_ptr< RRValue > &param_=boost::intrusive_ptr< RRValue >())
Construct a OperationAbortedException.
Utility class to use a C++ range with Generator<Return,void>.
Definition Generator.h:951
RR_OVIRTUAL void Close() RR_OVERRIDE
Close the generator.
Definition Generator.h:991
RR_OVIRTUAL T::value_type Next() RR_OVERRIDE
Advance the generator.
Definition Generator.h:967
RR_OVIRTUAL void Abort() RR_OVERRIDE
Abort the generator.
Definition Generator.h:984
Base class for Robot Raconteur exceptions.
Definition Error.h:53
Server endpoint representing a client connection.
Definition Service.h:728
Exception thrown when a generator has finished sending results.
Definition Error.h:1224
StopIterationException(const std::string &message, std::string sub_name="", const boost::intrusive_ptr< RRValue > &param_=boost::intrusive_ptr< RRValue >())
Construct a StopIterationException.
RR_OVIRTUAL void Abort() RR_OVERRIDE=0
Abort the generator.
RR_OVIRTUAL void AsyncNext(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:813
RR_OVIRTUAL void Close() RR_OVERRIDE=0
Close the generator.
RR_OVIRTUAL Return Next() RR_OVERRIDE=0
Advance 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:834
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:853
RR_OVIRTUAL void Close() RR_OVERRIDE=0
Close the generator.
RR_OVIRTUAL void Next(const Param &v) RR_OVERRIDE=0
Advance 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:900
RR_OVIRTUAL void Abort() RR_OVERRIDE=0
Abort the generator.
RR_OVIRTUAL void AsyncNext(const Param &v, boost::function< void(const boost::shared_ptr< RobotRaconteurException > &)> handler, int32_t timeout=RR_TIMEOUT_INFINITE) RR_OVERRIDE
Asynchronously advance the generator.
Definition Generator.h:880
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:919
Helper class for synchronous service generators.
Definition Generator.h:741
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:786
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:746
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:767