Reactor/lib/EventLoopThread.hpp
2025-06-27 18:01:00 -05:00

111 lines
2.6 KiB
C++

#pragma once
#include "Core.hpp"
#include "Utilities.hpp"
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <memory>
#include <atomic>
namespace reactor {
class EventLoopThread : public NonCopyable
{
private:
std::thread thread_;
EventLoop* loop_;
std::mutex mutex_;
std::condition_variable cond_;
std::string name_;
void threadFunc()
{
LOG_DEBUG << "EventLoopThread '" << name_ << "' starting";
EventLoop loop;
{
std::lock_guard<std::mutex> lock(mutex_);
loop_ = &loop;
cond_.notify_one();
}
loop.loop();
std::lock_guard<std::mutex> lock(mutex_);
loop_ = nullptr;
LOG_DEBUG << "EventLoopThread '" << name_ << "' finished";
}
public:
explicit EventLoopThread(const std::string& name = "EventLoopThread")
: loop_(nullptr), name_(name)
{
thread_ = std::thread([this]() { threadFunc(); });
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return loop_ != nullptr; });
LOG_INFO << "EventLoopThread '" << name_ << "' initialized";
}
~EventLoopThread()
{
if (loop_) {
loop_->quit();
thread_.join();
}
LOG_INFO << "EventLoopThread '" << name_ << "' destroyed";
}
EventLoop* getLoop() { return loop_; }
const std::string& name() const { return name_; }
};
class EventLoopThreadPool : public NonCopyable
{
private:
std::vector<std::unique_ptr<EventLoopThread>> threads_;
std::vector<EventLoop*> loops_;
std::atomic<size_t> next_;
std::string baseThreadName_;
public:
explicit EventLoopThreadPool(size_t numThreads, const std::string& baseName = "EventLoopThread")
: next_(0), baseThreadName_(baseName)
{
LOG_INFO << "Creating EventLoopThreadPool with " << numThreads << " threads";
for (size_t i = 0; i < numThreads; ++i) {
std::string threadName = baseThreadName_ + "-" + std::to_string(i);
auto thread = std::make_unique<EventLoopThread>(threadName);
loops_.push_back(thread->getLoop());
threads_.push_back(std::move(thread));
}
LOG_INFO << "EventLoopThreadPool created with " << numThreads << " threads";
}
~EventLoopThreadPool()
{
LOG_INFO << "EventLoopThreadPool destroying " << threads_.size() << " threads";
}
EventLoop* getNextLoop()
{
if (loops_.empty()) {
LOG_WARN << "EventLoopThreadPool has no loops available";
return nullptr;
}
size_t index = next_++ % loops_.size();
LOG_TRACE << "EventLoopThreadPool returning loop " << index;
return loops_[index];
}
std::vector<EventLoop*> getAllLoops() const { return loops_; }
size_t size() const { return loops_.size(); }
const std::string& getBaseName() const { return baseThreadName_; }
};
} // namespace reactor