Skip to content

Commit 35d066b

Browse files
committed
🎨 Use flow log spec if step log spec is not defined
1 parent 40911e6 commit 35d066b

File tree

7 files changed

+100
-68
lines changed

7 files changed

+100
-68
lines changed

include/flow/builder.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <flow/common.hpp>
55
#include <flow/graph_builder.hpp>
66
#include <flow/impl.hpp>
7-
#include <log/level.hpp>
87

98
#include <stdx/ct_string.hpp>
109

include/flow/graph_builder.hpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@
2727
namespace flow {
2828
namespace detail {
2929
template <typename T> using is_duplicated = std::bool_constant<(T::size() > 1)>;
30-
}
30+
31+
template <typename CTNode, typename Output>
32+
concept is_output_compatible = requires(CTNode n) {
33+
{ Output::create_node(n) } -> std::same_as<typename Output::node_t>;
34+
};
35+
} // namespace detail
36+
3137
template <typename T> using name_for = typename T::name_t;
3238

3339
[[nodiscard]] constexpr auto edge_size(auto const &nodes,
@@ -57,12 +63,14 @@ template <stdx::ct_string Name,
5763
template <stdx::ct_string, std::size_t> typename Impl>
5864
struct graph_builder {
5965
// NOLINTBEGIN(readability-function-cognitive-complexity)
60-
template <typename Node, std::size_t N, std::size_t E>
66+
template <typename Output, std::size_t N, std::size_t E>
6167
[[nodiscard]] constexpr static auto make_graph(auto const &nodes,
6268
auto const &edges) {
63-
using graph_t = stdx::cx_multimap<Node, Node, N, E>;
69+
using output_node_t = typename Output::node_t;
70+
using graph_t = stdx::cx_multimap<output_node_t, output_node_t, N, E>;
6471
graph_t g{};
65-
for_each([&](auto const &node) { g.put(node); }, nodes);
72+
for_each([&]<typename Node>(Node n) { g.put(Output::create_node(n)); },
73+
nodes);
6674

6775
auto const named_nodes = stdx::apply_indices<name_for>(nodes);
6876
for_each(
@@ -96,7 +104,7 @@ struct graph_builder {
96104
},
97105
node_ps);
98106

99-
g.put(lhs, rhs);
107+
g.put(Output::create_node(lhs), Output::create_node(rhs));
100108
},
101109
edges);
102110
return g;
@@ -213,18 +221,16 @@ struct graph_builder {
213221
constexpr auto edge_capacity = edge_size(node_set, edges);
214222

215223
using output_t = Impl<Graph::name, node_capacity>;
216-
using rt_node_t = typename output_t::node_t;
217-
218224
static_assert(
219225
all_of(
220226
[]<typename N>(N const &) {
221-
return std::is_convertible_v<N, rt_node_t>;
227+
return detail::is_output_compatible<N, output_t>;
222228
},
223229
node_set),
224230
"Output node type is not compatible with given input nodes");
225231

226-
auto g = make_graph<rt_node_t, node_capacity, edge_capacity>(node_set,
227-
edges);
232+
auto g =
233+
make_graph<output_t, node_capacity, edge_capacity>(node_set, edges);
228234
return topo_sort<output_t>(g);
229235
}
230236

include/flow/impl.hpp

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <flow/step.hpp>
55
#include <log/log.hpp>
66

7+
#include <stdx/ct_string.hpp>
78
#include <stdx/cx_vector.hpp>
89
#include <stdx/span.hpp>
910

@@ -13,6 +14,41 @@
1314
#include <type_traits>
1415

1516
namespace flow {
17+
namespace detail {
18+
template <typename CTNode> constexpr auto run_func() -> void {
19+
if (CTNode::condition) {
20+
typename CTNode::func_t{}();
21+
}
22+
}
23+
24+
template <typename Flow, typename CTNode> constexpr auto log_func() -> void {
25+
if (CTNode::condition) {
26+
using log_spec_t = decltype(get_log_spec<CTNode, Flow>());
27+
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level, "flow.{}({})",
28+
typename CTNode::type_t{}, typename CTNode::name_t{});
29+
}
30+
}
31+
} // namespace detail
32+
33+
struct rt_node {
34+
constexpr rt_node() = default;
35+
36+
template <typename Flow, typename CTNode> constexpr rt_node(Flow, CTNode) {
37+
// GCC wants these to be explicitly marked constexpr
38+
constexpr auto rf = detail::run_func<CTNode>;
39+
constexpr auto lf = detail::log_func<Flow, CTNode>;
40+
run = rf;
41+
log_name = lf;
42+
}
43+
44+
FunctionPtr run{};
45+
FunctionPtr log_name{};
46+
47+
private:
48+
friend constexpr auto operator==(rt_node const &,
49+
rt_node const &) -> bool = default;
50+
};
51+
1652
/**
1753
* flow::impl is a constant representation of a series of Milestones and actions
1854
* to be executed in a specific order.
@@ -45,11 +81,16 @@ template <stdx::ct_string Name, std::size_t NumSteps> class impl {
4581
public:
4682
stdx::cx_vector<FunctionPtr, capacity> functionPtrs{};
4783

48-
using node_t = rt_node;
4984
constexpr static bool active = capacity > 0;
50-
5185
constexpr static auto name = Name;
5286

87+
using node_t = rt_node;
88+
89+
template <typename CTNode>
90+
constexpr static auto create_node(CTNode n) -> node_t {
91+
return node_t{log_spec_id_t<Name>{}, n};
92+
}
93+
5394
/**
5495
* Create a new flow::impl of Milestones.
5596
*
@@ -60,17 +101,16 @@ template <stdx::ct_string Name, std::size_t NumSteps> class impl {
60101
*
61102
* @see flow::builder
62103
*/
63-
constexpr explicit(true)
64-
impl(stdx::span<node_t const, NumSteps> newMilestones) {
104+
constexpr explicit(true) impl(stdx::span<node_t const, NumSteps> steps) {
65105
if constexpr (loggingEnabled) {
66-
for (auto const &milestone : newMilestones) {
67-
functionPtrs.push_back(milestone.log_name);
68-
functionPtrs.push_back(milestone.run);
106+
for (auto const &step : steps) {
107+
functionPtrs.push_back(step.log_name);
108+
functionPtrs.push_back(step.run);
69109
}
70110
} else {
71-
std::transform(std::cbegin(newMilestones), std::cend(newMilestones),
111+
std::transform(std::cbegin(steps), std::cend(steps),
72112
std::back_inserter(functionPtrs),
73-
[](auto const &milestone) { return milestone.run; });
113+
[](auto const &step) { return step.run; });
74114
}
75115
}
76116
};

include/flow/log.hpp

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include <log/log.hpp>
44

5+
#include <stdx/ct_string.hpp>
6+
57
#include <type_traits>
68

79
namespace flow {
@@ -12,21 +14,23 @@ struct default_log_spec {
1214
template <stdx::ct_string, typename...>
1315
constexpr auto log_spec = default_log_spec{};
1416

15-
template <typename T, typename... DummyArgs>
17+
template <stdx::ct_string Name> struct log_spec_id_t {
18+
constexpr static auto ct_name = Name;
19+
};
20+
21+
template <typename T, typename Fallback = log_spec_id_t<"default">,
22+
typename... DummyArgs>
1623
requires(sizeof...(DummyArgs) == 0)
1724
constexpr static auto get_log_spec() {
18-
if constexpr (std::is_same_v<decltype(log_spec<T::ct_name, DummyArgs...>),
19-
default_log_spec const>) {
20-
return log_spec<"default", DummyArgs...>;
25+
using log_spec_t = decltype(log_spec<T::ct_name, DummyArgs...>);
26+
if constexpr (std::is_same_v<log_spec_t, default_log_spec const>) {
27+
if constexpr (Fallback::ct_name == stdx::ct_string{"default"}) {
28+
return log_spec<Fallback::ct_name, DummyArgs...>;
29+
} else {
30+
return get_log_spec<Fallback>();
31+
}
2132
} else {
22-
return log_spec<T::ct_name, DummyArgs...>;
33+
return log_spec_t{};
2334
}
2435
}
25-
26-
template <typename T, typename... DummyArgs, typename... Args>
27-
auto log_with_spec(Args &&...args) {
28-
using log_spec_t = decltype(get_log_spec<T, DummyArgs...>());
29-
logging::log<typename log_spec_t::flavor, log_spec_t::level,
30-
cib_log_module_id_t>(std::forward<Args>(args)...);
31-
}
3236
} // namespace flow

include/flow/step.hpp

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,20 @@
1414
#include <type_traits>
1515

1616
namespace flow {
17-
struct rt_node {
18-
FunctionPtr run;
19-
FunctionPtr log_name;
20-
21-
private:
22-
friend constexpr auto operator==(rt_node const &,
23-
rt_node const &) -> bool = default;
24-
};
25-
26-
namespace detail {
27-
template <typename Cond, typename F> constexpr auto run_func() -> void {
28-
if (Cond{}) {
29-
F{}();
30-
}
31-
}
32-
33-
template <typename ct_node, typename Cond, stdx::ct_string Type,
34-
stdx::ct_string Name>
35-
constexpr auto log_func() -> void {
36-
if (Cond{}) {
37-
using log_spec_t = decltype(get_log_spec<ct_node>());
38-
CIB_LOG(typename log_spec_t::flavor, log_spec_t::level, "flow.{}({})",
39-
stdx::ct_string_to_type<Type, sc::string_constant>(),
40-
stdx::ct_string_to_type<Name, sc::string_constant>());
41-
}
42-
}
43-
} // namespace detail
44-
4517
template <stdx::ct_string Type, stdx::ct_string Name,
4618
subgraph_identity Identity, typename Cond, typename F>
4719
struct ct_node {
4820
using is_subgraph = void;
4921
using type_t =
5022
decltype(stdx::ct_string_to_type<Type, sc::string_constant>());
51-
5223
using name_t =
5324
decltype(stdx::ct_string_to_type<Name, sc::string_constant>());
25+
using func_t = F;
5426

5527
constexpr static auto ct_name = Name;
56-
5728
constexpr static auto identity = Identity;
58-
5929
constexpr static auto condition = Cond{};
6030

61-
constexpr operator rt_node() const {
62-
return rt_node{detail::run_func<Cond, F>,
63-
detail::log_func<ct_node, Cond, Type, Name>};
64-
}
65-
6631
constexpr auto operator*() const {
6732
if constexpr (Identity == subgraph_identity::REFERENCE) {
6833
return ct_node<Type, Name, subgraph_identity::VALUE, Cond, F>{};

include/seq/impl.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ template <stdx::ct_string, std::size_t NumSteps> struct impl {
2424

2525
using node_t = rt_step;
2626

27+
template <typename CTNode>
28+
constexpr static auto create_node(CTNode n) -> node_t {
29+
return n;
30+
}
31+
2732
constexpr explicit(true) impl(stdx::span<node_t const, NumSteps> steps) {
2833
for (auto const &step : steps) {
2934
_forward_steps.push_back(step.forward_ptr);

test/flow/custom_log_levels.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ constexpr auto run_flow = []() -> void {
3030

3131
struct TestFlowA : public flow::service<"A"> {};
3232
struct TestFlowB : public flow::service<"B"> {};
33+
struct TestFlowC : public flow::service<"C"> {};
3334

3435
constexpr auto msA = flow::milestone<"msA">();
3536
constexpr auto msB = flow::milestone<"msB">();
@@ -81,3 +82,15 @@ TEST_CASE("override log level by name", "[flow_custom_log_levels]") {
8182
CHECK(log_calls[1] == logging::level::USER2);
8283
CHECK(log_calls[2] == logging::level::USER1);
8384
}
85+
86+
template <> constexpr auto flow::log_spec<"C"> = user1_log_spec{};
87+
88+
TEST_CASE("default log spec for step will use overridden log spec for flow",
89+
"[flow_custom_log_levels]") {
90+
run_flow<TestFlowC, cib::exports<TestFlowC>,
91+
cib::extend<TestFlowC>(*msA)>();
92+
93+
REQUIRE(log_calls.size() == 3);
94+
std::for_each(std::begin(log_calls), std::end(log_calls),
95+
[](auto level) { CHECK(level == logging::level::USER1); });
96+
}

0 commit comments

Comments
 (0)