avoid quadratic behavior of GMainLoop when all fd's have the same priority

https://bugzilla.gnome.org/show_bug.cgi?id=640518
This commit is contained in:
Paolo Bonzini 2011-01-25 11:31:41 +01:00 committed by Matthias Clasen
parent 1e88c5321c
commit c5d9a46394

View File

@ -227,7 +227,7 @@ struct _GMainContext
GSource *source_list;
gint in_check_or_prepare;
GPollRec *poll_records;
GPollRec *poll_records, *poll_records_tail;
guint n_poll_records;
GPollFD *cached_poll_array;
guint cached_poll_array_size;
@ -302,6 +302,7 @@ struct _GUnixSignalWatchSource
struct _GPollRec
{
GPollFD *fd;
GPollRec *prev;
GPollRec *next;
gint priority;
};
@ -3530,7 +3531,7 @@ g_main_context_add_poll_unlocked (GMainContext *context,
gint priority,
GPollFD *fd)
{
GPollRec *lastrec, *pollrec;
GPollRec *prevrec, *nextrec;
GPollRec *newrec = g_slice_new (GPollRec);
/* This file descriptor may be checked before we ever poll */
@ -3538,20 +3539,26 @@ g_main_context_add_poll_unlocked (GMainContext *context,
newrec->fd = fd;
newrec->priority = priority;
lastrec = NULL;
pollrec = context->poll_records;
while (pollrec && priority >= pollrec->priority)
prevrec = context->poll_records_tail;
nextrec = NULL;
while (prevrec && priority < prevrec->priority)
{
lastrec = pollrec;
pollrec = pollrec->next;
nextrec = prevrec;
prevrec = prevrec->prev;
}
if (lastrec)
lastrec->next = newrec;
if (prevrec)
prevrec->next = newrec;
else
context->poll_records = newrec;
newrec->next = pollrec;
newrec->prev = prevrec;
newrec->next = nextrec;
if (nextrec)
nextrec->prev = newrec;
else
context->poll_records_tail = newrec;
context->n_poll_records++;
@ -3590,27 +3597,33 @@ static void
g_main_context_remove_poll_unlocked (GMainContext *context,
GPollFD *fd)
{
GPollRec *pollrec, *lastrec;
GPollRec *pollrec, *prevrec, *nextrec;
lastrec = NULL;
prevrec = NULL;
pollrec = context->poll_records;
while (pollrec)
{
nextrec = pollrec->next;
if (pollrec->fd == fd)
{
if (lastrec != NULL)
lastrec->next = pollrec->next;
if (prevrec != NULL)
prevrec->next = nextrec;
else
context->poll_records = pollrec->next;
context->poll_records = nextrec;
if (nextrec != NULL)
nextrec->prev = prevrec;
else
context->poll_records_tail = prevrec;
g_slice_free (GPollRec, pollrec);
context->n_poll_records--;
break;
}
lastrec = pollrec;
pollrec = pollrec->next;
prevrec = pollrec;
pollrec = nextrec;
}
#ifdef G_THREADS_ENABLED