24#include <boost/bind/placeholders.hpp>
25#include <boost/scope_exit.hpp>
26#include <boost/system/error_code.hpp>
27#include <boost/bind/bind.hpp>
37namespace RobotRaconteur
44class sync_async_handler :
private boost::noncopyable
47 RR_SHARED_PTR<AutoResetEvent> ev;
48 RR_SHARED_PTR<RobotRaconteurException> err;
49 RR_SHARED_PTR<T> data;
50 boost::mutex data_lock;
52 sync_async_handler() { ev = RR_MAKE_SHARED<AutoResetEvent>(); }
54 sync_async_handler(
const RR_SHARED_PTR<RobotRaconteurException>& err)
56 ev = RR_MAKE_SHARED<AutoResetEvent>();
60 void operator()() { ev->Set(); }
62 void operator()(
const RR_SHARED_PTR<RobotRaconteurException>& err)
64 boost::mutex::scoped_lock lock(data_lock);
69 void operator()(
const RR_SHARED_PTR<T>& data,
const RR_SHARED_PTR<RobotRaconteurException>& err)
71 boost::mutex::scoped_lock lock(data_lock);
77 RR_SHARED_PTR<T> end()
81 boost::mutex::scoped_lock lock(data_lock);
84 RobotRaconteurExceptionUtil::DownCastAndThrowException(err);
88 throw InternalErrorException(
"Internal async error");
97 boost::mutex::scoped_lock lock(data_lock);
100 RobotRaconteurExceptionUtil::DownCastAndThrowException(err);
104 bool try_end(RR_SHARED_PTR<T>& res, RR_SHARED_PTR<RobotRaconteurException>& err_out)
108 boost::mutex::scoped_lock lock(data_lock);
117 err_out = RR_MAKE_SHARED<InternalErrorException>(
"Internal async error");
125 bool try_end_void(RR_SHARED_PTR<RobotRaconteurException>& err_out)
129 boost::mutex::scoped_lock lock(data_lock);
140RR_SHARED_PTR<Timer> async_timeout_wrapper_CreateTimer(
const RR_SHARED_PTR<RobotRaconteurNode>& node,
141 const boost::posix_time::time_duration& period,
142 RR_MOVE_ARG(boost::function<
void(
const TimerEvent&)>) handler,
146void async_timeout_wrapper_closer(
const RR_SHARED_PTR<T>& d)
152 catch (std::exception&)
156template <
typename T,
typename T2>
157void async_timeout_wrapper_closer(
const RR_SHARED_PTR<T>& d)
161 RR_SHARED_PTR<T2> t2 = RR_DYNAMIC_POINTER_CAST<T2>(d);
166 catch (std::exception&)
171class async_timeout_wrapper :
public RR_ENABLE_SHARED_FROM_THIS<async_timeout_wrapper<T> >,
private boost::noncopyable
174 boost::function<void(
const RR_SHARED_PTR<T>&,
const RR_SHARED_PTR<RobotRaconteurException>&)> handler_;
175 RR_SHARED_PTR<Timer> timeout_timer_;
176 boost::mutex handled_lock;
178 RR_SHARED_PTR<RobotRaconteurException> timeout_exception_;
179 boost::function<void(
const RR_SHARED_PTR<T>&)> deleter_;
180 RR_WEAK_PTR<RobotRaconteurNode> node;
183 async_timeout_wrapper(
184 const RR_SHARED_PTR<RobotRaconteurNode>& node,
185 boost::function<
void(
const RR_SHARED_PTR<T>&,
const RR_SHARED_PTR<RobotRaconteurException>&)> handler,
186 RR_MOVE_ARG(boost::function<
void(
const RR_SHARED_PTR<T>&)>) deleter = 0)
187 : handler_(handler), handled(false), node(node)
189 deleter_.swap(deleter);
192 void start_timer(int32_t timeout,
const RR_SHARED_PTR<RobotRaconteurException>& timeout_exception =
193 RR_MAKE_SHARED<ConnectionException>(
"Timeout during operation"));
195 void operator()(
const RR_SHARED_PTR<T>& data,
const RR_SHARED_PTR<RobotRaconteurException>& err)
198 boost::mutex::scoped_lock lock(handled_lock);
201 if (data && deleter_)
208 timeout_timer_->TryStop();
210 timeout_timer_.reset();
216 void handle_error(
const RR_SHARED_PTR<RobotRaconteurException>& err)
219 boost::mutex::scoped_lock lock(handled_lock);
227 timeout_timer_->TryStop();
229 timeout_timer_.reset();
233 handler_(RR_SHARED_PTR<T>(), err);
236 void handle_error(
const boost::system::error_code& err)
238 if (err.value() == boost::system::errc::timed_out)
239 handle_error(timeout_exception_);
240 handle_error(RR_MAKE_SHARED<ConnectionException>(err.message()));
244 void timeout_handler(
const TimerEvent& )
247 boost::mutex::scoped_lock lock(handled_lock);
252 timeout_timer_.reset();
255 handler_(RR_SHARED_PTR<T>(), timeout_exception_);
260void 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);
274 timeout_exception_ = RR_MOVE(timeout_exception);
276 async_timeout_wrapper_CreateTimer(n, boost::posix_time::milliseconds(timeout),
277 boost::bind(&async_timeout_wrapper<T>::timeout_handler,
278 this->shared_from_this(), RR_BOOST_PLACEHOLDERS(_1)),
280 timeout_timer_->Start();
284class ROBOTRACONTEUR_CORE_API async_signal_semaphore :
private boost::noncopyable
287 boost::mutex this_lock;
288 boost::condition_variable next_wait;
289 boost::initialized<bool> running;
290 boost::initialized<bool> next;
291 boost::initialized<uint64_t> next_id;
294 template <
typename F>
295 bool try_fire_next(BOOST_ASIO_MOVE_ARG(F) h)
297 boost::mutex::scoped_lock lock(this_lock);
301 uint64_t my_id = ++next_id.data();
305 next_wait.notify_all();
314 next_wait.wait(lock);
315 if (my_id != next_id)
322 running.data() =
true;
324 BOOST_SCOPE_EXIT_TPL(this_)
326 boost::mutex::scoped_lock lock2(this_->this_lock);
327 this_->running.data() =
false;
328 this_->next_wait.notify_all();
330 BOOST_SCOPE_EXIT_END;
340class ROBOTRACONTEUR_CORE_API async_signal_pool_semaphore
341 :
public RR_ENABLE_SHARED_FROM_THIS<async_signal_pool_semaphore>,
342 private boost::noncopyable
345 boost::mutex this_lock;
346 boost::initialized<bool> running;
347 boost::function<void()> next;
348 RR_WEAK_PTR<RobotRaconteurNode> node;
351 async_signal_pool_semaphore(
const RR_SHARED_PTR<RobotRaconteurNode>& node) : node(node) {}
353 template <
typename F>
354 void try_fire_next(BOOST_ASIO_MOVE_ARG(F) h)
356 boost::mutex::scoped_lock lock(this_lock);
360 RR_SHARED_PTR<RobotRaconteurNode> node1 = this->node.lock();
372 void do_fire_next(
const boost::function<
void()>& h)
378 catch (std::exception& exp)
380 handle_exception(&exp);
383 BOOST_SCOPE_EXIT(this_)
385 boost::mutex::scoped_lock lock2(this_->this_lock);
387 boost::function<void()> h2;
388 h2.swap(this_->next);
390 this_->running.data() =
false;
393 RR_SHARED_PTR<RobotRaconteurNode> node = this_->node.lock();
399 boost::bind(&async_signal_pool_semaphore::do_fire_next, this_->shared_from_this(), h2));
401 catch (std::exception&)
403 this_->running.data() =
true;
405 BOOST_SCOPE_EXIT_END;
408 void do_post(
const RR_SHARED_PTR<RobotRaconteurNode>& node1, RR_MOVE_ARG(boost::function<
void()>) h);
410 void handle_exception(std::exception* exp);
413ROBOTRACONTEUR_CORE_API
void InvokeHandler_HandleException(RR_WEAK_PTR<RobotRaconteurNode> node, std::exception& exp);
415ROBOTRACONTEUR_CORE_API
void InvokeHandler_DoPost(RR_WEAK_PTR<RobotRaconteurNode> node,
416 const boost::function<
void()>& h,
bool shutdown_op =
false,
417 bool throw_on_released =
true);
419ROBOTRACONTEUR_CORE_API
void InvokeHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
420 const boost::function<
void()>& handler);
423void InvokeHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const typename boost::function<
void(
const T&)>& handler,
430 catch (std::exception& exp)
432 InvokeHandler_HandleException(RR_MOVE(node), exp);
436ROBOTRACONTEUR_CORE_API
void InvokeHandler(
437 RR_WEAK_PTR<RobotRaconteurNode> node,
438 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler);
440ROBOTRACONTEUR_CORE_API
void InvokeHandlerWithException(
441 RR_WEAK_PTR<RobotRaconteurNode> node,
442 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
443 const RR_SHARED_PTR<RobotRaconteurException>& exp);
445ROBOTRACONTEUR_CORE_API
void InvokeHandlerWithException(
446 RR_WEAK_PTR<RobotRaconteurNode> node,
447 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler, std::exception& exp,
448 MessageErrorType default_err = MessageErrorType_UnknownError);
452 RR_WEAK_PTR<RobotRaconteurNode> node,
453 const typename boost::function<
void(
const T&,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
458 handler(value, RR_SHARED_PTR<RobotRaconteurException>());
460 catch (std::exception& exp)
462 InvokeHandler_HandleException(RR_MOVE(node), exp);
467void InvokeHandlerWithException(
468 RR_WEAK_PTR<RobotRaconteurNode> node,
469 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
470 const RR_SHARED_PTR<RobotRaconteurException>& exp)
472 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
475 handler(default_value, exp);
477 catch (std::exception& exp)
479 InvokeHandler_HandleException(RR_MOVE(node), exp);
484void InvokeHandlerWithException(
485 RR_WEAK_PTR<RobotRaconteurNode> node,
486 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
487 std::exception& exp, MessageErrorType default_err = MessageErrorType_UnknownError)
489 typename boost::initialized<typename boost::remove_const<typename boost::remove_reference<T>::type>::type>
493 RR_SHARED_PTR<RobotRaconteurException> err =
494 RobotRaconteurExceptionUtil::ExceptionToSharedPtr(exp, default_err);
495 handler(default_value, err);
497 catch (std::exception& exp)
499 InvokeHandler_HandleException(RR_MOVE(node), exp);
503ROBOTRACONTEUR_CORE_API
void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const boost::function<
void()>& handler,
504 bool shutdown_op =
false,
bool throw_on_released =
true);
507void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
const typename boost::function<
void(
const T&)>& handler,
508 const T& value,
bool shutdown_op =
false,
bool throw_on_released =
true)
510 boost::function<void()> h = boost::bind(handler, value);
511 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
514ROBOTRACONTEUR_CORE_API
void PostHandler(
515 RR_WEAK_PTR<RobotRaconteurNode> node,
516 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
bool shutdown_op =
false,
517 bool throw_on_released =
true);
519ROBOTRACONTEUR_CORE_API
void PostHandlerWithException(
520 RR_WEAK_PTR<RobotRaconteurNode> node,
521 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
522 const RR_SHARED_PTR<RobotRaconteurException>& exp,
bool shutdown_op =
false,
bool throw_on_released =
true);
524ROBOTRACONTEUR_CORE_API
void PostHandlerWithException(
525 RR_WEAK_PTR<RobotRaconteurNode> node,
526 const boost::function<
void(
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler, std::exception& exp,
527 MessageErrorType default_err = MessageErrorType_UnknownError,
bool shutdown_op =
false,
528 bool throw_on_released =
true);
531void PostHandler(RR_WEAK_PTR<RobotRaconteurNode> node,
532 const typename boost::function<
void(
const T&,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
533 const T& value,
bool shutdown_op =
false,
bool throw_on_released =
true)
535 boost::function<void()> h = boost::bind(handler, value, RR_SHARED_PTR<RobotRaconteurException>());
536 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
540void PostHandlerWithException(
541 RR_WEAK_PTR<RobotRaconteurNode> node,
542 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
543 const RR_SHARED_PTR<RobotRaconteurException>& exp,
bool shutdown_op =
false,
bool throw_on_released =
true)
545 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
546 boost::function<void()> h = boost::bind(handler, default_value, exp);
547 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
551void PostHandlerWithException(
552 RR_WEAK_PTR<RobotRaconteurNode> node,
553 const typename boost::function<
void(T,
const RR_SHARED_PTR<RobotRaconteurException>&)>& handler,
554 std::exception& exp, MessageErrorType default_err = MessageErrorType_UnknownError,
bool shutdown_op =
false,
555 bool throw_on_released =
true)
557 typename boost::initialized<typename boost::remove_reference<T>::type> default_value;
558 RR_SHARED_PTR<RobotRaconteurException> err = RobotRaconteurExceptionUtil::ExceptionToSharedPtr(exp, default_err);
559 boost::function<void()> h = boost::bind(handler, default_value, err);
560 InvokeHandler_DoPost(RR_MOVE(node), h, shutdown_op, throw_on_released);
#define RR_TIMEOUT_INFINITE
Disable timeout for asynchronous operations.
Definition RobotRaconteurConstants.h:566
The central node implementation.
Definition RobotRaconteurNode.h:132