c_cpp event_loop.cpp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp event_loop.cpp相关的知识,希望对你有一定的参考价值。

#include <array>
#include <condition_variable>
#include <cstdio>
#include <mutex>
#include <iostream>
#include <string>
#include <vector>
#include <thread>

#include <errno.h>

#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

using namespace std;

class message
{
public:
    virtual void process() = 0;

    virtual ~message()
    {
    }
};

class notify_message : public message
{
    string text_;

public:
    notify_message(const string &text)
        : text_(text)
    {
    }

    void process() override
    {
        cerr << text_;
    }
};

class worker_thread
{
public:
    vector<unique_ptr<message>> messages_;
    vector<unique_ptr<message>> messages_back_buffer_;
    mutex message_mutex_;
    condition_variable  message_cond_;
    thread wt_;

    ~worker_thread()
    {
        wt_.join();
    }

    void start()
    {
        wt_ = thread(&worker_thread::run, this);
    }

    void run()
    {
        unique_lock<mutex> lock(message_mutex_);
        while (true) {
            message_cond_.wait(lock, [&]() {
                return !messages_.empty();
            });

            swap(messages_, messages_back_buffer_);

            lock.unlock();

            for (const auto &msg : messages_back_buffer_) {
                try {
                    msg->process();
                }
                catch (const exception &e) {
                    cerr << e.what() << '\n';
                }
                catch (...) {
                    cerr << "An error has occurred\n";
                }
            }

            messages_back_buffer_.clear();

            lock.lock();
        }
    }

    void add_messages(vector<unique_ptr<message>> messages)
    {
        if (!messages.empty()) {
            (lock_guard<mutex>(message_mutex_),
             messages_.insert(begin(messages_),
                              make_move_iterator(begin(messages)),
                              make_move_iterator(end(messages))));

            message_cond_.notify_one();
        }
    }
};

int make_socket()
{
    int sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
    if (sock < 0) {
        perror("socket");
        exit(-1);
    }

    const char *sock_path = "foo";

    if (remove(sock_path) < 0 && errno != ENOENT) {
        perror("remove");
        exit(-1);
    }

    sockaddr_un server_addr;
    memset(&server_addr, sizeof server_addr, 0);
    server_addr.sun_family = AF_UNIX;

    strncpy(server_addr.sun_path, sock_path, sizeof server_addr.sun_path - 1);

    if (bind(sock, reinterpret_cast<sockaddr *>(&server_addr), sizeof server_addr) < 0) {
        perror("bind");
        exit(-1);
    }

    return sock;
}

int main()
{
    int sock = make_socket();

    array<pollfd, 1> fds = { sock, POLLIN, 0 };

    worker_thread worker;
    worker.start();

    while (true) {
        int ret = poll(begin(fds), fds.size(), -1);
        if (ret < 0 && errno == EINTR) {
            continue;
        }

        if (fds[0].revents & POLLIN) {
            vector<unique_ptr<message>> messages;

            while (true) {
                char buf[1024] = { };
                ssize_t len = recvfrom(sock, buf, sizeof buf, 0, NULL, NULL);
                if (len > 0) {
                    messages.emplace_back(new notify_message(buf));
                    continue;
                }
                else if (len < 0) {
                    if (errno != EINTR && errno != EWOULDBLOCK) {
                        perror("recvfrom");
                    }
                }
                break;
            }

            worker.add_messages(move(messages));
        }
    }
}

以上是关于c_cpp event_loop.cpp的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 200.岛屿数量

c_cpp 127.单词阶梯

c_cpp MOFSET

c_cpp MOFSET

c_cpp 31.下一个排列

c_cpp string→char *