sandbox
Loading...
Searching...
No Matches
task_graph.hpp
1// SPDX-License-Identifier: MIT
2// #ifndef LIBSBX_CONTAINERS_TASK_GRAPH_HPP_
3// #define LIBSBX_CONTAINERS_TASK_GRAPH_HPP_
4
5// #include <cstdint>
6
7// #include <string>
8// #include <variant>
9// #include <vector>
10// #include <memory>
11// #include <functional>
12// #include <algorithm>
13
14// namespace sbx::containers {
15
16// namespace detail {
17
18// enum class node_state : std::uint32_t {
19// none = 0x00000000,
20// conditioned = 0x10000000,
21// preempted = 0x20000000,
22// retain_subflow = 0x40000000,
23// joined_subflow = 0x80000000
24// }; // enum class node_state
25
26// enum class error_state : std::uint32_t {
27// none = 0x00000000,
28// exception = 0x10000000,
29// cancelled = 0x20000000,
30// anchored = 0x40000000
31// }; // enum class node_state
32
33// template<typename T, typename>
34// struct get_index;
35
36// template<std::size_t I, typename... Ts>
37// struct get_index_impl {};
38
39// template<std::size_t I, typename T, typename... Ts>
40// struct get_index_impl<I, T, T, Ts...> : std::integral_constant<std::size_t, I>{};
41
42// template<std::size_t I, typename T, typename U, typename... Ts>
43// struct get_index_impl<I, T, U, Ts...> : get_index_impl<I+1u, T, Ts...>{};
44
45// template<typename T, typename... Ts>
46// struct get_index<T, std::variant<Ts...>> : get_index_impl<0u, T, Ts...>{};
47
48// template<typename T, typename... Ts>
49// constexpr auto get_index_v = get_index<T, Ts...>::value;
50
51// class graph_node;
52// class graph_base;
53// class graph_builder;
54// class task;
55// class sub_graph;
56
57// class graph_base : std::vector<std::unique_ptr<graph_node>> {
58
59// friend class graph_node;
60// friend class graph_builder;
61
62// using base = std::vector<std::unique_ptr<graph_node>>;
63
64// public:
65
66// graph_base() = default;
67
68// graph_base(const graph_base& other) = delete;
69
70// graph_base(graph_base&& other) = default;
71
72// auto operator=(const graph_base& other) -> graph_base& = delete;
73
74// auto operator=(graph_base&& other) -> graph_base& = default;
75
76// private:
77
78// auto _reserve(const std::size_t capacity) -> void;
79
80// auto _erase(graph_node* node) -> void;
81
82// template<typename... Args>
83// auto _emplace_back(Args&&... args) -> graph_node*;
84
85// }; // class graph_base
86
87// struct task_parameters {
88// std::string name;
89// void*data ;
90// }; // struct task_parameters
91
92// struct default_task_parameters { };
93
94// template<typename Type>
95// constexpr bool is_task_params_v = std::is_same_v<std::decay_t<Type>, task_parameters> || std::is_same_v<std::decay_t<Type>, default_task_parameters> || std::is_constructible_v<std::string, Type>;
96
97// template<typename Callable, typename = void>
98// struct is_static_task : std::false_type{ };
99
100// template<typename Callable>
101// struct is_static_task<Callable, std::enable_if_t<std::is_invocable_v<Callable>>> : std::is_same<std::invoke_result_t<Callable>, void> { };
102
103// template <typename Callable>
104// constexpr bool is_static_task_v = is_static_task<Callable>::value;
105
106// class graph_node {
107
108// friend class graph_builder;
109// friend class task;
110
111// using placeholder_task = std::monostate;
112
113// struct static_task {
114
115// template<typename Callable>
116// static_task(Callable&& callable);
117
118// std::function<void()> work;
119// }; // struct static_task
120
121// struct sub_graph {
122
123// template<typename Callable>
124// sub_graph(Callable&& callable);
125
126// std::function<void(sub_graph&)> work;
127// graph_base graph;
128// }; // struct sub_graph
129
130
131// using task_handle = std::variant<placeholder_task, static_task>;
132
133// public:
134
135// inline static constexpr auto placeholder = get_index_v<placeholder_task, task_handle>;
136// inline static constexpr auto static_work = get_index_v<static_task, task_handle>;
137
138// graph_node();
139
140// template<typename... Args>
141// graph_node(node_state node_state, const task_parameters& parameters, graph_node* parent, Args&&...);
142
143// template<typename... Args>
144// graph_node(node_state node_state,const default_task_parameters& parameters, graph_node* parent, Args&&...);
145
146// auto num_successors() const -> std::size_t;
147// auto num_predecessors() const -> std::size_t;
148
149// auto name() const -> const std::string&;
150
151
152// private:
153
154// auto _precede(graph_node* node) -> void;
155// auto _remove_successors(graph_node* node) -> void;
156// auto _remove_predecessors(graph_node* node) -> void;
157
158// node_state _state;
159// std::string _name;
160// void* _data;
161// graph_node* _parent;
162// std::size_t _num_successors;
163// std::vector<graph_node*> _edges;
164// task_handle _handle;
165
166// }; // class graph_node
167
168// class task {
169
170// friend class graph_builder;
171
172// public:
173
174// auto name() const -> const std::string&;
175
176// auto num_predecessors() const -> std::size_t;
177// auto num_successors() const -> std::size_t;
178
179// template<typename... Tasks>
180// auto precede(Tasks&&... tasks) -> task&;
181
182// template<typename... Tasks>
183// auto succeed(Tasks&&... tasks) -> task&;
184
185// private:
186
187// task(graph_node* node);
188
189// graph_node* _node;
190
191// }; // class task
192
193// class graph_builder {
194
195// public:
196
197// graph_builder(graph_base& graph);
198
199// template <typename Callable>
200// requires (is_static_task_v<Callable>)
201// auto emplace(Callable&& callable) -> task;
202
203// template<typename... Callables>
204// requires (sizeof...(Callables) > 1u)
205// auto emplace(Callables&&... callables) -> decltype(auto);
206
207// protected:
208
209// graph_base& _graph;
210
211// private:
212
213// }; // class graph_builder
214
215// class sub_graph : public graph_builder {
216
217// public:
218
219// private:
220
221// sub_graph(graph_node* parent, graph_base& graph)
222// : graph_builder{graph},
223// _parent{parent} { }
224
225// graph_node* _parent;
226
227// }; // class subgraph
228
229// auto graph_base::_reserve(const std::size_t capacity) -> void {
230// base::reserve(capacity);
231// }
232
233// auto graph_base::_erase(graph_node* node) -> void {
234// base::erase(std::remove_if(base::begin(), base::end(), [&](auto& entry){ return entry.get() == node; }), base::end() );
235// }
236
237// template<typename... Args>
238// auto graph_base::_emplace_back(Args&&... args) -> graph_node* {
239// base::push_back(std::make_unique<graph_node>(std::forward<Args>(args)...));
240// return back().get();
241// }
242
243// template<typename Callable>
244// graph_node::static_task::static_task(Callable&& callable)
245// : work{std::forward<Callable>(callable)} { }
246
247// template<typename Callable>
248// graph_node::sub_graph::sub_graph(Callable&& callable)
249// : work{std::forward<Callable>(callable)} { }
250
251// graph_node::graph_node()
252// : _state{node_state::none},
253// _data{nullptr},
254// _parent{nullptr},
255// _num_successors{0u} { }
256
257// template<typename... Args>
258// graph_node::graph_node(node_state node_state, const task_parameters& parameters, graph_node* parent, Args&&... args)
259// : _state{node_state},
260// _name{parameters.name},
261// _data{parameters.data},
262// _parent{parent},
263// _num_successors{0u},
264// _handle{std::forward<Args>(args)...} { }
265
266// template<typename... Args>
267// graph_node::graph_node(node_state node_state, const default_task_parameters& parameters, graph_node* parent, Args&&...args)
268// : _state{node_state},
269// _data{nullptr},
270// _parent{parent},
271// _num_successors{0u},
272// _handle{std::forward<Args>(args)...} { }
273
274// auto graph_node::num_successors() const -> std::size_t {
275// return _num_successors;
276// }
277
278// auto graph_node::num_predecessors() const -> std::size_t {
279// return _edges.size() - _num_successors;
280// }
281
282// auto graph_node::name() const -> const std::string& {
283// return _name;
284// }
285
286// auto graph_node::_precede(graph_node* node) -> void {
287// _edges.push_back(node);
288// std::swap(_edges[_num_successors++], _edges[_edges.size() - 1]);
289// node->_edges.push_back(this);
290// }
291
292// auto graph_node::_remove_successors(graph_node* node) -> void {
293// auto sit = std::remove(_edges.begin(), _edges.begin() + _num_successors, node);
294// size_t new_num_successors = std::distance(_edges.begin(), sit);
295// std::move(_edges.begin() + _num_successors, _edges.end(), sit);
296// _edges.resize(_edges.size() - (_num_successors - new_num_successors));
297// _num_successors = new_num_successors;
298// }
299
300// auto graph_node::_remove_predecessors(graph_node* node) -> void {
301// _edges.erase(std::remove(_edges.begin() + _num_successors, _edges.end(), node), _edges.end());
302// }
303
304// auto task::name() const -> const std::string& {
305// return _node->name();
306// }
307
308// auto task::num_predecessors() const -> std::size_t {
309// return _node->num_predecessors();
310// }
311
312// auto task::num_successors() const -> std::size_t {
313// return _node->num_predecessors();
314// }
315
316// template<typename... Tasks>
317// auto task::precede(Tasks&&... tasks) -> task& {
318// (_node->_precede(tasks._node), ...);
319// return *this;
320// }
321
322// template<typename... Tasks>
323// auto task::succeed(Tasks&&... tasks) -> task& {
324// (tasks._node->_precede(_node), ...);
325// return *this;
326// }
327
328// task::task(graph_node* node)
329// : _node{node} { }
330
331// graph_builder::graph_builder(graph_base& graph)
332// : _graph{graph} { }
333
334// template <typename Callable>
335// requires (is_static_task_v<Callable>)
336// auto graph_builder::emplace(Callable&& callable) -> task {
337// return task{_graph._emplace_back(node_state::none, default_task_parameters{}, nullptr, std::in_place_type_t<graph_node::static_task>{}, std::forward<Callable>(callable) )};
338// }
339
340// template<typename... Callables>
341// requires (sizeof...(Callables) > 1u)
342// auto graph_builder::emplace(Callables&&... callables) -> decltype(auto) {
343// _graph.reserve(sizeof...(Callables));
344// return std::make_tuple(emplace(std::forward<Callables>(callables))...);
345// }
346
347// } // namespace detail
348
349// class task_graph : public detail::graph_builder {
350
351// using base = detail::graph_builder;
352
353// public:
354
355// task_graph(const std::string& name)
356// : base{_graph},
357// _name{name} { }
358
359// private:
360
361// detail::graph_base _graph;
362// std::string _name;
363
364// }; // class graph
365
366
367// } // namespace sbx::containers
368
369// #endif // LIBSBX_CONTAINERS_TASK_GRAPH_HPP_