|
|
@@ -13,19 +13,6 @@
|
|
|
|
|
|
namespace entt {
|
|
|
|
|
|
-/*! @cond TURN_OFF_DOXYGEN */
|
|
|
-namespace internal {
|
|
|
-
|
|
|
-template<typename Type>
|
|
|
-struct process_handler {
|
|
|
- // std::shared_ptr because of its type erased allocator which is useful here
|
|
|
- std::shared_ptr<process_handler> next{};
|
|
|
- std::shared_ptr<Type> task{};
|
|
|
-};
|
|
|
-
|
|
|
-} // namespace internal
|
|
|
-/*! @endcond */
|
|
|
-
|
|
|
/**
|
|
|
* @brief Cooperative scheduler for processes.
|
|
|
*
|
|
|
@@ -55,23 +42,9 @@ struct process_handler {
|
|
|
*/
|
|
|
template<typename Delta, typename Allocator>
|
|
|
class basic_scheduler {
|
|
|
- using process_type = basic_process<Delta>;
|
|
|
using alloc_traits = std::allocator_traits<Allocator>;
|
|
|
- using handler_type = internal::process_handler<process_type>;
|
|
|
- using container_allocator = typename alloc_traits::template rebind_alloc<handler_type>;
|
|
|
- using container_type = std::vector<handler_type, container_allocator>;
|
|
|
-
|
|
|
- bool update(const std::size_t pos, const Delta delta, void *data) {
|
|
|
- handlers.first()[pos].task->tick(delta, data);
|
|
|
- // callbacks can insert or erase tasks, invalidating the reference
|
|
|
- auto &elem = handlers.first()[pos];
|
|
|
-
|
|
|
- if(elem.task->rejected()) {
|
|
|
- elem.next.reset();
|
|
|
- }
|
|
|
-
|
|
|
- return (elem.task->rejected() || elem.task->finished());
|
|
|
- }
|
|
|
+ using container_allocator = typename alloc_traits::template rebind_alloc<std::shared_ptr<basic_process<Delta>>>;
|
|
|
+ using container_type = std::vector<std::shared_ptr<basic_process<Delta>>, container_allocator>;
|
|
|
|
|
|
public:
|
|
|
/*! @brief Allocator type. */
|
|
|
@@ -202,7 +175,7 @@ public:
|
|
|
*/
|
|
|
template<typename Proc, typename... Args>
|
|
|
basic_scheduler &attach(Args &&...args) {
|
|
|
- handlers.first().emplace_back().task = std::allocate_shared<Proc>(handlers.second(), std::forward<Args>(args)...);
|
|
|
+ handlers.first().emplace_back(std::allocate_shared<Proc>(handlers.second(), std::forward<Args>(args)...));
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
@@ -273,10 +246,13 @@ public:
|
|
|
template<typename Proc, typename... Args>
|
|
|
basic_scheduler &then(Args &&...args) {
|
|
|
ENTT_ASSERT(!handlers.first().empty(), "Process not available");
|
|
|
- auto *curr = &handlers.first().back();
|
|
|
- for(; curr->next; curr = curr->next.get()) {}
|
|
|
- curr->next = std::allocate_shared<handler_type>(handlers.second());
|
|
|
- curr->next->task = std::allocate_shared<Proc>(handlers.second(), std::forward<Args>(args)...);
|
|
|
+ auto curr = handlers.first().back();
|
|
|
+
|
|
|
+ for(auto child = curr->peek(); child; child = curr->peek()) {
|
|
|
+ curr = child;
|
|
|
+ }
|
|
|
+
|
|
|
+ curr->then(std::allocate_shared<Proc>(handlers.second(), std::forward<Args>(args)...));
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
@@ -305,15 +281,18 @@ public:
|
|
|
*/
|
|
|
void update(const delta_type delta, void *data = nullptr) {
|
|
|
for(auto next = handlers.first().size(); next; --next) {
|
|
|
- if(const auto pos = next - 1u; update(pos, delta, data)) {
|
|
|
- // updating might spawn/reallocate, cannot hold refs until here
|
|
|
- if(auto &curr = handlers.first()[pos]; curr.next) {
|
|
|
- auto elem = curr.next;
|
|
|
- curr = std::move(*elem);
|
|
|
- } else {
|
|
|
- curr = std::move(handlers.first().back());
|
|
|
- handlers.first().pop_back();
|
|
|
- }
|
|
|
+ const auto pos = next - 1u;
|
|
|
+ handlers.first()[pos]->tick(delta, data);
|
|
|
+ // updating might spawn/reallocate, cannot hold refs until here
|
|
|
+ auto &elem = handlers.first()[pos];
|
|
|
+
|
|
|
+ if(elem->finished()) {
|
|
|
+ elem = std::move(elem->release());
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!elem || elem->rejected()) {
|
|
|
+ elem = std::move(handlers.first().back());
|
|
|
+ handlers.first().pop_back();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -330,10 +309,10 @@ public:
|
|
|
*/
|
|
|
void abort(const bool immediate = false) {
|
|
|
for(auto &&curr: handlers.first()) {
|
|
|
- curr.task->abort();
|
|
|
+ curr->abort();
|
|
|
|
|
|
if(immediate) {
|
|
|
- curr.task->tick({});
|
|
|
+ curr->tick({});
|
|
|
}
|
|
|
}
|
|
|
}
|