|
- #pragma once
-
- #include <ecs/config.h>
- #include <ecs/tag/system.h>
- #include <ecs/context/context.fwd.h>
- #include <ecs/core/utils/thread_pool/task_queue.h>
-
- namespace ecs {
- namespace core {
- namespace system {
- namespace scheduler {
-
- namespace detail
- {
- /**
- * meta data to store for each system instance
- */
- struct instance_meta_data_t
- {
- ssize_t thread_id = -1;
- };
-
- /**
- * struct to wrap some system meta data
- */
- template<
- typename T_system_tag,
- typename T_execute,
- typename T_dependency_ids>
- struct dependency_item_t
- {
- using system_tag_type = T_system_tag;
- using execute_type = T_execute;
- using dependency_ids_type = T_dependency_ids;
-
- system_tag_type tag; //!< tag of system this dependency element represents
- execute_type execute; //!< boolean value to determine if the system should be executed or not
- dependency_ids_type dependency_ids; //!< list of system IDs that depends on this system/item
- };
-
- /**
- * defines a task to be executed (represents a system to execute in the scheduler)
- *
- * @tparam T_dependency_item dependency item type for this task
- * @tparam T_dependent_ids id types of tasks that depends on this task
- */
- template<
- typename T_dependency_item,
- typename T_dependent_ids>
- struct task_t
- {
- public:
- using dependency_item_type = T_dependency_item;
- using dependent_ids_type = T_dependent_ids;
- using this_type = task_t<dependency_item_type, dependent_ids_type>;
-
- private:
- std::atomic<size_t> _dependency_count;
-
- public:
- mp::unwrap_t<dependency_item_type> dependency_item;
-
- /**
- * constructor
- */
- inline task_t();
-
- /**
- * get the number unfinished tasks, this task depends on
- */
- inline size_t dependency_count() const;
-
- /**
- * decrepent the unfished task counter
- *
- * @retval TRUE if all tasks, this task depends on, are finished
- * @retval FALSE if at least on task, this task depends on, is not finished
- */
- inline bool decrement_and_check();
-
- /**
- * execute the passed function for task ID that depends on this task
- *
- * @tparam T_func function type to execute
- *
- * @param func function to execute
- */
- template<typename T_func>
- constexpr decltype(auto) for_dependent_ids(T_func&& func) const noexcept;
- };
-
- /**
- * predicate type to create a list of task IDs that depends on the given task
- */
- struct dependent_ids_t
- {
- /**
- * execute the predicate
- *
- * @tparam T_dependency_items list of dependency items
- * @tparam T_dependency_item dependency item to get taks IDs for, that depends on that item
- *
- * @return list of task IDs that depends on the given dependency item
- */
- template<typename T_dependency_items, typename T_dependency_item>
- constexpr decltype(auto) operator()(T_dependency_items, T_dependency_item) const noexcept;
- };
-
- /**
- * predicate type to create a list of tasks
- */
- struct make_tasks_t
- {
- /**
- * execute the predicate
- *
- * @tparam T_dependency_items list of dependency items to create tasks from
- *
- * @return list of tasks
- */
- template<typename T_dependency_items>
- constexpr decltype(auto) operator()(T_dependency_items) const noexcept;
- };
-
- /**
- * extention of the normal counter_blocker to handle tasks to be executed in the context of the main thread
- */
- struct task_counter_blocker_t
- : public utils::counter_blocker
- {
- private:
- utils::task_queue _tasks; //!< tasks to execute in the main thread
-
- public:
- using utils::counter_blocker::counter_blocker;
-
- /**
- * enqueue a new task inside the task list
- *
- * @tparam T_task type of the task
- *
- * @param task task to execute
- */
- template<typename T_task>
- inline void post(T_task&& task);
-
- /**
- * execute all tasks stored in the queue
- */
- inline void process();
- };
-
- /**
- * defines a group of tasks to execute with
- *
- * @tparam T_context context type
- * @tparam T_dependency_items list of dependency items
- */
- template<typename T_context, typename T_dependency_items>
- struct task_group_t
- {
- public:
- using context_type = T_context;
- using dependency_items_type = T_dependency_items;
- using this_type = task_group_t<context_type, dependency_items_type>;
-
- private:
- using task_types = mp::decay_t<decltype((make_tasks_t { })(dependency_items_type { }))>;
- using tasks_tuple_type = mp::list::unwrap_t<hana::tuple, task_types>;
-
- private:
- context_type& _context; //!< context to use for system execution
- task_counter_blocker_t& _counter; //!< counter to track running tasks
- tasks_tuple_type _tasks; //!< tuple of all tasks
-
- public:
- /**
- * constructor
- *
- * @param p_context context to use for system execution
- * @param p_counter counter to track running tasks
- */
- inline task_group_t(context_type& p_context, task_counter_blocker_t& p_counter);
-
- /**
- * start the given task
- *
- * @tparam T_task_id id type of the task to execute
- * @tparam T_func overloaded function type to execute system with
- *
- * @param id id of task to execute
- * @param func overloaded function to execute system with
- */
- template<typename T_task_id, typename T_func>
- inline void start_task(T_task_id id, T_func&& func);
-
- private:
- /**
- * execute the task using the thread pool
- *
- * @tparam T_task_id id type of task to execute
- * @tparam T_func overloaded function type to execute system with
- *
- * @param func overloaded function to execute system with
- */
- template<typename T_task_id, typename T_func>
- inline void post_task_in_thread_pool(T_task_id, T_func&& func);
-
- /**
- * execute the actual task using the passed overloaded function
- *
- * @tparam T_task_id id type of task to execute
- * @tparam T_func overloaded function type to execute system with
- *
- * @param func overloaded function to execute system with
- */
- template<typename T_task_id, typename T_func>
- inline void execute_task(T_task_id, T_func&& func);
-
- /**
- * update the dependencies of the current task and start the next task
- *
- * @tparam T_task_id id type of task to update dependencies for
- * @tparam T_func overloaded function type to execute system with
- *
- * @param func overloaded function to execute system with
- */
- template<typename T_task_id, typename T_func>
- inline void check_and_start_dependencies(T_task_id, T_func&& func);
- };
-
- /**
- * create a list of dependency items
- *
- * @tparam T_system_signature_list system signature list type
- * @tparam T_system_tag_list list of system tag types
- *
- * @return list of dependency items
- */
- template<typename T_system_signature_list, typename T_system_tag_list>
- constexpr decltype(auto) build_dependency_list(T_system_signature_list, T_system_tag_list) noexcept;
-
- /**
- * get a list of independent items from the passed dependency list
- *
- * @tparam T_dependency_list dependency item list to get independent items from
- *
- * @return list of independent items
- */
- template<typename T_dependency_list>
- constexpr decltype(auto) get_independent_item_ids(T_dependency_list) noexcept;
- }
-
- /**
- * scheduler that resolves the dependencies between systems and then executes the systems in a save way in parallel
- *
- * @tparam T_settings settings type the environment is configured with
- */
- template<typename T_settings>
- struct atomic_counter
- {
- public:
- using settings_type = T_settings;
- using context_type = ::ecs::context::type<settings_type>;
- using instance_meta_data_type = detail::instance_meta_data_t;
-
- private:
- context_type& _context;
-
- public:
- /**
- * constructor
- *
- * @param p_context context to use for system exeution
- */
- inline atomic_counter(context_type& p_context);
-
- /**
- * execute the systems for that system tags are passed
- *
- * @tparam T_system_tag_list list of system tag type to execute systems for
- * @tparam T_func overloaded function type to use for system execution
- *
- * @param stl list of system tags to execute systems for
- * @param func overloaded function to use for system execution
- */
- template<typename T_system_tag_list, typename T_func>
- inline void execute(T_system_tag_list stl, T_func&& func);
- };
-
- } } } }
|