diff --git a/libs/bt/include/psemek/bt/timeout.hpp b/libs/bt/include/psemek/bt/timeout.hpp new file mode 100644 index 00000000..ede8d7e0 --- /dev/null +++ b/libs/bt/include/psemek/bt/timeout.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include + +namespace psemek::bt +{ + + template + struct timeout_node; + + template + struct timeout_node, DurationFn> + : node> + { + using tree_type = tree; + using node_type = node; + using typename node_type::finished; + using typename node_type::status; + + timeout_node(node_ptr child, DurationFn && duration_fn) + : child_(std::move(child)) + , duration_fn_(std::move(duration_fn)) + {} + + void start(Args ... args) override + { + timer_ = duration_fn_(args...); + child_->start(args...); + } + + status update(Time dt, Args ... args) override + { + timer_ -= dt; + if (timer_ <= Time{0}) + return finished{false}; + + return child_->update(dt, args...); + } + + bool event(Event const & event, Args ... args) override + { + return child_->event(event, args...); + } + + private: + node_ptr> child_; + DurationFn duration_fn_; + Time timer_ = Time{}; + }; + + namespace detail + { + + template + struct timeout_helper + { + static node_ptr make(node_ptr child, DurationFn && duration_fn) + { + return std::make_unique>(std::move(child), std::move(duration_fn)); + } + }; + + template + struct timeout_helper, Time> + { + static node_ptr> make(node_ptr> child, Time duration) + { + auto duration_fn = [duration](Args ...){ return duration; }; + return std::make_unique, decltype(duration_fn)>>(std::move(child), std::move(duration_fn)); + } + }; + + } + + template + node_ptr timeout(node_ptr child, DurationFn && duration_fn) + { + return detail::timeout_helper::make(std::move(child), std::move(duration_fn)); + } + +}