mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-06-21 19:54:51 +02:00
GCancellable: Use Linux eventfd() instead of pipe
See commit f626dd2b4311bd82137c5b208ab2de288c3e6fae for rationale; basically it's cheaper than a pipe. https://bugzilla.gnome.org/show_bug.cgi?id=653140
This commit is contained in:
parent
3904c8761a
commit
fa87399280
@ -24,6 +24,9 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
#include "glib-unix.h"
|
#include "glib-unix.h"
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include <gioerror.h>
|
#include <gioerror.h>
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@ -57,6 +60,7 @@ struct _GCancellablePrivate
|
|||||||
guint cancelled_running_waiting : 1;
|
guint cancelled_running_waiting : 1;
|
||||||
|
|
||||||
guint fd_refcount;
|
guint fd_refcount;
|
||||||
|
/* If cancel_pipe[0] is != -1 and cancel_pipe[1] is -1, it is an eventfd */
|
||||||
int cancel_pipe[2];
|
int cancel_pipe[2];
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
@ -193,12 +197,56 @@ g_cancellable_class_init (GCancellableClass *klass)
|
|||||||
|
|
||||||
#ifndef G_OS_WIN32
|
#ifndef G_OS_WIN32
|
||||||
|
|
||||||
|
static void
|
||||||
|
g_cancellable_write_cancelled (GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
gssize c;
|
||||||
|
GCancellablePrivate *priv;
|
||||||
|
const char ch = 'x';
|
||||||
|
|
||||||
|
priv = cancellable->priv;
|
||||||
|
|
||||||
|
if (priv->cancel_pipe[0] == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_assert (cancellable->priv->cancelled);
|
||||||
|
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (priv->cancel_pipe[1] == -1)
|
||||||
|
{
|
||||||
|
guint64 buf = 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
c = write (priv->cancel_pipe[0], &buf, sizeof (buf));
|
||||||
|
while (c == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do
|
||||||
|
c = write (priv->cancel_pipe[1], &ch, 1);
|
||||||
|
while (c == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_cancellable_open_pipe (GCancellable *cancellable)
|
g_cancellable_open_pipe (GCancellable *cancellable)
|
||||||
{
|
{
|
||||||
GCancellablePrivate *priv;
|
GCancellablePrivate *priv;
|
||||||
|
|
||||||
priv = cancellable->priv;
|
priv = cancellable->priv;
|
||||||
|
#ifdef HAVE_EVENTFD
|
||||||
|
priv->cancel_pipe[0] = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||||
|
if (priv->cancel_pipe[0] >= 0)
|
||||||
|
{
|
||||||
|
if (priv->cancelled)
|
||||||
|
g_cancellable_write_cancelled (cancellable);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (errno != ENOSYS)
|
||||||
|
return;
|
||||||
|
/* Fall through on ENOSYS */
|
||||||
|
#endif
|
||||||
if (g_unix_open_pipe (priv->cancel_pipe, FD_CLOEXEC, NULL))
|
if (g_unix_open_pipe (priv->cancel_pipe, FD_CLOEXEC, NULL))
|
||||||
{
|
{
|
||||||
/* Make them nonblocking, just to be sure we don't block
|
/* Make them nonblocking, just to be sure we don't block
|
||||||
@ -208,14 +256,7 @@ g_cancellable_open_pipe (GCancellable *cancellable)
|
|||||||
g_unix_set_fd_nonblocking (priv->cancel_pipe[1], TRUE, NULL);
|
g_unix_set_fd_nonblocking (priv->cancel_pipe[1], TRUE, NULL);
|
||||||
|
|
||||||
if (priv->cancelled)
|
if (priv->cancelled)
|
||||||
{
|
g_cancellable_write_cancelled (cancellable);
|
||||||
const char ch = 'x';
|
|
||||||
gssize c;
|
|
||||||
|
|
||||||
do
|
|
||||||
c = write (priv->cancel_pipe[1], &ch, 1);
|
|
||||||
while (c == -1 && errno == EINTR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -351,11 +392,24 @@ g_cancellable_reset (GCancellable *cancellable)
|
|||||||
if (priv->cancel_pipe[0] != -1)
|
if (priv->cancel_pipe[0] != -1)
|
||||||
{
|
{
|
||||||
gssize c;
|
gssize c;
|
||||||
char ch;
|
#ifdef HAVE_EVENTFD
|
||||||
|
if (priv->cancel_pipe[1] == -1)
|
||||||
|
{
|
||||||
|
guint64 buf;
|
||||||
|
|
||||||
do
|
do
|
||||||
c = read (priv->cancel_pipe[0], &ch, 1);
|
c = read (priv->cancel_pipe[0], &buf, sizeof(buf));
|
||||||
while (c == -1 && errno == EINTR);
|
while (c == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
do
|
||||||
|
c = read (priv->cancel_pipe[0], &ch, 1);
|
||||||
|
while (c == -1 && errno == EINTR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->cancelled = FALSE;
|
priv->cancelled = FALSE;
|
||||||
@ -604,15 +658,9 @@ g_cancellable_cancel (GCancellable *cancellable)
|
|||||||
if (priv->event)
|
if (priv->event)
|
||||||
SetEvent (priv->event);
|
SetEvent (priv->event);
|
||||||
#endif
|
#endif
|
||||||
if (priv->cancel_pipe[1] != -1)
|
|
||||||
{
|
g_cancellable_write_cancelled (cancellable);
|
||||||
const char ch = 'x';
|
|
||||||
gssize c;
|
|
||||||
|
|
||||||
do
|
|
||||||
c = write (priv->cancel_pipe[1], &ch, 1);
|
|
||||||
while (c == -1 && errno == EINTR);
|
|
||||||
}
|
|
||||||
G_UNLOCK(cancellable);
|
G_UNLOCK(cancellable);
|
||||||
|
|
||||||
g_object_ref (cancellable);
|
g_object_ref (cancellable);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user