rashok
rashok

Reputation: 13464

C File Descriptor for polling task completion status of worker thread

I am having a C project which has 2 threads, main_thread and worker_thread. Below pseudocode explains about it.

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);
}

On main_thread I am waiting on a tcp socket for msgs from various clients. I am processing and posting the work to be done to another thread worker_thread.

Now I want the worker_thread to notify main_thread after finishing each task posted to it. I am expecting the event should come to a new file descriptor. That means I am expecting post_task should return a new fd which I can add to epollfd. And worker_thread should wakeup it.

Any suggestion for achieving this is ?

Upvotes: 0

Views: 129

Answers (1)

Shawn
Shawn

Reputation: 52549

Since you mention using epoll, you must be using Linux. Which means you can use eventfd().

Basically, your post_task function creates a new eventfd descriptor for each thread and the main thread monitors it for readability in epoll. The thread then writes a 64 bit integer to its descriptor when it's done. The main thread then wakes from epoll, sees the event is readable, reads a 64 bit integer from it, and does whatever it needs to do now that it knows the associated thread is done with a task. (On non-linux systems you can get a similar effect using pipe(); I've written code with an event creation function that switches between the two depending on what OS is being targeted)

If you need to pass more information than just a "I'm done" status, I like using a Unix domain datagram socket created with socketpair() and reading/writing structs with all the needed data. If you include a thread id, all threads can even share the same socket.

Upvotes: 1

Related Questions