aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/notify.c54
-rw-r--r--src/notify.h45
2 files changed, 66 insertions, 33 deletions
diff --git a/src/notify.c b/src/notify.c
index 4eda79391..5d53b231d 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -17,32 +17,52 @@
*/
#include "notify.h"
-#include "os_compat.h"
-#include "log.h"
-#include "utils.h"
-void notifyInit(Notify *notify)
+int notifyInit(Notify *notify)
{
- if (pipe(notify->fds) < 0)
- FATAL("Couldn't open pipe: %s", strerror(errno));
- if (set_nonblocking(notify->fds[1]) < 0)
- FATAL("Couldn't set non-blocking on notify fd: %s",
- strerror(errno));
+ int ret;
+
+ ret = pthread_mutex_init(&notify->mutex, NULL);
+ if (ret != 0)
+ return ret;
+
+ ret = pthread_cond_init(&notify->cond, NULL);
+ if (ret != 0) {
+ pthread_mutex_destroy(&notify->mutex);
+ return ret;
+ }
+
+ notify->pending = 0;
+
+ return 0;
}
-void notifyWait(Notify *notify)
+void notifyEnter(Notify *notify)
{
- char buffer[64];
+ pthread_mutex_lock(&notify->mutex);
+}
- if (read(notify->fds[0], buffer, sizeof(buffer)) < 0)
- FATAL("error reading from pipe: %s\n", strerror(errno));
+void notifyLeave(Notify *notify)
+{
+ pthread_mutex_unlock(&notify->mutex);
+}
+
+void notifyWait(Notify *notify)
+{
+ if (!notify->pending)
+ pthread_cond_wait(&notify->cond, &notify->mutex);
+ notify->pending = 0;
}
void notifySignal(Notify *notify)
{
- char buffer = 0;
+ notify->pending = 1;
+ pthread_cond_signal(&notify->cond);
+}
- if (write(notify->fds[1], &buffer, sizeof(buffer)) < 0 &&
- errno != EAGAIN && errno != EINTR)
- FATAL("error writing to pipe: %s\n", strerror(errno));
+void notifySignalSync(Notify *notify)
+{
+ pthread_mutex_lock(&notify->mutex);
+ notifySignal(notify);
+ pthread_mutex_unlock(&notify->mutex);
}
diff --git a/src/notify.h b/src/notify.h
index 9f1a1961b..f79518f8f 100644
--- a/src/notify.h
+++ b/src/notify.h
@@ -19,29 +19,42 @@
#ifndef NOTIFY_H
#define NOTIFY_H
-/*
- * This library implements inter-process signalling using blocking
- * read() on an anonymous pipe. As a side effect, the read() system
- * call has the same signal interruption behaviour as the old sleep
- * function.
- *
- * As soon as mpd uses threading instead of fork()/shm, we can replace
- * this library with a pthread_cond object.
- *
- * This code is experimental and carries a lot of overhead. Still, it
- * uses less resources than the old polling code with a fixed sleep
- * time.
- *
- */
+#include "os_compat.h"
typedef struct _Notify {
- int fds[2];
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int pending;
} Notify;
-void notifyInit(Notify *notify);
+int notifyInit(Notify *notify);
+
+/**
+ * The thread which shall be notified by this object must call this
+ * function before any notifyWait() invocation. It locks the mutex.
+ */
+void notifyEnter(Notify *notify);
+
+/**
+ * Neutralize notifyLeave().
+ */
+void notifyLeave(Notify *notify);
+/**
+ * Wait for a notification. Return immediately if we have already
+ * been notified since we last returned from notifyWait().
+ */
void notifyWait(Notify *notify);
+/**
+ * Notify the thread. This function never blocks.
+ */
void notifySignal(Notify *notify);
+/**
+ * Notify the thread synchonously, i.e. wait until it has received the
+ * notification.
+ */
+void notifySignalSync(Notify *notify);
+
#endif