更改字符集
This commit is contained in:
Binary file not shown.
+5
-1
@@ -10,7 +10,10 @@ set(CMAKE_WIN32_EXECUTABLE true)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_compile_options(${PROJECT_NAME} -Wno-microsoft-string-literal-from-predefined)
|
||||
endif ()
|
||||
#add_compile_options(${PROJECT_NAME} /utf-8)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
add_compile_options(/source-charset:utf-8)
|
||||
add_compile_options(/execution-charset:utf-8)
|
||||
endif ()
|
||||
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
@@ -44,3 +47,4 @@ add_executable(${PROJECT_NAME}
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-3-4.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
class Task;
|
||||
class TaskScheduler;
|
||||
|
||||
class Task final : public AnywhereEditable<Task> {
|
||||
friend class TaskScheduler;
|
||||
|
||||
public:
|
||||
Function<void(Task& self)> func;
|
||||
|
||||
explicit Task(const Function<void(Task& self)>& func) : func(func) {}
|
||||
explicit Task(Function<void(Task& self)>&& func) : func(std::move(func)) {}
|
||||
void schedulePop(const bool pop) noexcept { reserved[0] = pop; }
|
||||
bool scheduledPop() const noexcept { return reserved[0]; }
|
||||
|
||||
int pop() noexcept override {
|
||||
schedulePop(true);
|
||||
Success();
|
||||
}
|
||||
};
|
||||
|
||||
class TaskScheduler {
|
||||
public:
|
||||
AnywhereEditableList<Task> tasks;
|
||||
|
||||
void runAll() {
|
||||
for (Task& task : tasks) {
|
||||
task.func(task);
|
||||
if (task.scheduledPop()) tasks.pop(&task);
|
||||
}
|
||||
}
|
||||
|
||||
void pushCopy(Task& task) { tasks.pushCopy(&task); }
|
||||
/* 必须是new Task,交付托管 */
|
||||
void pushNewed(Task* task) { tasks.pushNewed(task); }
|
||||
void pushThis(Task& task) { tasks.pushThis(&task); }
|
||||
};
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,142 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-3-6.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "def.h"
|
||||
|
||||
struct IGarbage;
|
||||
template <typename T>
|
||||
class Garbage;
|
||||
class GarbageCollector;
|
||||
|
||||
struct IGarbage {
|
||||
private:
|
||||
friend class GarbageCollector;
|
||||
IGarbage* next = nullptr;
|
||||
|
||||
protected:
|
||||
void* ptr;
|
||||
explicit IGarbage(void* ptr) : ptr(ptr) {}
|
||||
virtual ~IGarbage() = default;
|
||||
virtual void collect() = 0;
|
||||
virtual void deleteThis() = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Garbage final : public IGarbage {
|
||||
friend class GarbageCollector;
|
||||
|
||||
public:
|
||||
explicit Garbage(T* ptr) : IGarbage(ptr) {}
|
||||
void collect() override { delete static_cast<T*>(ptr); }
|
||||
|
||||
protected:
|
||||
void deleteThis() override { delete this; }
|
||||
};
|
||||
|
||||
class GarbageCollector {
|
||||
IGarbage* submitted = nullptr;
|
||||
IGarbage* submittedEnd = nullptr;
|
||||
IGarbage* packed = nullptr;
|
||||
IGarbage* packedEnd = nullptr;
|
||||
IGarbage* processing = nullptr;
|
||||
|
||||
public:
|
||||
GarbageCollector() = default;
|
||||
GarbageCollector(const GarbageCollector&) = delete;
|
||||
GarbageCollector(GarbageCollector&&) = delete;
|
||||
GarbageCollector& operator=(const GarbageCollector&) = delete;
|
||||
GarbageCollector& operator=(GarbageCollector&&) = delete;
|
||||
|
||||
~GarbageCollector() {
|
||||
IGarbage* iter = processing;
|
||||
while (processing) {
|
||||
iter = processing->next;
|
||||
processing->collect();
|
||||
processing->deleteThis();
|
||||
processing = iter;
|
||||
}
|
||||
while (packed) {
|
||||
iter = packed->next;
|
||||
packed->collect();
|
||||
packed->deleteThis();
|
||||
packed = iter;
|
||||
}
|
||||
while (submitted) {
|
||||
iter = submitted->next;
|
||||
submitted->collect();
|
||||
submitted->deleteThis();
|
||||
submitted = iter;
|
||||
}
|
||||
submittedEnd = nullptr;
|
||||
}
|
||||
|
||||
/** 只能在gameThread调用 */
|
||||
template <TypeName T>
|
||||
void submit(T* ptr) noexcept(false) {
|
||||
IGarbage* garbage = new Garbage<T>(ptr);
|
||||
if (IGarbage* end = submittedEnd) { // 后续添加,可能存在线程竞争
|
||||
while (end->next) end = end->next; // 理论上不会进入循环,但防止万一
|
||||
end->next = garbage;
|
||||
if (submitted) submittedEnd = garbage; // 参考pack(),submitted会被先置空
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
if (!submitted) submittedEnd = nullptr; // 防止submittedEnd = garbage在pack()中置空后进行。此函数是同步的,所以可以这样操作。
|
||||
}
|
||||
else { // 添加首个,一定不会有线程竞争;或先前的已经pack
|
||||
submitted = garbage;
|
||||
submittedEnd = garbage;
|
||||
}
|
||||
}
|
||||
|
||||
/** 只能在renderThread调用 */
|
||||
void pack() {
|
||||
if (!submitted) return; // 提交链为空,不进行后续操作,防止竞争
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
IGarbage* submit = submitted;
|
||||
IGarbage* submitEnd = submittedEnd;
|
||||
submitted = nullptr; // 先把这个置为nullptr
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
submittedEnd = nullptr;
|
||||
if (IGarbage* end = packedEnd) {
|
||||
while (end->next) end = end->next; // 以防万一
|
||||
end->next = submit;
|
||||
if (packed) packedEnd = submitEnd;
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
if (!packed) packedEnd = nullptr;
|
||||
}
|
||||
else {
|
||||
packed = submit;
|
||||
packedEnd = submitEnd;
|
||||
}
|
||||
while (packedEnd->next) packedEnd = packedEnd->next;
|
||||
}
|
||||
|
||||
/** 只能在gameThread调用 */
|
||||
void collect() {
|
||||
IGarbage* next = processing;
|
||||
while (processing) {
|
||||
next = processing->next;
|
||||
processing->next = nullptr;
|
||||
processing->collect();
|
||||
processing->deleteThis();
|
||||
processing = next;
|
||||
}
|
||||
if (!packed) return;
|
||||
// 搬运packed且搬运期间的packed链必须必须完全固定
|
||||
// 保证运行顺序
|
||||
processing = packed;
|
||||
packed = nullptr;
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
packedEnd = nullptr;
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
while (processing) {
|
||||
next = processing->next;
|
||||
processing->next = nullptr;
|
||||
processing->collect();
|
||||
processing->deleteThis();
|
||||
processing = next;
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,210 @@
|
||||
//
|
||||
// Created by EmsiaetKadosh on 25-3-4.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
template <typename T, typename L = void>
|
||||
class AnywhereEditable;
|
||||
template <typename T, typename L = void>
|
||||
class AnywhereEditableList;
|
||||
template <typename T, typename L = void>
|
||||
class AnywhereIterator;
|
||||
class AnywhereIteratorEnd;
|
||||
|
||||
/**
|
||||
* 此处无法进行代码编译层面的直接约束
|
||||
* @tparam T 满足T extends AnywhereEditable<T, L>
|
||||
* @tparam L 满足L extends AnywhereEditableList<T, L>
|
||||
*/
|
||||
template <typename T, typename L>
|
||||
class AnywhereEditable {
|
||||
public:
|
||||
using Lst = std::conditional_t<std::is_same_v<L, void>, AnywhereEditableList<T, L>, L>;
|
||||
|
||||
private:
|
||||
friend class AnywhereIterator<T, L>;
|
||||
friend class AnywhereEditableList<T, L>;
|
||||
friend class AnywhereIteratorEnd;
|
||||
friend L;
|
||||
AnywhereEditable* prev = nullptr;
|
||||
AnywhereEditable* next = nullptr;
|
||||
AnywhereEditableList<T, L>* list = nullptr; // 指示自身属于某个列表
|
||||
protected:
|
||||
bool managedByList = false; // 指示是否在列表内管理内存,而非列表外管理内存
|
||||
byte reserved[7]{}; // reserved[0]: Task::schedulePop
|
||||
|
||||
public:
|
||||
AnywhereEditable() = default;
|
||||
AnywhereEditable(const AnywhereEditable& other) {}
|
||||
|
||||
AnywhereEditable(AnywhereEditable&& other) noexcept : prev(other->prev), next(other->next), list(other->list) {
|
||||
other->prev = nullptr;
|
||||
other->next = nullptr;
|
||||
other->list = nullptr;
|
||||
}
|
||||
|
||||
virtual ~AnywhereEditable() {
|
||||
if (list) {
|
||||
managedByList = false;
|
||||
auto lst = list;
|
||||
list = nullptr;
|
||||
lst->pop(static_cast<T*>(this));
|
||||
Logger.warn(L"~AnywhereEditable() : 析构时没有清除list,导致了析构时pop");
|
||||
}
|
||||
}
|
||||
|
||||
int pushCopy(AnywhereEditableList<T, L>& list) noexcept;
|
||||
int pushThis(AnywhereEditableList<T, L>& list) noexcept;
|
||||
virtual int pop() noexcept;
|
||||
AnywhereEditableList<T, L>* getContainer() const noexcept { return list; }
|
||||
};
|
||||
|
||||
template <typename T, typename L>
|
||||
class AnywhereIterator {
|
||||
friend class AnywhereIteratorEnd;
|
||||
AnywhereEditable<T, L>* current;
|
||||
|
||||
public:
|
||||
explicit AnywhereIterator(AnywhereEditable<T, L>* current) : current(current) {}
|
||||
AnywhereIterator(const AnywhereIterator& other) = default;
|
||||
|
||||
T& operator*() noexcept(false) {
|
||||
if (current->next) return static_cast<T&>(*current);
|
||||
throw RuntimeException(L"AnywhereIterator::operator*() : next is null, end of list");
|
||||
}
|
||||
|
||||
T* operator->() noexcept(false) {
|
||||
if (current->next) return &static_cast<T&>(*current);
|
||||
throw RuntimeException(L"AnywhereIterator::operator*() : next is null, end of list");
|
||||
}
|
||||
|
||||
bool operator!=(const AnywhereIterator& other) const noexcept { return current != other.current; }
|
||||
bool operator==(const AnywhereIterator& other) const noexcept { return current == other.current; }
|
||||
bool operator!=(const AnywhereIteratorEnd& other) const noexcept;
|
||||
bool operator==(const AnywhereIteratorEnd& other) const noexcept;
|
||||
|
||||
AnywhereIterator& operator++() noexcept(false) {
|
||||
if (current->next) current = current->next;
|
||||
else throw InvalidOperationException(L"AnywhereIterator::operator++() : end of list");
|
||||
return *this;
|
||||
}
|
||||
|
||||
AnywhereIterator operator++(int) noexcept(false) {
|
||||
if (current->next) {
|
||||
AnywhereIterator ret = *this;
|
||||
current = current->next;
|
||||
return ret;
|
||||
}
|
||||
throw InvalidOperationException(L"AnywhereIterator::operator++() : end of list");
|
||||
}
|
||||
|
||||
AnywhereIterator& operator--() noexcept(false) {
|
||||
if (current->prev) current = current->prev;
|
||||
else throw InvalidOperationException(L"AnywhereIterator::operator--() : begin of list");
|
||||
return *this;
|
||||
}
|
||||
|
||||
AnywhereIterator operator--(int) noexcept(false) {
|
||||
if (current->prev) {
|
||||
AnywhereIterator ret = *this;
|
||||
current = current->prev;
|
||||
return ret;
|
||||
}
|
||||
throw InvalidOperationException(L"AnywhereIterator::operator--() : begin of list");
|
||||
}
|
||||
};
|
||||
|
||||
class AnywhereIteratorEnd {
|
||||
public:
|
||||
AnywhereIteratorEnd() {}
|
||||
AnywhereIteratorEnd(const AnywhereIteratorEnd& other) = delete;
|
||||
AnywhereIteratorEnd(AnywhereIteratorEnd&& other) = delete;
|
||||
|
||||
template <typename T, typename L>
|
||||
bool operator!=(const AnywhereIterator<T, L>& other) const noexcept { return other.current && other.current->next; }
|
||||
|
||||
template <typename T, typename L>
|
||||
bool operator==(const AnywhereIterator<T, L>& other) const noexcept { return !operator!=(other); }
|
||||
};
|
||||
|
||||
template <typename T, typename L>
|
||||
class AnywhereEditableList {
|
||||
protected:
|
||||
AnywhereEditable<T, L> head;
|
||||
AnywhereEditable<T, L> tail;
|
||||
|
||||
public:
|
||||
AnywhereEditableList() {
|
||||
head.next = &tail;
|
||||
tail.prev = &head;
|
||||
}
|
||||
|
||||
virtual ~AnywhereEditableList() { for (AnywhereIterator<T, L> it = begin(); it != end(); ++it) {} }
|
||||
|
||||
int pushCopy(T* value) noexcept;
|
||||
int pushThis(T* value) noexcept;
|
||||
int pushNewed(T* value) noexcept;
|
||||
virtual int pop(T* value) noexcept;
|
||||
AnywhereIterator<T, L> begin() noexcept { return AnywhereIterator<T, L>(head.next); }
|
||||
AnywhereIteratorEnd end() noexcept { return AnywhereIteratorEnd(); }
|
||||
AnywhereIterator<T, L> begin() const noexcept { return AnywhereIterator<T, L>(head.next); }
|
||||
AnywhereIteratorEnd end() const noexcept { return AnywhereIteratorEnd(); }
|
||||
AnywhereEditable<T, L>* front() const noexcept { return head.next == &tail ? nullptr : head.next; }
|
||||
AnywhereEditable<T, L>* back() const noexcept { return tail.prev == &head ? nullptr : tail.prev; }
|
||||
};
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditable<T, L>::pushCopy(AnywhereEditableList<T, L>& list) noexcept { return list.pushCopy(static_cast<T*>(this)); }
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditable<T, L>::pushThis(AnywhereEditableList<T, L>& list) noexcept { return list.pushThis(static_cast<T*>(this)); }
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditable<T, L>::pop() noexcept { return list->pop(static_cast<T*>(this)); }
|
||||
|
||||
template <typename T, typename L>
|
||||
bool AnywhereIterator<T, L>::operator!=(const AnywhereIteratorEnd& other) const noexcept { return other != *this; }
|
||||
|
||||
template <typename T, typename L>
|
||||
bool AnywhereIterator<T, L>::operator==(const AnywhereIteratorEnd& other) const noexcept { return other == *this; }
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditableList<T, L>::pushCopy(T* value) noexcept {
|
||||
T* nv = new T(*value);
|
||||
return pushNewed(nv);
|
||||
}
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditableList<T, L>::pushThis(T* value) noexcept {
|
||||
if (value->list) {
|
||||
Logger.error(L"AnywhereEditableList::pushThis() : value is already in a list");
|
||||
Failed();
|
||||
}
|
||||
value->list = this;
|
||||
tail.prev->next = value;
|
||||
value->prev = tail.prev;
|
||||
value->next = &tail;
|
||||
tail.prev = value;
|
||||
Success();
|
||||
}
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditableList<T, L>::pushNewed(T* value) noexcept {
|
||||
const int ret = pushThis(value);
|
||||
if (ret) delete value;
|
||||
else value->managedByList = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T, typename L>
|
||||
int AnywhereEditableList<T, L>::pop(T* value) noexcept {
|
||||
if (value->list != this) {
|
||||
Logger.error(L"AnywhereEditableList::pop() : value is not in this list");
|
||||
Failed();
|
||||
}
|
||||
value->list = nullptr;
|
||||
value->next->prev = value->prev;
|
||||
value->prev->next = value->next;
|
||||
if (value->managedByList) delete value;
|
||||
Success();
|
||||
}
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user