Porting windows manual-reset event to Linux? Porting windows manual-reset event to Linux? windows windows

Porting windows manual-reset event to Linux?


Pthreads are low level constructs. No, there isn't a simpler mechanism; pthread_cond__* is conceptually similar to an auto-reset event. Be careful, pthread_cond_wait may have spurious wakeups, so it should never be used without some sort of external flag regardless of the situation.

Building your own wouldn't be too hard, though.

#include <pthread.h>#include <stdbool.h>struct mrevent {    pthread_mutex_t mutex;    pthread_cond_t cond;    bool triggered;};void mrevent_init(struct mrevent *ev) {    pthread_mutex_init(&ev->mutex, 0);    pthread_cond_init(&ev->cond, 0);    ev->triggered = false;}void mrevent_trigger(struct mrevent *ev) {    pthread_mutex_lock(&ev->mutex);    ev->triggered = true;    pthread_cond_signal(&ev->cond);    pthread_mutex_unlock(&ev->mutex);}void mrevent_reset(struct mrevent *ev) {    pthread_mutex_lock(&ev->mutex);    ev->triggered = false;    pthread_mutex_unlock(&ev->mutex);}void mrevent_wait(struct mrevent *ev) {     pthread_mutex_lock(&ev->mutex);     while (!ev->triggered)         pthread_cond_wait(&ev->cond, &ev->mutex);     pthread_mutex_unlock(&ev->mutex);}

This may not fit your usage, as you will often have a different lock that you'd want to use in place of ev->mutex, but this is the gist of how it's typically used.


You can easy implement manual-reset events with pipes:

event is in triggered state -> there is something to read from the pipe

SetEvent -> write()

ResetEvent -> read()

WaitForMultipleObjects -> poll() (or select()) for reading

the "SetEvent" operation should write something (e.g. 1 byte of any value) just to put the pipe in non-empty state, so subsequent "Wait" operation, that is, poll() for data available for read will not block.

The "ResetEvent" operation will read up the data written to make sure pipe is empty again.The read-end of the pipe should be made non-blocking so that trying to reset (read from) already reset event (empty pipe) wont block - fcntl(pipe_out, F_SETFL, O_NONBLOCK)Since there may be more than 1 SetEvents before the ResetEvent, you should code it so that it reads as many bytes as there are in the pipe:

char buf[256]; // 256 is arbitrarywhile( read(pipe_out, buf, sizeof(buf)) == sizeof(buf));

Note that waiting for the event does not read from the pipe and hence the "event" will remain in triggered state until the reset operation.


I prefer the pipe approach, because often one doesn't need just an event to wait for, but multiple objects e.g. WaitForMultipleObjects(...). And with using pipes one could easily replace the windows WaitForMultipleObjects call with poll(...), select, pselect, and epoll.

There was a light-weight method for process synchronization called Futex (Fast Userspace Locking system call). There was a function futex_fd to get one or more file descriptors for futexes. This file descriptor, together with possibly many others representing real files, devices, sockets or the like could get passed to select, poll, or epoll. Unfortunately it was removed from the kernel. So the pipes tricks remain the only facility to do this:

int pipefd[2];char buf[256]; // 256 is arbitraryint r = pipe2(pipefd, O_NONBLOCK);void setEvent(){  write(pipefd[1], &buf, 1); }void resetEvent() {  while( read(pipefd[0], &buf, sizeof(buf)) > 0 ) {;} }void waitForEvent(int timeoutMS){    struct pollfd fds[1];   fds[0].fd = pipefd[0];   fds[0].events = POLLRDNORM;   poll(fds, 1, timeoutMS);}// finalize:close(pipefd[0]);close(pipefd[1]);