Дескриптор файла C для статуса завершения задачи рабочего потока - PullRequest
0 голосов
/ 18 октября 2019

У меня есть проект C, который имеет 2 потока, main_thread и worker_thread. Ниже псевдокод объясняет об этом.

TASK g_task[MAX_TASK];
worker_thread()
{
    do {
        listen_for_task on g_task
        do_task(0);
    } while(0);
}

int post_task(msg)
{
    post on g_task
    /* I am planning for a kind of file descriptor to return from here */
    /* on which main thread polls along with sock_fd */
    return fd;
}

main_thread()
{
    int sock_fd;

    /* sock_fd listens on well known TCP port for msgs from clients */
    /* Using epoll */
    ev.events = EPOLIN;
    ev.data.fd = sock_fd;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, sock_fd, &ev);
    do {
        nfs = epoll_wait(...)
        if (nfs > 0) {
            /* I read the msg from from sock_fd and post to g_task */
            post_task(msg)
        }
    } while (0);
}

Вкл. main_thread Я жду на сокете tcp сообщений от различных клиентов. Я обрабатываю и публикую свою работу в другой теме worker_thread.

Теперь я хочу, чтобы worker_thread уведомлял main_thread после завершения каждого выполненного задания. Я ожидаю, что событие должно прийти к новому дескриптору файла. Это означает, что я ожидаю, что post_task должен вернуть новый fd, который я могу добавить к epollfd. И worker_thread должен его разбудить.

Есть какие-нибудь предложения для достижения этого?

1 Ответ

1 голос
/ 18 октября 2019

Поскольку вы упоминаете об использовании epoll, вы должны использовать Linux. Это означает, что вы можете использовать eventfd().

По сути, ваша функция post_task создает новый дескриптор eventfd для каждого потока, а основной поток отслеживает его на читаемость в epoll. Затем поток записывает 64-битное целое число в свой дескриптор, когда это будет сделано. Затем основной поток выходит из epoll, видит, что событие доступно для чтения, считывает из него 64-битное целое число и делает все, что ему нужно сделать сейчас, когда он знает, что связанный поток выполнен с задачей. (В системах, отличных от Linux, вы можете получить аналогичный эффект, используя pipe(); я написал код с функцией создания события, которая переключается между ними в зависимости от целевой ОС)

Если вам нужно передать больше информации, чем просто состояние «Я закончил», мне нравится использовать сокет дейтаграмм домена Unix, созданный с помощью socketpair(), и структуры чтения / записи со всеми необходимыми данными. Если вы включите идентификатор потока, все потоки могут даже использовать один и тот же сокет.

...