Add bt node result interception & re-throw node
This commit is contained in:
parent
a1a1dbd56e
commit
0a42a015eb
2 changed files with 150 additions and 0 deletions
25
libs/bt/include/psemek/bt/finally.hpp
Normal file
25
libs/bt/include/psemek/bt/finally.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/bt/node.hpp>
|
||||||
|
#include <psemek/bt/sequence.hpp>
|
||||||
|
#include <psemek/bt/success.hpp>
|
||||||
|
#include <psemek/bt/trampoline.hpp>
|
||||||
|
|
||||||
|
namespace psemek::bt
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Tree>
|
||||||
|
node_ptr<Tree> finally(node_ptr<Tree> child, node_ptr<Tree> finalizator)
|
||||||
|
{
|
||||||
|
trampoline<Tree> t;
|
||||||
|
|
||||||
|
return
|
||||||
|
t.rethrow(
|
||||||
|
bt::sequence(
|
||||||
|
bt::success(t.intercept(std::move(child))),
|
||||||
|
std::move(finalizator)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
125
libs/bt/include/psemek/bt/trampoline.hpp
Normal file
125
libs/bt/include/psemek/bt/trampoline.hpp
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/bt/node.hpp>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace psemek::bt
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Tree>
|
||||||
|
struct trampoline_state
|
||||||
|
{
|
||||||
|
std::optional<typename bt::node<Tree>::status> cached_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Tree>
|
||||||
|
struct trampoline_intercept_node;
|
||||||
|
|
||||||
|
template <typename Tree>
|
||||||
|
struct trampoline_rethrow_node;
|
||||||
|
|
||||||
|
template <typename Time, typename Event, typename ... Args>
|
||||||
|
struct trampoline_intercept_node<tree<Time, Event, Args...>>
|
||||||
|
: node<tree<Time, Event, Args...>>
|
||||||
|
{
|
||||||
|
using tree_type = tree<Time, Event, Args...>;
|
||||||
|
using node_type = node<tree_type>;
|
||||||
|
using typename node_type::finished;
|
||||||
|
using typename node_type::status;
|
||||||
|
|
||||||
|
trampoline_intercept_node(node_ptr<tree_type> child, std::shared_ptr<detail::trampoline_state<tree<Time, Event, Args...>>> state)
|
||||||
|
: child_(std::move(child))
|
||||||
|
, state_(std::move(state))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void start(Args ... args) override
|
||||||
|
{
|
||||||
|
child_->start(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
status update(Time dt, Args ... args) override
|
||||||
|
{
|
||||||
|
auto result = child_->update(dt, args...);
|
||||||
|
if (auto f = std::get_if<finished>(&result))
|
||||||
|
state_->cached_status = *f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool event(Event const & event, Args ... args) override
|
||||||
|
{
|
||||||
|
return child_->event(event, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
node_ptr<tree<Time, Event, Args...>> child_;
|
||||||
|
std::shared_ptr<detail::trampoline_state<tree<Time, Event, Args...>>> state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Time, typename Event, typename ... Args>
|
||||||
|
struct trampoline_rethrow_node<tree<Time, Event, Args...>>
|
||||||
|
: node<tree<Time, Event, Args...>>
|
||||||
|
{
|
||||||
|
using tree_type = tree<Time, Event, Args...>;
|
||||||
|
using node_type = node<tree_type>;
|
||||||
|
using typename node_type::finished;
|
||||||
|
using typename node_type::status;
|
||||||
|
|
||||||
|
trampoline_rethrow_node(node_ptr<tree_type> child, std::shared_ptr<detail::trampoline_state<tree<Time, Event, Args...>>> state)
|
||||||
|
: child_(std::move(child))
|
||||||
|
, state_(std::move(state))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void start(Args ... args) override
|
||||||
|
{
|
||||||
|
child_->start(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
status update(Time dt, Args ... args) override
|
||||||
|
{
|
||||||
|
auto result = child_->update(dt, args...);
|
||||||
|
if (std::get_if<finished>(&result) && state_->cached_status)
|
||||||
|
{
|
||||||
|
result = *state_->cached_status;
|
||||||
|
state_->cached_status = std::nullopt;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool event(Event const & event, Args ... args) override
|
||||||
|
{
|
||||||
|
return child_->event(event, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
node_ptr<tree<Time, Event, Args...>> child_;
|
||||||
|
std::shared_ptr<detail::trampoline_state<tree<Time, Event, Args...>>> state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tree>
|
||||||
|
struct trampoline
|
||||||
|
{
|
||||||
|
trampoline()
|
||||||
|
: state_(std::make_shared<detail::trampoline_state<Tree>>())
|
||||||
|
{}
|
||||||
|
|
||||||
|
node_ptr<Tree> intercept(node_ptr<Tree> child)
|
||||||
|
{
|
||||||
|
return std::make_unique<trampoline_intercept_node<Tree>>(std::move(child), state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_ptr<Tree> rethrow(node_ptr<Tree> child)
|
||||||
|
{
|
||||||
|
return std::make_unique<trampoline_rethrow_node<Tree>>(std::move(child), state_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<detail::trampoline_state<Tree>> state_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue