임시저장(빌드 안됨) 졸려서 자러갈거야

This commit is contained in:
2025-04-29 21:49:58 +09:00
parent 1c6404530d
commit 1703974310
8 changed files with 167 additions and 17 deletions

View File

@@ -12,5 +12,4 @@ int main() {
sock.connect(serveraddr); sock.connect(serveraddr);
spdlog::info("Connection established from {}, {}", sock, (std::string)serveraddr); spdlog::info("Connection established from {}, {}", sock, (std::string)serveraddr);
sock.send("Hello, World!", 14, 0); sock.send("Hello, World!", 14, 0);
sleep(100);
} }

View File

@@ -3,6 +3,7 @@
#include "Socket/WSAManager.hpp" #include "Socket/WSAManager.hpp"
#include "Utils/ConfigManager.hpp" #include "Utils/ConfigManager.hpp"
#include "Utils/Thread.hpp" #include "Utils/Thread.hpp"
#include "Utils/ThreadPool.hpp"
#include "Utils/StringTokenizer.hpp" #include "Utils/StringTokenizer.hpp"
#include "Session/Session.hpp" #include "Session/Session.hpp"
@@ -39,12 +40,17 @@ int main() {
#endif #endif
spdlog::info("PID : {}", pid); spdlog::info("PID : {}", pid);
Chattr::ThreadPool threadPool(3);
while (true) { while (true) {
spdlog::info("Waiting for connection..."); spdlog::info("Waiting for connection...");
sock.accept(clientSock, clientAddr); sock.accept(clientSock, clientAddr);
Chattr::Thread thread_(_TCPClient, std::move(clientSock), clientAddr); threadPool.enqueueJob(_TCPClient, std::move(clientSock), clientAddr);
thread_.detach();
//Chattr::Thread thread_(_TCPClient, std::move(clientSock), clientAddr);
//thread_.detach();
} }
} }

26
impl/Session/Session.cpp Normal file
View File

@@ -0,0 +1,26 @@
#include "Session/Session.hpp"
namespace Chattr {
Session::Session() {
}
Session::~Session() {
}
bool Session::init() {
return false;
}
void Session::destruct() {
}
int Session::send() {
return -1;
}
int Session::recv() {
return -1;
}
}

View File

@@ -1,17 +1,30 @@
#include "Utils/Thread.hpp" #include "Utils/Thread.hpp"
namespace Chattr { namespace Chattr {
Thread::~Thread() {
if (!detached) Thread::Thread(Thread&& other) noexcept {
join(); other.detach();
} }
void Thread::join() { Thread& Thread::operator=(Thread&& other) noexcept {
other.detach();
return *this;
}
Thread::~Thread() {
if (!detached) {
spdlog::critical("There is not joined thread");
std::exit(EXIT_FAILURE);
}
}
void* Thread::join() {
#ifdef _WIN32 #ifdef _WIN32
WaitForSingleObject(handle_, INFINITE); WaitForSingleObject(handle_, INFINITE);
#elif __linux__ #elif __linux__
pthread_join(handle_, NULL); pthread_join(handle_, returnValue);
#endif #endif
return returnValue;
} }
void Thread::detach() { void Thread::detach() {

47
impl/Utils/ThreadPool.cpp Normal file
View File

@@ -0,0 +1,47 @@
#include "Utils/ThreadPool.hpp"
#include "precomp.hpp"
namespace Chattr {
ThreadPool::ThreadPool(std::uint32_t numThreads) {
workers_.reserve(numThreads);
while (numThreads--)
workers_.push_back([this]() -> void* { return this->Worker(); });
}
ThreadPool::~ThreadPool() {
terminate_ = true;
jobQueueCV_.notify_all();
for (auto& t : workers_)
t.join();
}
void* ThreadPool::Worker() {
#ifdef _WIN32
DWORD pid = GetCurrentProcessId();
#elif __linux__
pid_t pid = getpid();
#endif
spdlog::info("ThreadPool Worker : {}", pid);
while (!terminate_) {
std::unique_lock<std::mutex> lock(jobQueueMutex);
spdlog::info("ThreadPool Worker : {} Waiting for a job", pid);
jobQueueCV_.wait(lock, [this]() { return !this->jobs_.empty() || terminate_; });
if (this->jobs_.empty())
return nullptr;
auto jobPair = std::move(jobs_.front());
jobs_.pop();
lock.unlock();
spdlog::info("ThreadPool Worker : {} Executing a job", pid);
auto job = jobPair.first();
jobPair.second() = (*job)();
}
return nullptr;
}
}

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Socket/TCPSocket.hpp" #include "Socket/TCPSocket.hpp"
#include "Utils/Snowflake.hpp"
#include <vector> #include <vector>
namespace Chattr { namespace Chattr {
@@ -17,5 +18,6 @@ public:
private: private:
struct std::vector<Chattr::TCPSocket> tcpSock_; struct std::vector<Chattr::TCPSocket> tcpSock_;
struct std::vector<Chattr::Socket> udpSock_; struct std::vector<Chattr::Socket> udpSock_;
struct Snowflake sessId_;
}; };
} }

View File

@@ -12,39 +12,53 @@
namespace Chattr { namespace Chattr {
template<typename F, typename... Args>
concept ReturnsVoidPtr = std::is_same_v<
std::invoke_result_t<F, Args...>,
void*
>;
class Thread { class Thread {
public: public:
#ifdef _WIN32 #ifdef _WIN32
static unsigned __stdcall thread_func(LPVOID param) { static unsigned __stdcall thread_func(LPVOID param) {
auto task(static_cast<std::packaged_task<void()>*>(param)); // auto task = static_cast<std::function<void *()>*>(param);
std::unique_ptr<std::function<void*()>> task(static_cast<std::function<void* ()>*>(param));
(*task)(); (*task)();
delete task;
return 0; return 0;
} }
#elif __linux__ #elif __linux__
static void* thread_func(void *param) { static void* thread_func(void *param) {
auto task(static_cast<std::packaged_task<void()>*>(param)); auto task(static_cast<std::packaged_task<void*()>*>(param));
(*task)(); (*task)();
delete task; delete task;
return 0; return 0;
} }
#endif #endif
Thread(Thread&&) noexcept;
Thread& operator=(Thread&&) noexcept;
Thread(const Thread&) = delete;
Thread& operator=(Thread&) = delete;
template<typename _Callable, typename... _Args> template<typename _Callable, typename... _Args>
requires (!std::is_same_v<std::decay_t<_Callable>, Thread>) //복사 생성하면 안 되므로 requires ReturnsVoidPtr<_Callable, _Args...> && (!std::is_same_v<std::decay_t<_Callable>, Thread>)
Thread(_Callable&& __f, _Args&&... __args) { Thread(_Callable&& __f, _Args&&... __args) {
auto boundFunc = [__f = std::move(__f), ... __args = std::move(__args)]() mutable { auto boundFunc = [this, __f = std::move(__f), ... __args = std::move(__args)]() mutable -> void* {
__f(std::move(__args)...); void* ret = __f(std::move(__args)...);
returnValue = ret;
return ret;
}; };
auto funcPtr = new std::packaged_task<void()>(std::move(boundFunc)); std::function<void* ()> funcPtr = std::move(boundFunc);
#ifdef _WIN32 #ifdef _WIN32
handle_ = (HANDLE)_beginthreadex(nullptr, 0, thread_func, funcPtr, 0, nullptr); handle_ = (HANDLE)_beginthreadex(nullptr, 0, thread_func, new std::function<void *()>(std::move(funcPtr)), 0, nullptr);
#elif __linux__ #elif __linux__
pthread_create(&handle_, NULL, thread_func, funcPtr); pthread_create(&handle_, NULL, thread_func, funcPtr);
#endif #endif
} }
~Thread(); ~Thread();
void join(); void* join();
void detach(); void detach();
private: private:
@@ -53,6 +67,7 @@ private:
#elif __linux__ #elif __linux__
pthread_t handle_; pthread_t handle_;
#endif #endif
void* returnValue = nullptr;
bool detached = false; bool detached = false;
}; };

View File

@@ -0,0 +1,42 @@
#pragma once
#include "Thread.hpp"
#include <vector>
#include <queue>
#include <functional>
#include <condition_variable>
#include <mutex>
#include <memory>
namespace Chattr {
class ThreadPool {
public:
ThreadPool(std::uint32_t numThreads);
~ThreadPool();
template<typename _Callable, typename... _Args>
requires ReturnsVoidPtr<_Callable, _Args...> && (!std::is_same_v<std::decay_t<_Callable>, Thread>)
int enqueueJob(_Callable&& __job, void* retVal, _Args&&... __args) {
if (terminate_) {
spdlog::error("Cannot run jobs on threads that terminating...");
return -1;
}
std::lock_guard<std::mutex> lock(jobQueueMutex);
auto boundFunc = std::bind(std::forward<_Callable>(__job), std::forward<_Args>(__args)...);
std::function<void*()> job(std::move(boundFunc));
jobs_.push(job, retVal);
jobQueueCV_.notify_one();
}
private:
void* Worker();
std::condition_variable jobQueueCV_;
std::mutex jobQueueMutex;
std::queue<std::pair<std::function<void*()>, void*>> jobs_;
std::vector<Chattr::Thread> workers_;
bool terminate_ = false;
};
}