use the pthread API in notify.c
This patch rewrites notify.c to use the pthread API, namely pthread_mutex and pthread_cond. This is a lot cheaper and easier than the pipe() hack. git-svn-id: https://svn.musicpd.org/mpd/trunk@7280 09075e82-0dd4-0310-85a5-a0d7c8717e4f
This commit is contained in:
parent
38e0dafc4c
commit
0146fbe3ce
56
src/notify.c
56
src/notify.c
@ -17,32 +17,52 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "notify.h"
|
#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)
|
int ret;
|
||||||
FATAL("Couldn't open pipe: %s", strerror(errno));
|
|
||||||
if (set_nonblocking(notify->fds[1]) < 0)
|
ret = pthread_mutex_init(¬ify->mutex, NULL);
|
||||||
FATAL("Couldn't set non-blocking on notify fd: %s",
|
if (ret != 0)
|
||||||
strerror(errno));
|
return ret;
|
||||||
|
|
||||||
|
ret = pthread_cond_init(¬ify->cond, NULL);
|
||||||
|
if (ret != 0) {
|
||||||
|
pthread_mutex_destroy(¬ify->mutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify->pending = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyEnter(Notify *notify)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(¬ify->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyLeave(Notify *notify)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(¬ify->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifyWait(Notify *notify)
|
void notifyWait(Notify *notify)
|
||||||
{
|
{
|
||||||
char buffer[64];
|
if (!notify->pending)
|
||||||
|
pthread_cond_wait(¬ify->cond, ¬ify->mutex);
|
||||||
if (read(notify->fds[0], buffer, sizeof(buffer)) < 0)
|
notify->pending = 0;
|
||||||
FATAL("error reading from pipe: %s\n", strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notifySignal(Notify *notify)
|
void notifySignal(Notify *notify)
|
||||||
{
|
{
|
||||||
char buffer = 0;
|
notify->pending = 1;
|
||||||
|
pthread_cond_signal(¬ify->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(¬ify->mutex);
|
||||||
|
notifySignal(notify);
|
||||||
|
pthread_mutex_unlock(¬ify->mutex);
|
||||||
}
|
}
|
||||||
|
45
src/notify.h
45
src/notify.h
@ -19,29 +19,42 @@
|
|||||||
#ifndef NOTIFY_H
|
#ifndef NOTIFY_H
|
||||||
#define NOTIFY_H
|
#define NOTIFY_H
|
||||||
|
|
||||||
/*
|
#include "os_compat.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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _Notify {
|
typedef struct _Notify {
|
||||||
int fds[2];
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
int pending;
|
||||||
} Notify;
|
} 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);
|
void notifyWait(Notify *notify);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the thread. This function never blocks.
|
||||||
|
*/
|
||||||
void notifySignal(Notify *notify);
|
void notifySignal(Notify *notify);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the thread synchonously, i.e. wait until it has received the
|
||||||
|
* notification.
|
||||||
|
*/
|
||||||
|
void notifySignalSync(Notify *notify);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user