还是一堆bug的状态
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory_resource>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "Memory.h"
|
||||
#include "Object_Semantics.h"
|
||||
namespace renderive {
|
||||
class Task : Move_Only {
|
||||
public:
|
||||
static constexpr std::size_t Inline_Size = 64;
|
||||
static constexpr std::size_t Inline_Align = alignof(std::max_align_t);
|
||||
Task() noexcept = default;
|
||||
Task(std::nullptr_t) noexcept {}
|
||||
template <typename Callable>
|
||||
requires (!std::is_same_v<std::decay_t<Callable>, Task>)
|
||||
Task(Callable&& callable) {
|
||||
using Model = Task_Model<std::decay_t<Callable>>;
|
||||
if constexpr (sizeof(Model) <= Inline_Size && alignof(Model) <= Inline_Align && std::is_nothrow_move_constructible_v<Model>) {
|
||||
object = inline_storage();
|
||||
std::construct_at(static_cast<Model*>(object), std::forward<Callable>(callable));
|
||||
inline_object = true;
|
||||
}
|
||||
else {
|
||||
resource = memory_resource(Memory_Domain::Scheduler_Task);
|
||||
std::pmr::polymorphic_allocator<Model> allocator(resource);
|
||||
object = allocator.allocate(1);
|
||||
try {
|
||||
std::construct_at(static_cast<Model*>(object), std::forward<Callable>(callable));
|
||||
}
|
||||
catch (...) {
|
||||
allocator.deallocate(static_cast<Model*>(object), 1);
|
||||
object = nullptr;
|
||||
resource = nullptr;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
invoke_function = &invoke<Model>;
|
||||
destroy_function = &destroy<Model>;
|
||||
move_function = &move<Model>;
|
||||
}
|
||||
Task(Task&& other) noexcept {
|
||||
move_from(std::move(other));
|
||||
}
|
||||
Task& operator=(Task&& other) noexcept {
|
||||
if (this == &other)
|
||||
return *this;
|
||||
reset();
|
||||
move_from(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
~Task() {
|
||||
reset();
|
||||
}
|
||||
void operator()() {
|
||||
if (invoke_function)
|
||||
invoke_function(object);
|
||||
}
|
||||
explicit operator bool() const noexcept {
|
||||
return object != nullptr;
|
||||
}
|
||||
private:
|
||||
template <typename Callable>
|
||||
struct Task_Model {
|
||||
template <typename Source>
|
||||
explicit Task_Model(Source&& callable) : callable(std::forward<Source>(callable)) {}
|
||||
Callable callable;
|
||||
};
|
||||
template <typename Model>
|
||||
static void invoke(void* object) {
|
||||
static_cast<Model*>(object)->callable();
|
||||
}
|
||||
template <typename Model>
|
||||
static void destroy(void* object, std::pmr::memory_resource* resource) {
|
||||
std::destroy_at(static_cast<Model*>(object));
|
||||
if (resource) {
|
||||
std::pmr::polymorphic_allocator<Model> allocator(resource);
|
||||
allocator.deallocate(static_cast<Model*>(object), 1);
|
||||
}
|
||||
}
|
||||
template <typename Model>
|
||||
static void move(void* destination, void* source) {
|
||||
std::construct_at(static_cast<Model*>(destination), std::move(*static_cast<Model*>(source)));
|
||||
std::destroy_at(static_cast<Model*>(source));
|
||||
}
|
||||
void* inline_storage() noexcept {
|
||||
return static_cast<void*>(storage);
|
||||
}
|
||||
void move_from(Task&& other) noexcept {
|
||||
invoke_function = std::exchange(other.invoke_function, nullptr);
|
||||
destroy_function = std::exchange(other.destroy_function, nullptr);
|
||||
move_function = std::exchange(other.move_function, nullptr);
|
||||
inline_object = std::exchange(other.inline_object, false);
|
||||
if (!other.object) {
|
||||
object = nullptr;
|
||||
resource = nullptr;
|
||||
return;
|
||||
}
|
||||
if (inline_object) {
|
||||
object = inline_storage();
|
||||
resource = nullptr;
|
||||
move_function(object, other.object);
|
||||
other.object = nullptr;
|
||||
return;
|
||||
}
|
||||
object = std::exchange(other.object, nullptr);
|
||||
resource = std::exchange(other.resource, nullptr);
|
||||
}
|
||||
void reset() noexcept {
|
||||
if (!object)
|
||||
return;
|
||||
destroy_function(object, resource);
|
||||
object = nullptr;
|
||||
resource = nullptr;
|
||||
invoke_function = nullptr;
|
||||
destroy_function = nullptr;
|
||||
move_function = nullptr;
|
||||
inline_object = false;
|
||||
}
|
||||
alignas(std::max_align_t) std::byte storage[Inline_Size]{};
|
||||
void* object{};
|
||||
std::pmr::memory_resource* resource{};
|
||||
void (*invoke_function)(void*){};
|
||||
void (*destroy_function)(void*, std::pmr::memory_resource*){};
|
||||
void (*move_function)(void*, void*){};
|
||||
bool inline_object{};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user