[c++] C++ 스레드 풀과 작업 로깅
이번에는 C++을 사용하여 스레드 풀을 구현하고 작업 로깅을 하는 방법에 대해 알아보겠습니다.
1. C++ 스레드 풀 구현하기
C++에서 스레드 풀을 구현하는 방법에는 여러 가지가 있지만, 표준 라이브러리인 std::thread
와 std::future
를 사용하는 방법이 일반적입니다. 아래는 간단한 예제 코드입니다.
#include <iostream>
#include <thread>
#include <vector>
#include <functional>
#include <future>
class ThreadPool {
public:
ThreadPool(size_t numThreads) {
for (size_t i = 0; i < numThreads; ++i) {
threads.emplace_back([this] {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(mutex);
condition.wait(lock, [this] { return stop || !tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
task = std::move(tasks.front());
tasks.pop();
}
task();
}
});
}
}
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
using return_type = decltype(f(args...));
auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(mutex);
if (stop) {
throw std::runtime_error("enqueue on stopped ThreadPool");
}
tasks.emplace([task]() { (*task)(); });
}
condition.notify_one();
return res;
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(mutex);
stop = true;
}
condition.notify_all();
for (std::thread& thread : threads) {
thread.join();
}
}
private:
std::vector<std::thread> threads;
std::queue<std::function<void()>> tasks;
std::mutex mutex;
std::condition_variable condition;
bool stop = false;
};
int main() {
ThreadPool pool(4);
std::vector<std::future<int>> results;
for (int i = 0; i < 8; ++i) {
results.emplace_back(
pool.enqueue([i] {
std::this_thread::sleep_for(std::chrono::seconds(1));
return i * i;
})
);
}
for (auto&& result : results) {
std::cout << result.get() << ' ';
}
std::cout << std::endl;
return 0;
}
위의 코드는 스레드 풀을 구현하는 간단한 예제로, ThreadPool
클래스를 사용하여 원하는 작업을 여러 개의 스레드로 분산하여 실행할 수 있습니다.
2. 작업 로깅 구현하기
작업 로깅은 각각의 작업이 실행될 때 로그를 남기는 것을 의미합니다. 아래는 위의 예제 코드에 작업 로깅을 추가한 예제입니다.
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
// 작업 시작 로깅
std::cout << "Starting task" << std::endl;
using return_type = decltype(f(args...));
// ...
// 작업 종료 로깅
res.then([](std::future<return_type> f) {
std::cout << "Task finished" << std::endl;
});
return res;
}
위의 코드에서 enqueue
함수 내에 작업 시작과 종료 시점에 로그를 남기는 부분을 추가했습니다. 이를 통해 각 작업이 언제 시작되고 종료되는지를 로깅할 수 있습니다.
3. 참고 자료
위의 내용은 C++을 사용하여 스레드 풀을 구현하고 작업 로깅하는 간단한 예제입니다. 보다 자세한 내용은 아래의 참고 자료를 참고하시기 바랍니다.
이상으로 C++ 스레드 풀과 작업 로깅에 대한 내용을 살펴보았습니다. 감사합니다!