cxx之简单的消息队列模型

194 阅读1分钟

event_loop.h

namespace eventLoop {

class EventLoop {
public:
    static std::unique_ptr<EventLoop> create();

    ~EventLoop();

    void doShutDown();
    bool onReceiveEvent(std::shared_ptr<std::string> event);

private:
    EventLoop();
    void receivingLoop();
    void receiveEventLocked(std::unique_lock<std::mutex>& lock);

private:

    std::deque<std::shared_ptr<std::string>> m_events;

    bool m_is_shutdown;

    std::mutex m_mutex;

    std::condition_variable m_condition_variable;

    std::thread m_receiving_thread;
};
}

event_loop.cpp

std::unique_ptr<eventLoop::EventLoop> eventLoop::EventLoop::create() {
    return std::unique_ptr<eventLoop::EventLoop>(new eventLoop::EventLoop());
}

eventLoop::EventLoop::EventLoop()
        : m_is_shutdown(false), m_mutex(), m_condition_variable() {
    m_receiving_thread = std::thread(&eventLoop::EventLoop::receivingLoop, this);
}

eventLoop::EventLoop::~EventLoop() {
    doShutDown();
}

void eventLoop::EventLoop::doShutDown() {
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_is_shutdown = true;
        m_condition_variable.notify_one();
    }
    if (m_receiving_thread.joinable()) {
        m_receiving_thread.join();
    }

    // other clear work
    // ...
}

bool eventLoop::EventLoop::onReceiveEvent(std::shared_ptr<std::string> event) {
    if (!event) {
        return false;
    }
    std::lock_guard<std::mutex> lock(m_mutex);
    if (m_is_shutdown) {
        return false;
    }
    m_events.push_back(std::move(event));
    m_condition_variable.notify_one();
}

void eventLoop::EventLoop::receivingLoop() {
    auto wake = [this]() {
        return !m_events.empty() || m_is_shutdown;
    };
    std::unique_lock<std::mutex> lock(m_mutex);
    while (true) {
        m_condition_variable.wait(lock, wake);
        if (m_is_shutdown) {
            break;
        }
        receiveEventLocked(lock);
    }
}

void eventLoop::EventLoop::receiveEventLocked(std::unique_lock<std::mutex>& lock) {
    if (m_events.empty()) {
        return;
    }
    auto event = m_events.front();
    m_events.pop_front();
    lock.unlock();

    // handle the event
    // ...
    std::cout << "handle the event->" << *event << std::endl;

    lock.lock();
}