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 }
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
579template <typename Return, typename Param>
580class 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
632template <typename Return>
633class 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
678template <typename Param>
679class 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
737template <typename Return, typename Param>
738class 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 }
762
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 }
781
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
804template <typename Return>
805class 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 }
829
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 }
848
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
871template <typename Param>
872class 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 }
895
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 }
914
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
947template <typename T>
948class 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 {
972 }
973
974 if (iter == range.end())
975 {
976 throw StopIterationException("");
977 }
978
979 return *iter++;
980 }
981
982 RR_OVIRTUAL void Abort() RR_OVERRIDE
983 {
984 boost::mutex::scoped_lock lock(range_lock);
985 iter = range.end();
986 aborted = true;
987 }
988
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
1004template <typename T>
1005RR_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
1011template <typename Return, typename Param>
1012using GeneratorPtr = RR_SHARED_PTR<Generator<Return, Param> >;
1013template <typename Return, typename Param>
1014using GeneratorConstPtr = RR_SHARED_PTR<const Generator<Return, Param> >;
1015template <typename T>
1016using RangeGeneratorPtr = RR_SHARED_PTR<RangeGenerator<T> >;
1017template <typename T>
1018using 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 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.
Exception thrown when an operation is aborted.
Definition Error.h:1199
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:53
Server endpoint representing a client connection.
Definition Service.h:728
Exception thrown when a generator has finished sending results.
Definition Error.h:1224
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:811
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:832
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:851
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:898
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:878
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:917
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