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