24 #include <boost/bind/placeholders.hpp>
25 #include <boost/scope_exit.hpp>
26 #include <boost/system/error_code.hpp>
36 namespace RobotRaconteur
38 class ROBOTRACONTEUR_CORE_API RobotRaconteurNode;
43 class sync_async_handler :
private boost::noncopyable
46 RR_SHARED_PTR<AutoResetEvent> ev;
47 RR_SHARED_PTR<RobotRaconteurException> err;
48 RR_SHARED_PTR<T> data;
49 boost::mutex data_lock;
51 sync_async_handler() { ev = RR_MAKE_SHARED<AutoResetEvent>(); }
53 sync_async_handler(
const RR_SHARED_PTR<RobotRaconteurException>& err)
55 ev = RR_MAKE_SHARED<AutoResetEvent>();
59 void operator()() { ev->Set(); }
61 void operator()(
const RR_SHARED_PTR<RobotRaconteurException>& err)
63 boost::mutex::scoped_lock lock(data_lock);
68 void operator()(
const RR_SHARED_PTR<T>& data,
const RR_SHARED_PTR<RobotRaconteurException>& err)
70 boost::mutex::scoped_lock lock(data_lock);
76 RR_SHARED_PTR<T> end()
80 boost::mutex::scoped_lock lock(data_lock);
83 RobotRaconteurExceptionUtil::DownCastAndThrowException(err);
87 throw InternalErrorException(
"Internal async error");
96 boost::mutex::scoped_lock lock(data_lock);
99 RobotRaconteurExceptionUtil::DownCastAndThrowException(err);
103 bool try_end(RR_SHARED_PTR<T>& res, RR_SHARED_PTR<RobotRaconteurException>& err_out)
107 boost::mutex::scoped_lock lock(data_lock);
116 err_out = RR_MAKE_SHARED<InternalErrorException>(
"Internal async error");
124 bool try_end_void(RR_SHARED_PTR<RobotRaconteurException>& err_out)
128 boost::mutex::scoped_lock lock(data_lock);
139 RR_SHARED_PTR<Timer> async_timeout_wrapper_CreateTimer(
const RR_SHARED_PTR<RobotRaconteurNode>& node,
140 const boost::posix_time::time_duration& period,
141 RR_MOVE_ARG(boost::function<
void(
const TimerEvent&)>) handler,
144 template <
typename T>
145 void async_timeout_wrapper_closer(
const RR_SHARED_PTR<T>& d)
151 catch (std::exception&)
155 template <
typename T,
typename T2>
156 void async_timeout_wrapper_closer(
const RR_SHARED_PTR<T>& d)
160 RR_SHARED_PTR<T2> t2 = RR_DYNAMIC_POINTER_CAST<T2>(d);
165 catch (std::exception&)
169 template <
typename T>
170 class async_timeout_wrapper :
public RR_ENABLE_SHARED_FROM_THIS<async_timeout_wrapper<T> >,
private boost::noncopyable
173 boost::function<void(
const RR_SHARED_PTR<T>&,
const RR_SHARED_PTR<RobotRaconteurException>&)> handler_;
174 RR_SHARED_PTR<Timer> timeout_timer_;
175 boost::mutex handled_lock;
177 RR_SHARED_PTR<RobotRaconteurException> timeout_exception_;
178 boost::function<void(
const RR_SHARED_PTR<T>&)> deleter_;
179 RR_WEAK_PTR<RobotRaconteurNode> node;
182 async_timeout_wrapper(
183 const RR_SHARED_PTR<RobotRaconteurNode>& node,
184 boost::function<
void(
const RR_SHARED_PTR<T>&,
const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
185 RR_MOVE_ARG(boost::function<
void(
const RR_SHARED_PTR<T>&)>) deleter = 0)
186 : handler_(handler), handled(false), node(node)
188 deleter_.swap(deleter);
191 void start_timer(int32_t timeout,
const RR_SHARED_PTR<RobotRaconteurException>& timeout_exception =
192 RR_MAKE_SHARED<ConnectionException>(
"Timeout during operation"));
194 void operator()(
const RR_SHARED_PTR<T>& data,
const RR_SHARED_PTR<RobotRaconteurException>& err)
197 boost::mutex::scoped_lock lock(handled_lock);
200 if (data && deleter_)
207 timeout_timer_->TryStop();
209 timeout_timer_.reset();
215 void handle_error(
const RR_SHARED_PTR<RobotRaconteurException>& err)
218 boost::mutex::scoped_lock lock(handled_lock);
226 timeout_timer_->TryStop();
228 timeout_timer_.reset();
232 handler_(RR_SHARED_PTR<T>(), err);
235 void handle_error(
const boost::system::error_code& err)
237 if (err.value() == boost::system::errc::timed_out)
238 handle_error(timeout_exception_);
239 handle_error(RR_MAKE_SHARED<ConnectionException>(err.message()));
243 void timeout_handler(
const TimerEvent& )
246 boost::mutex::scoped_lock lock(handled_lock);
252 timeout_timer_.reset();
255 handler_(RR_SHARED_PTR<T>(), timeout_exception_);
259 template <
typename T>
260 void async_timeout_wrapper<T>::start_timer(int32_t timeout,
261 const RR_SHARED_PTR<RobotRaconteurException>& timeout_exception)
263 RR_SHARED_PTR<RobotRaconteurNode> n = node.lock();
265 throw InvalidOperationException(
"Node has been released");
267 boost::mutex::scoped_lock lock(handled_lock);
275 async_timeout_wrapper_CreateTimer(n, boost::posix_time::milliseconds(timeout),
276 boost::bind(&async_timeout_wrapper<T>::timeout_handler,
277 this->shared_from_this(), RR_BOOST_PLACEHOLDERS(_1)),
279 timeout_timer_->Start();
280 timeout_exception_ = RR_MOVE(timeout_exception);
308 class ROBOTRACONTEUR_CORE_API async_signal_semaphore :
private boost::noncopyable
311 boost::mutex this_lock;
312 boost::condition_variable next_wait;
313 boost::initialized<bool> running;
314 boost::initialized<bool> next;
315 boost::initialized<uint64_t> next_id;
318 template <
typename F>
319 bool try_fire_next(BOOST_ASIO_MOVE_ARG(F) h)
321 boost::mutex::scoped_lock lock(this_lock);
325 uint64_t my_id = ++next_id.data();
329 next_wait.notify_all();
338 next_wait.wait(lock);
339 if (my_id != next_id)
346 running.data() =
true;
348 BOOST_SCOPE_EXIT_TPL(this_)
350 boost::mutex::scoped_lock lock2(this_->this_lock);
351 this_->running.data() =
false;
352 this_->next_wait.notify_all();
354 BOOST_SCOPE_EXIT_END;
364 class ROBOTRACONTEUR_CORE_API async_signal_pool_semaphore
365 :
public RR_ENABLE_SHARED_FROM_THIS<async_signal_pool_semaphore>,
366 private boost::noncopyable
369 boost::mutex this_lock;
370 boost::initialized<bool> running;
371 boost::function<void()> next;
372 RR_WEAK_PTR<RobotRaconteurNode> node;
375 async_signal_pool_semaphore(
const RR_SHARED_PTR<RobotRaconteurNode>& node) : node(node) {}
377 template <
typename F>
378 void try_fire_next(BOOST_ASIO_MOVE_ARG(F) h)
380 boost::mutex::scoped_lock lock(this_lock);
384 RR_SHARED_PTR<RobotRaconteurNode> node1 = this->node.lock();
396 void do_fire_next(
const boost::function<
void()>& h)
402 catch (std::exception& exp)
404 handle_exception(&exp);
407 BOOST_SCOPE_EXIT(this_)
409 boost::mutex::scoped_lock lock2(this_->this_lock);
411 boost::function<void()> h2;
412 h2.swap(this_->next);
414 this_->running.data() =
false;
417 RR_SHARED_PTR<RobotRaconteurNode> node = this_->node.lock();
423 boost::bind(&async_signal_pool_semaphore::do_fire_next, this_->shared_from_this(), h2));
425 catch (std::exception&)
427 this_->running.data() =
true;
429 BOOST_SCOPE_EXIT_END;
432 void do_post(
const RR_SHARED_PTR<RobotRaconteurNode>& node1, RR_MOVE_ARG(boost::function<
void()>) h);
434 void handle_exception(std::exception* exp);
437 ROBOTRACONTEUR_CORE_API
void InvokeHandler_HandleException(RR_WEAK_PTR<RobotRaconteurNode> node, std::exception& exp);
439 ROBOTRACONTEUR_CORE_API
void InvokeHandler_DoPost(RR_WEAK_PTR<RobotRaconteurNode> node,
440 const boost::function<
void()>& h,
bool shutdown_op =
false,
441 bool throw_on_released =
true);
443 ROBOTRACONTEUR_CORE_API
void InvokeHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
444 const boost::function<
void()>& handler);
446 template <
typename T>
447 void InvokeHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const typename boost::function<
void(
const T&)>& handler,
454 catch (std::exception& exp)
456 InvokeHandler_HandleException(RR_MOVE(node), exp);
460 ROBOTRACONTEUR_CORE_API
void InvokeHandler(
461 RR_WEAK_PTR<RobotRaconteurNode> node,
462 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler);
464 ROBOTRACONTEUR_CORE_API
void InvokeHandlerWithException(
465 RR_WEAK_PTR<RobotRaconteurNode> node,
466 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
467 const RR_SHARED_PTR<RobotRaconteurException>& exp);
469 ROBOTRACONTEUR_CORE_API
void InvokeHandlerWithException(
470 RR_WEAK_PTR<RobotRaconteurNode> node,
471 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler, std::exception& exp,
472 MessageErrorType default_err = MessageErrorType_UnknownError);
474 template <
typename T>
476 RR_WEAK_PTR<RobotRaconteurNode> node,
477 const typename boost::function<
void(
const T&,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
482 handler(value, RR_SHARED_PTR<RobotRaconteurException>());
484 catch (std::exception& exp)
486 InvokeHandler_HandleException(RR_MOVE(node), exp);
490 template <
typename T>
491 void InvokeHandlerWithException(
492 RR_WEAK_PTR<RobotRaconteurNode> node,
493 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
494 const RR_SHARED_PTR<RobotRaconteurException>& exp)
496 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
499 handler(default_value, exp);
501 catch (std::exception& exp)
503 InvokeHandler_HandleException(RR_MOVE(node), exp);
507 template <
typename T>
508 void InvokeHandlerWithException(
509 RR_WEAK_PTR<RobotRaconteurNode> node,
510 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
511 std::exception& exp, MessageErrorType default_err = MessageErrorType_UnknownError)
513 typename boost::initialized<typename boost::remove_const<typename boost::remove_reference<T>::type>::type>
517 RR_SHARED_PTR<RobotRaconteurException> err =
518 RobotRaconteurExceptionUtil::ExceptionToSharedPtr(exp, default_err);
519 handler(default_value, err);
521 catch (std::exception& exp)
523 InvokeHandler_HandleException(RR_MOVE(node), exp);
527 ROBOTRACONTEUR_CORE_API
void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const boost::function<
void()>& handler,
528 bool shutdown_op =
false,
bool throw_on_released =
true);
530 template <
typename T>
531 void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const typename boost::function<
void(
const T&)>& handler,
532 const T& value,
bool shutdown_op =
false,
bool throw_on_released =
true)
534 boost::function<void()> h = boost::bind(handler, value);
535 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
538 ROBOTRACONTEUR_CORE_API
void PostHandler(
539 RR_WEAK_PTR<RobotRaconteurNode> node,
540 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
bool shutdown_op =
false,
541 bool throw_on_released =
true);
543 ROBOTRACONTEUR_CORE_API
void PostHandlerWithException(
544 RR_WEAK_PTR<RobotRaconteurNode> node,
545 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
546 const RR_SHARED_PTR<RobotRaconteurException>& exp,
bool shutdown_op =
false,
bool throw_on_released =
true);
548 ROBOTRACONTEUR_CORE_API
void PostHandlerWithException(
549 RR_WEAK_PTR<RobotRaconteurNode> node,
550 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler, std::exception& exp,
551 MessageErrorType default_err = MessageErrorType_UnknownError,
bool shutdown_op =
false,
552 bool throw_on_released =
true);
554 template <
typename T>
555 void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
556 const typename boost::function<
void(
const T&,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
557 const T& value,
bool shutdown_op =
false,
bool throw_on_released =
true)
559 boost::function<void()> h = boost::bind(handler, value, RR_SHARED_PTR<RobotRaconteurException>());
560 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
563 template <
typename T>
564 void PostHandlerWithException(
565 RR_WEAK_PTR<RobotRaconteurNode> node,
566 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
567 const RR_SHARED_PTR<RobotRaconteurException>& exp,
bool shutdown_op =
false,
bool throw_on_released =
true)
569 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
570 boost::function<void()> h = boost::bind(handler, default_value, exp);
571 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
574 template <
typename T>
575 void PostHandlerWithException(
576 RR_WEAK_PTR<RobotRaconteurNode> node,
577 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
578 std::exception& exp, MessageErrorType default_err = MessageErrorType_UnknownError,
bool shutdown_op =
false,
579 bool throw_on_released =
true)
581 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
582 RR_SHARED_PTR<RobotRaconteurException> err = RobotRaconteurExceptionUtil::ExceptionToSharedPtr(exp, default_err);
583 boost::function<void()> h = boost::bind(handler, default_value, err);
584 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
#define RR_TIMEOUT_INFINITE
Disable timeout for asynchronous operations.
Definition: RobotRaconteurConstants.h:566