Sygaldry
Loading...
Searching...
No Matches
sygac-runtime.hpp
1#pragma once
2/*
3Copyright 2023 Travis J. West, https://traviswest.ca, Input Devices and Music
4Interaction Laboratory (IDMIL), Centre for Interdisciplinary Research in Music
5Media and Technology (CIRMMT), McGill University, Montréal, Canada, and Univ.
6Lille, Inria, CNRS, Centrale Lille, UMR 9189 CRIStAL, F-59000 Lille, France
7
8SPDX-License-Identifier: MIT
9*/
10
11#include <boost/mp11.hpp>
12#include "sygac-functions.hpp"
13#include "sygac-components.hpp"
14#include "sygac-endpoints.hpp"
15
16namespace sygaldry {
17
21
25
31template<typename ComponentContainer, typename ... Args>
33{
34 using arg_pack_t = decltype(tpl::forward_as_tuple(find<Args>(std::declval<ComponentContainer&>())...));
35 const arg_pack_t pack;
36
37 constexpr impl_arg_pack(ComponentContainer& container) : pack{tpl::forward_as_tuple(find<Args>(container) ...)} {}
38};
39
40template<typename...>
42{
43 struct dummy_t {
44 tpl::tuple<> pack;
45 constexpr dummy_t(auto&) : pack{} {};
46 };
47 using pack_t = dummy_t;
48};
49
50template<typename Component, typename ComponentContainer, typename FuncRefl>
51 requires FuncRefl::exists::value
53{
54 using args = typename FuncRefl::arguments;
55 using cvref_less = boost::mp11::mp_transform<std::remove_cvref_t, args>;
56 using prepended = boost::mp11::mp_push_front<cvref_less, ComponentContainer>;
57 using pack_t = boost::mp11::mp_rename<prepended, impl_arg_pack>;
58};
59
60template<typename Component, typename ComponentContainer>
62{
67
68 Component& component;
69 init_arg_pack init_args;
70 main_arg_pack main_args;
71 ext_src_arg_pack ext_src_args;
72 ext_dst_arg_pack ext_dst_args;
73
74 constexpr component_runtime(Component& comp, ComponentContainer& cont)
75 : component{comp}, init_args{cont}, main_args{cont}, ext_src_args{cont}, ext_dst_args{cont} {}
76
77 void init() const
78 {
79 if constexpr (requires {&Component::init;})
80 tpl::apply([&](auto& ... args) {component.init(args...);}, init_args.pack);
81 }
82
83 void external_sources() const
84 {
85 if constexpr (requires {&Component::external_sources;})
86 tpl::apply([&](auto& ... args) {component.external_sources(args...);}, ext_src_args.pack);
87 }
88
89 void main() const
90 {
91 if constexpr (requires {&Component::operator();})
92 tpl::apply(component, main_args.pack);
93 else if constexpr (requires {&Component::main;})
94 tpl::apply([&](auto& ... args) {component.main(args...);}, main_args.pack);
95 }
96
97 void external_destinations() const
98 {
99 if constexpr (requires {&Component::external_destinations;})
100 tpl::apply([&](auto& ... args) {component.external_destinations(args...);}, ext_dst_args.pack);
101 }
102};
103
104template<typename ComponentContainer>
105constexpr auto component_to_runtime_tuple(ComponentContainer& cont)
106{
107 auto tup = component_filter_by_tag<node::component>(cont);
108 if constexpr (is_tuple_v<decltype(tup)>)
109 return tup.map([&](auto& tagged_component)
110 {
111 return component_runtime{tagged_component.ref, cont};
112 });
113 // if there's only one component, `component_filter_by_tag` returns the tagged component directly
114 else return tpl::make_tuple(component_runtime{tup.ref, cont});
115}
117
118
148template<typename ComponentContainer>
150{
158 ComponentContainer& container;
159
170 decltype(component_to_runtime_tuple(std::declval<ComponentContainer&>())) component_runtimes;
171
181 constexpr Runtime(ComponentContainer& c) : container{c}, component_runtimes{component_to_runtime_tuple(c)} {};
182
184 void init() const
185 {
186 for_each_endpoint(container, []<typename T>(T& ep)
187 {
188 initialize_endpoint(ep);
189 });
190 tuple_for_each(component_runtimes, [](auto& r){r.init();});
191 }
192
194 void external_sources() const
195 {
196 tuple_for_each(component_runtimes, [](auto& r){clear_input_flags(r.component);});
197 tuple_for_each(component_runtimes, [](auto& r){r.external_sources();});
198 }
199
201 void main() const { tuple_for_each(component_runtimes, [](auto& r){r.main();}); }
202
205 {
206 tuple_for_each(component_runtimes, [](auto& r){r.external_destinations();});
207 tuple_for_each(component_runtimes, [](auto& r){clear_output_flags(r.component);});
208 }
209
211 void tick() const
212 {
214 main();
216 }
217
219 int app_main() const { for (init(); true; tick()) {} return 0; }
220};
221
224}
Check if T is a Sygaldry component.
Definition sygac-components.hpp:124
Wrapper for a component assemblage that calls init and main of all subcomponents that aren't parts.
Definition sygac-runtime.hpp:150
decltype(component_to_runtime_tuple(std::declval< ComponentContainer & >())) component_runtimes
A tuple of component-level runtimes.
Definition sygac-runtime.hpp:170
void external_sources() const
Clear input flags, then run the external sources subroutine of all components in the container that h...
Definition sygac-runtime.hpp:194
void main() const
Run the main subroutine of all components in the container.
Definition sygac-runtime.hpp:201
void tick() const
Run external sources, main, and external destinations, clearing flags appropriately.
Definition sygac-runtime.hpp:211
ComponentContainer & container
Definition sygac-runtime.hpp:158
void external_destinations() const
Run the external destinations subroutine of all components in the container that have one,...
Definition sygac-runtime.hpp:204
int app_main() const
A wrapper for init and tick that loops indefinitely, intended for instruments with simple requirement...
Definition sygac-runtime.hpp:219
constexpr Runtime(ComponentContainer &c)
The constructor, e.g. constexpr auto runtime = Runtime{container};
Definition sygac-runtime.hpp:181
void init() const
Initialize all components in the container.
Definition sygac-runtime.hpp:184
Definition sygac-runtime.hpp:62
Definition sygac-runtime.hpp:33
Definition sygac-runtime.hpp:43
Definition sygac-runtime.hpp:42