Implement g_cancellable_release_fd()

Part of: Bug 591388 - number of GCancellables available is too limited
This commit is contained in:
Benjamin Otte 2009-08-11 15:04:43 +02:00
parent 63426886ff
commit e2c97292c2

View File

@ -52,11 +52,11 @@ enum {
struct _GCancellablePrivate struct _GCancellablePrivate
{ {
GObject parent_instance;
guint cancelled : 1; guint cancelled : 1;
guint cancelled_running : 1; guint cancelled_running : 1;
guint cancelled_running_waiting : 1; guint cancelled_running_waiting : 1;
guint fd_refcount;
int cancel_pipe[2]; int cancel_pipe[2];
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -73,23 +73,39 @@ G_LOCK_DEFINE_STATIC(cancellable);
static GCond *cancellable_cond = NULL; static GCond *cancellable_cond = NULL;
static void static void
g_cancellable_finalize (GObject *object) g_cancellable_close_pipe (GCancellable *cancellable)
{ {
GCancellable *cancellable = G_CANCELLABLE (object);
GCancellablePrivate *priv; GCancellablePrivate *priv;
priv = cancellable->priv; priv = cancellable->priv;
if (priv->cancel_pipe[0] != -1) if (priv->cancel_pipe[0] != -1)
{
close (priv->cancel_pipe[0]); close (priv->cancel_pipe[0]);
priv->cancel_pipe[0] = -1;
}
if (priv->cancel_pipe[1] != -1) if (priv->cancel_pipe[1] != -1)
{
close (priv->cancel_pipe[1]); close (priv->cancel_pipe[1]);
priv->cancel_pipe[1] = -1;
}
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
if (priv->event) if (priv->event)
{
CloseHandle (priv->event); CloseHandle (priv->event);
priv->event = NULL;
}
#endif #endif
}
static void
g_cancellable_finalize (GObject *object)
{
GCancellable *cancellable = G_CANCELLABLE (object);
g_cancellable_close_pipe (cancellable);
G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object); G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
} }
@ -430,8 +446,8 @@ int
g_cancellable_get_fd (GCancellable *cancellable) g_cancellable_get_fd (GCancellable *cancellable)
{ {
GCancellablePrivate *priv; GCancellablePrivate *priv;
int fd; int fd;
if (cancellable == NULL) if (cancellable == NULL)
return -1; return -1;
@ -443,8 +459,9 @@ g_cancellable_get_fd (GCancellable *cancellable)
G_LOCK(cancellable); G_LOCK(cancellable);
if (priv->cancel_pipe[0] == -1) if (priv->cancel_pipe[0] == -1)
g_cancellable_open_pipe (cancellable); g_cancellable_open_pipe (cancellable);
fd = priv->cancel_pipe[0]; fd = priv->cancel_pipe[0];
if (fd != -1)
priv->fd_refcount++;
G_UNLOCK(cancellable); G_UNLOCK(cancellable);
#endif #endif
@ -484,7 +501,6 @@ gboolean
g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd) g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
{ {
GCancellablePrivate *priv; GCancellablePrivate *priv;
int fd;
g_return_val_if_fail (pollfd != NULL, FALSE); g_return_val_if_fail (pollfd != NULL, FALSE);
if (cancellable == NULL) if (cancellable == NULL)
@ -494,22 +510,34 @@ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
priv = cancellable->priv; priv = cancellable->priv;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
if (!priv->event) G_LOCK(cancellable);
if (priv->event == NULL)
{ {
/* A manual reset anonymous event, starting unset */ /* A manual reset anonymous event, starting unset */
priv->event = CreateEvent (NULL, TRUE, FALSE, NULL); priv->event = CreateEvent (NULL, TRUE, FALSE, NULL);
if (priv->event == NULL) if (priv->event == NULL)
{
G_UNLOCK(cancellable);
return FALSE; return FALSE;
} }
}
priv->fd_refcount++;
G_UNLOCK(cancellable);
pollfd->fd = (gintptr)priv->event; pollfd->fd = (gintptr)priv->event;
#else /* !G_OS_WIN32 */ #else /* !G_OS_WIN32 */
fd = g_cancellable_get_fd (cancellable); {
int fd = g_cancellable_get_fd (cancellable);
if (fd == -1) if (fd == -1)
return -1; return FALSE;
pollfd->fd = fd; pollfd->fd = fd;
}
#endif /* G_OS_WIN32 */ #endif /* G_OS_WIN32 */
pollfd->events = G_IO_IN; pollfd->events = G_IO_IN;
pollfd->revents = 0; pollfd->revents = 0;
return TRUE;
} }
/** /**
@ -531,7 +559,18 @@ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
void void
g_cancellable_release_fd (GCancellable *cancellable) g_cancellable_release_fd (GCancellable *cancellable)
{ {
GCancellablePrivate *priv;
g_return_if_fail (G_IS_CANCELLABLE (cancellable)); g_return_if_fail (G_IS_CANCELLABLE (cancellable));
g_return_if_fail (cancellable->priv->fd_refcount > 0);
priv = cancellable->priv;
G_LOCK (cancellable);
priv->fd_refcount--;
if (priv->fd_refcount == 0)
g_cancellable_close_pipe (cancellable);
G_UNLOCK (cancellable);
} }
/** /**
@ -556,7 +595,7 @@ g_cancellable_release_fd (GCancellable *cancellable)
void void
g_cancellable_cancel (GCancellable *cancellable) g_cancellable_cancel (GCancellable *cancellable)
{ {
static const char ch = 'x'; const char ch = 'x';
gboolean cancel; gboolean cancel;
GCancellablePrivate *priv; GCancellablePrivate *priv;