Skip to content

Commit

Permalink
refactor: update common inline interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
FlyAndNotDown committed Apr 14, 2024
1 parent 085320c commit 53b980a
Show file tree
Hide file tree
Showing 16 changed files with 821 additions and 535 deletions.
203 changes: 55 additions & 148 deletions Engine/Source/Common/Include/Common/Concurrent.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,98 +25,29 @@
namespace Common {
class NamedThread {
public:
NamedThread() = default;

template <typename F, typename... Args>
explicit NamedThread(const std::string& name, F&& task, Args&&... args)
{
thread = std::thread([this, task = std::forward<F>(task), name](Args&&... args) -> void {
SetThreadName(name);
task(args...);
}, std::forward<Args>(args)...);
}

NamedThread(NamedThread&& other) noexcept : thread(std::move(other.thread)) {}

~NamedThread() = default;
explicit NamedThread(const std::string& name, F&& task, Args&&... args);

NamedThread& operator=(NamedThread&& other) noexcept
{
thread = std::move(other.thread);
return *this;
}
NamedThread();
NamedThread(NamedThread&& other) noexcept;
~NamedThread();
NamedThread& operator=(NamedThread&& other) noexcept;

void Join()
{
thread.join();
}
void Join();

private:
void SetThreadName(const std::string& name)
{
#if PLATFORM_WINDOWS
SetThreadDescription(thread.native_handle(), Common::StringUtils::ToWideString(name).c_str());
#elif PLATFORM_MACOS
pthread_setname_np(name.c_str());
#else
pthread_setname_np(thread.native_handle(), name.c_str());
#endif
}
void SetThreadName(const std::string& name);

std::thread thread;
};

class ThreadPool {
public:
ThreadPool(const std::string& name, uint8_t threadNum) : stop(false)
{
threads.reserve(threadNum);
for (auto i = 0; i < threadNum; i++) {
std::string fullName = name + "-" + std::to_string(i);
threads.emplace_back(NamedThread(fullName, [this]() -> void {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mutex);
condition.wait(lock, [this]() -> bool { return stop || !tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
task = std::move(tasks.front());
tasks.pop();
}
task();
}
}));
}
}

~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(mutex);
stop = true;
}
condition.notify_all();
for (auto& thread : threads) {
thread.Join();
}
}
ThreadPool(const std::string& name, uint8_t threadNum);
~ThreadPool();

template <typename F, typename... Args>
auto EmplaceTask(F&& task, Args&&... args)
{
using RetType = std::invoke_result_t<F, Args...>;
auto packagedTask = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(task), std::forward<Args>(args)...));
auto result = packagedTask->get_future();
{
std::unique_lock<std::mutex> lock(mutex);
Assert(!stop);
tasks.emplace([packagedTask]() -> void { (*packagedTask)(); });
}
condition.notify_one();
return result;
}
auto EmplaceTask(F&& task, Args&&... args);

private:
bool stop;
Expand All @@ -128,78 +59,13 @@ namespace Common {

class WorkerThread {
public:
explicit WorkerThread(const std::string& name) : stop(false), flush(false)
{
thread = NamedThread(name, [this]() -> void {
while (true) {
bool needNotifyMainThread = false;
std::vector<std::function<void()>> tasksToExecute;
{
std::unique_lock<std::mutex> lock(mutex);
taskCondition.wait(lock, [this]() -> bool { return stop || flush || !tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
if (flush) {
tasksToExecute.reserve(tasks.size());
while (!tasks.empty()) {
tasksToExecute.emplace_back(std::move(tasks.front()));
tasks.pop();
}
flush = false;
needNotifyMainThread = true;
} else {
tasksToExecute.emplace_back(std::move(tasks.front()));
tasks.pop();
}
}
for (auto& task : tasksToExecute) {
task();
}
if (needNotifyMainThread) {
flushCondition.notify_one();
}
}
});
}
explicit WorkerThread(const std::string& name);
~WorkerThread();

~WorkerThread()
{
{
std::unique_lock<std::mutex> lock(mutex);
stop = true;
}
taskCondition.notify_all();
thread.Join();
}

void Flush()
{
{
std::unique_lock<std::mutex> lock(mutex);
flush = true;
}
taskCondition.notify_one();
{
std::unique_lock<std::mutex> lock(mutex);
flushCondition.wait(lock);
}
}
void Flush();

template <typename F, typename... Args>
auto EmplaceTask(F&& task, Args&&... args)
{
using RetType = std::invoke_result_t<F, Args...>;
auto packagedTask = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(task), std::forward<Args>(args)...));
auto result = packagedTask->get_future();
{
std::unique_lock<std::mutex> lock(mutex);
Assert(!stop);
tasks.emplace([packagedTask]() -> void { (*packagedTask)(); });
}
taskCondition.notify_one();
return result;
}
auto EmplaceTask(F&& task, Args&&... args);

private:
bool stop;
Expand All @@ -211,3 +77,44 @@ namespace Common {
std::queue<std::function<void()>> tasks;
};
}

namespace Common {
template <typename F, typename... Args>
NamedThread::NamedThread(const std::string& name, F&& task, Args&& ... args)
{
thread = std::thread([this, task = std::forward<F>(task), name](Args&&... args) -> void {
SetThreadName(name);
task(args...);
}, std::forward<Args>(args)...);
}

template <typename F, typename... Args>
auto ThreadPool::EmplaceTask(F&& task, Args&& ... args)
{
using RetType = std::invoke_result_t<F, Args...>;
auto packagedTask = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(task), std::forward<Args>(args)...));
auto result = packagedTask->get_future();
{
std::unique_lock<std::mutex> lock(mutex);
Assert(!stop);
tasks.emplace([packagedTask]() -> void { (*packagedTask)(); });
}
condition.notify_one();
return result;
}

template <typename F, typename... Args>
auto WorkerThread::EmplaceTask(F&& task, Args&& ... args)
{
using RetType = std::invoke_result_t<F, Args...>;
auto packagedTask = std::make_shared<std::packaged_task<RetType()>>(std::bind(std::forward<F>(task), std::forward<Args>(args)...));
auto result = packagedTask->get_future();
{
std::unique_lock<std::mutex> lock(mutex);
Assert(!stop);
tasks.emplace([packagedTask]() -> void { (*packagedTask)(); });
}
taskCondition.notify_one();
return result;
}
}
72 changes: 43 additions & 29 deletions Engine/Source/Common/Include/Common/Container.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,59 @@ namespace Common {
class VectorUtils {
public:
template <typename T>
static inline typename std::vector<T>::iterator SwapWithLastAndDelete(std::vector<T>& vector, const typename std::vector<T>::iterator& iterator)
{
std::iter_swap(iterator, vector.end() - 1);
vector.pop_back();
return iterator;
}
static inline typename std::vector<T>::iterator SwapWithLastAndDelete(std::vector<T>& vector, const typename std::vector<T>::iterator& iterator);

template <typename T>
static inline size_t SwapWithLastAndDelete(std::vector<T>& vector, size_t index)
{
std::swap(vector[index], vector[vector.size() - 1]);
vector.pop_back();
return index;
}
static inline size_t SwapWithLastAndDelete(std::vector<T>& vector, size_t index);

template <typename T>
static inline std::vector<T> GetIntersection(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
std::vector<T> result;
std::set_intersection(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::back_inserter(result));
return result;
}
static inline std::vector<T> GetIntersection(const std::vector<T>& lhs, const std::vector<T>& rhs);
};

class SetUtils {
public:
template <typename T>
static inline std::unordered_set<T> GetIntersection(const std::unordered_set<T>& lhs, const std::unordered_set<T>& rhs)
{
std::unordered_set<T> result;
result.reserve(lhs.size());
for (const auto& elementLhs : lhs) {
for (const auto& elementRhs : rhs) {
if (elementLhs == elementRhs) {
result.emplace(elementLhs);
}
static inline std::unordered_set<T> GetIntersection(const std::unordered_set<T>& lhs, const std::unordered_set<T>& rhs);
};
}

namespace Common {
template <typename T>
typename std::vector<T>::iterator VectorUtils::SwapWithLastAndDelete(std::vector<T>& vector, const typename std::vector<T>::iterator& iterator)
{
std::iter_swap(iterator, vector.end() - 1);
vector.pop_back();
return iterator;
}

template <typename T>
size_t VectorUtils::SwapWithLastAndDelete(std::vector<T>& vector, size_t index)
{
std::swap(vector[index], vector[vector.size() - 1]);
vector.pop_back();
return index;
}

template <typename T>
std::vector<T> VectorUtils::GetIntersection(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
std::vector<T> result;
std::set_intersection(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), std::back_inserter(result));
return result;
}

template <typename T>
std::unordered_set<T> SetUtils::GetIntersection(const std::unordered_set<T>& lhs, const std::unordered_set<T>& rhs)
{
std::unordered_set<T> result;
result.reserve(lhs.size());
for (const auto& elementLhs : lhs) {
for (const auto& elementRhs : rhs) {
if (elementLhs == elementRhs) {
result.emplace(elementLhs);
}
}
return result;
}
};
return result;
}
}
18 changes: 3 additions & 15 deletions Engine/Source/Common/Include/Common/Debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,11 @@
namespace Common {
class Debug {
public:
static void AssertImpl(bool expression, const std::string& name, const std::string& file, uint32_t line, const std::string& reason = "")
{
if (expression) {
return;
}
std::cerr << "Assert failed: " << name << ", " << file << ", " << line << std::endl;
std::cerr << "Reason: " << reason << std::endl;
static void AssertImpl(bool expression, const std::string& name, const std::string& file, uint32_t line, const std::string& reason = "");

#if BUILD_CONFIG_DEBUG
debug_break();
#endif
}

~Debug() = default;
~Debug();

private:

Debug() = default;
Debug();
};
}
15 changes: 1 addition & 14 deletions Engine/Source/Common/Include/Common/File.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@
namespace Common {
class FileUtils {
public:
static std::string ReadTextFile(const std::string& fileName)
{
std::string result;
{
std::ifstream file(fileName, std::ios::ate | std::ios::binary);
Assert(file.is_open());
size_t size = file.tellg();
result.resize(size);
file.seekg(0);
file.read(result.data(), static_cast<std::streamsize>(size));
file.close();
}
return result;
}
static std::string ReadTextFile(const std::string& fileName);
};
}
Loading

0 comments on commit 53b980a

Please sign in to comment.