scheduler: review internals to use peek/release/whatever - see #1257
This commit is contained in:
@@ -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({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user