[Cogl] [PATCH 2/2] Use the Wayland embedded linked list implementation instead of BSD's

Neil Roberts neil at linux.intel.com
Mon Jun 10 06:15:08 PDT 2013


This removes cogl-queue.h and adds a copy of Wayland's embedded list
implementation. The advantage of the Wayland model is that it is much
simpler and so it is easier to follow. It also doesn't require
defining a typedef for every list type.

The downside is that there is only one list type which is a
doubly-linked list where the head has a pointer to both the beginning
and the end. The BSD implementation has many more combinations some of
which we were taking advantage of to reduce the size of critical
structs where we didn't need a pointer to the end of the list.

The corresponding changes to uses of cogl-queue.h are:

• COGL_STAILQ_* was used for onscreen the list of events and dirty
  notifications. This makes the size of the CoglContext grow by one
  pointer.

• COGL_TAILQ_* was used for fences.

• COGL_LIST_* for CoglClosures. In this case the list head now has an
  extra pointer which means CoglOnscreen will grow by the size of
  three pointers, but this doesn't seem like a particularly important
  struct to optimise for size anyway.

• COGL_LIST_* was used for the list of foreign GLES2 offscreens.

• COGL_TAILQ_* was used for the list of sub stacks in a
  CoglMemoryStack.

• COGL_LIST_* was used to track the list of layers that haven't had
  code generated yet while generating a fragment shader for a
  pipeline.

• COGL_LIST_* was used to track the pipeline hierarchy in CoglNode.

The last part is a bit more controversial because it increases the
size of CoglPipeline and CoglPipelineLayer by one pointer in order to
have the redundant tail pointer for the list head. Normally we try to
be very careful about the size of the CoglPipeline struct. Because
CoglPipeline is slice-allocated, this effectively ends up adding two
pointers to the size because GSlice rounds up to the size of two
pointers.
---
 cogl/Makefile.am                            |   3 +-
 cogl/cogl-closure-list-private.h            |  52 ++-
 cogl/cogl-closure-list.c                    |  10 +-
 cogl/cogl-context-private.h                 |   6 +-
 cogl/cogl-context.c                         |   6 +-
 cogl/cogl-fence-private.h                   |   6 +-
 cogl/cogl-fence.c                           |  25 +-
 cogl/cogl-gles2-context-private.h           |  14 +-
 cogl/cogl-gles2-context.c                   |  21 +-
 cogl/cogl-journal-private.h                 |   2 +-
 cogl/cogl-journal.c                         |   8 +-
 cogl/cogl-list.c                            |  94 ++++
 cogl/cogl-list.h                            | 123 ++++++
 cogl/cogl-memory-stack.c                    |  39 +-
 cogl/cogl-node-private.h                    |   8 +-
 cogl/cogl-node.c                            |  10 +-
 cogl/cogl-onscreen-private.h                |  28 +-
 cogl/cogl-onscreen.c                        |  29 +-
 cogl/cogl-pipeline-layer.c                  |   4 +-
 cogl/cogl-pipeline-private.h                |   2 +-
 cogl/cogl-pipeline.c                        |   4 +-
 cogl/cogl-poll.c                            |   2 +-
 cogl/cogl-queue.h                           | 647 ----------------------------
 cogl/cogl-renderer-private.h                |   2 +-
 cogl/cogl-renderer.c                        |   2 +-
 cogl/cogl-sdl.c                             |   2 +-
 cogl/driver/gl/cogl-pipeline-fragend-glsl.c |  47 +-
 doc/reference/cogl2/Makefile.am             |   1 -
 28 files changed, 375 insertions(+), 822 deletions(-)
 create mode 100644 cogl/cogl-list.c
 create mode 100644 cogl/cogl-list.h
 delete mode 100644 cogl/cogl-queue.h

diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 323239d..0c470f0 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -375,7 +375,8 @@ cogl_sources_c = \
 	$(srcdir)/cogl-point-in-poly-private.h       	\
 	$(srcdir)/cogl-point-in-poly.c       		\
 	$(srcdir)/cogl-clutter.c       			\
-	$(srcdir)/cogl-queue.h				\
+	$(srcdir)/cogl-list.c				\
+	$(srcdir)/cogl-list.h				\
 	$(srcdir)/winsys/cogl-winsys-stub-private.h	\
 	$(srcdir)/winsys/cogl-winsys-stub.c		\
 	$(srcdir)/cogl-config-private.h			\
diff --git a/cogl/cogl-closure-list-private.h b/cogl/cogl-closure-list-private.h
index 9aaa179..92ba0a1 100644
--- a/cogl/cogl-closure-list-private.h
+++ b/cogl/cogl-closure-list-private.h
@@ -25,7 +25,7 @@
 #define _COGL_CLOSURE_LIST_PRIVATE_H_
 
 #include "cogl-object.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 
 /*
  * This implements a list of callbacks that can be used a bit like
@@ -43,18 +43,14 @@
  * point.
  */
 
-typedef struct _CoglClosure CoglClosure;
-
-COGL_LIST_HEAD (CoglClosureList, CoglClosure);
-
-struct _CoglClosure
+typedef struct _CoglClosure
 {
-  COGL_LIST_ENTRY (CoglClosure) list_node;
+  CoglList link;
 
   void *function;
   void *user_data;
   CoglUserDataDestroyCallback destroy_cb;
-};
+} CoglClosure;
 
 /*
  * _cogl_closure_disconnect:
@@ -67,10 +63,10 @@ void
 _cogl_closure_disconnect (CoglClosure *closure);
 
 void
-_cogl_closure_list_disconnect_all (CoglClosureList *list);
+_cogl_closure_list_disconnect_all (CoglList *list);
 
 CoglClosure *
-_cogl_closure_list_add (CoglClosureList *list,
+_cogl_closure_list_add (CoglList *list,
                         void *function,
                         void *user_data,
                         CoglUserDataDestroyCallback destroy_cb);
@@ -91,26 +87,26 @@ _cogl_closure_list_add (CoglClosureList *list,
  * callbacks. If you want to handle the return value you should
  * manually iterate the list and invoke the callbacks yourself.
  */
-#define _cogl_closure_list_invoke(list, cb_type, ...)            \
-  G_STMT_START {                                                \
-    CoglClosure *_c, *_tmp;                                     \
-                                                                \
-    COGL_LIST_FOREACH_SAFE (_c, (list), list_node, _tmp)        \
-      {                                                         \
-        cb_type _cb = _c->function;                             \
-        _cb (__VA_ARGS__, _c->user_data);                       \
-      }                                                         \
+#define _cogl_closure_list_invoke(list, cb_type, ...)   \
+  G_STMT_START {                                        \
+    CoglClosure *_c, *_tmp;                             \
+                                                        \
+    _cogl_list_for_each_safe (_c, _tmp, (list), link)   \
+      {                                                 \
+        cb_type _cb = _c->function;                     \
+        _cb (__VA_ARGS__, _c->user_data);               \
+      }                                                 \
   } G_STMT_END
 
-#define _cogl_closure_list_invoke_no_args(list)                 \
-  G_STMT_START {                                                \
-    CoglClosure *_c, *_tmp;                                     \
-                                                                \
-    COGL_LIST_FOREACH_SAFE (_c, (list), list_node, _tmp)        \
-      {                                                         \
-        void (*_cb)(void *) = _c->function;                     \
-        _cb (_c->user_data);                                    \
-      }                                                         \
+#define _cogl_closure_list_invoke_no_args(list)         \
+  G_STMT_START {                                        \
+    CoglClosure *_c, *_tmp;                             \
+                                                        \
+    _cogl_list_for_each_safe (_c, _tmp, (list), link)   \
+      {                                                 \
+        void (*_cb)(void *) = _c->function;             \
+        _cb (_c->user_data);                            \
+      }                                                 \
   } G_STMT_END
 
 #endif /* _COGL_CLOSURE_LIST_PRIVATE_H_ */
diff --git a/cogl/cogl-closure-list.c b/cogl/cogl-closure-list.c
index 60b26b4..dfb5bf3 100644
--- a/cogl/cogl-closure-list.c
+++ b/cogl/cogl-closure-list.c
@@ -30,7 +30,7 @@
 void
 _cogl_closure_disconnect (CoglClosure *closure)
 {
-  COGL_LIST_REMOVE (closure, list_node);
+  _cogl_list_remove (&closure->link);
 
   if (closure->destroy_cb)
     closure->destroy_cb (closure->user_data);
@@ -39,16 +39,16 @@ _cogl_closure_disconnect (CoglClosure *closure)
 }
 
 void
-_cogl_closure_list_disconnect_all (CoglClosureList *list)
+_cogl_closure_list_disconnect_all (CoglList *list)
 {
   CoglClosure *closure, *next;
 
-  COGL_LIST_FOREACH_SAFE (closure, list, list_node, next)
+  _cogl_list_for_each_safe (closure, next, list, link)
     _cogl_closure_disconnect (closure);
 }
 
 CoglClosure *
-_cogl_closure_list_add (CoglClosureList *list,
+_cogl_closure_list_add (CoglList *list,
                         void *function,
                         void *user_data,
                         CoglUserDataDestroyCallback destroy_cb)
@@ -59,7 +59,7 @@ _cogl_closure_list_add (CoglClosureList *list,
   closure->user_data = user_data;
   closure->destroy_cb = destroy_cb;
 
-  COGL_LIST_INSERT_HEAD (list, closure, list_node);
+  _cogl_list_insert (list, &closure->link);
 
   return closure;
 }
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 7978232..c5f215d 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -176,8 +176,8 @@ struct _CoglContext
   gboolean have_last_offscreen_allocate_flags;
   CoglOffscreenAllocateFlags last_offscreen_allocate_flags;
 
-  CoglOnscreenEventList onscreen_events_queue;
-  CoglOnscreenQueuedDirtyList onscreen_dirty_queue;
+  CoglList onscreen_events_queue;
+  CoglList onscreen_dirty_queue;
   CoglClosure *onscreen_dispatch_idle;
 
   CoglGLES2Context *current_gles2_context;
@@ -274,7 +274,7 @@ struct _CoglContext
   int n_uniform_names;
 
   CoglPollSource *fences_poll_source;
-  CoglFenceList fences;
+  CoglList fences;
 
   /* This defines a list of function pointers that Cogl uses from
      either GL or GLES. All functions are accessed indirectly through
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 39901b1..26fe85c 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -292,8 +292,8 @@ cogl_context_new (CoglDisplay *display,
   context->current_draw_buffer_state_flushed = 0;
   context->current_draw_buffer_changes = COGL_FRAMEBUFFER_STATE_ALL;
 
-  COGL_TAILQ_INIT (&context->onscreen_events_queue);
-  COGL_TAILQ_INIT (&context->onscreen_dirty_queue);
+  _cogl_list_init (&context->onscreen_events_queue);
+  _cogl_list_init (&context->onscreen_dirty_queue);
 
   g_queue_init (&context->gles2_context_stack);
 
@@ -431,7 +431,7 @@ cogl_context_new (CoglDisplay *display,
       cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
     GE (context, glEnable (GL_POINT_SPRITE));
 
-  COGL_TAILQ_INIT (&context->fences);
+  _cogl_list_init (&context->fences);
 
   return context;
 }
diff --git a/cogl/cogl-fence-private.h b/cogl/cogl-fence-private.h
index 0817b7d..7a41c51 100644
--- a/cogl/cogl-fence-private.h
+++ b/cogl/cogl-fence-private.h
@@ -25,11 +25,9 @@
 #define __COGL_FENCE_PRIVATE_H__
 
 #include "cogl-fence.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 #include "cogl-winsys-private.h"
 
-COGL_TAILQ_HEAD (CoglFenceList, CoglFenceClosure);
-
 typedef enum
 {
   FENCE_TYPE_PENDING,
@@ -42,7 +40,7 @@ typedef enum
 
 struct _CoglFenceClosure
 {
-  COGL_TAILQ_ENTRY (CoglFenceClosure) list;
+  CoglList link;
   CoglFramebuffer *framebuffer;
 
   CoglFenceType type;
diff --git a/cogl/cogl-fence.c b/cogl/cogl-fence.c
index 2055ac4..77469d7 100644
--- a/cogl/cogl-fence.c
+++ b/cogl/cogl-fence.c
@@ -73,9 +73,9 @@ static void
 _cogl_fence_poll_dispatch (void *source, int revents)
 {
   CoglContext *context = source;
-  CoglFenceClosure *fence, *next;
+  CoglFenceClosure *fence, *tmp;
 
-  COGL_TAILQ_FOREACH_SAFE (fence, &context->fences, list, next)
+  _cogl_list_for_each_safe (fence, tmp, &context->fences, link)
     _cogl_fence_check (fence);
 }
 
@@ -92,11 +92,11 @@ _cogl_fence_poll_prepare (void *source)
     {
       CoglFramebuffer *fb = l->data;
 
-      if (!COGL_TAILQ_EMPTY (&fb->journal->pending_fences))
+      if (!_cogl_list_empty (&fb->journal->pending_fences))
         _cogl_framebuffer_flush_journal (fb);
     }
 
-  if (!COGL_TAILQ_EMPTY (&context->fences))
+  if (!_cogl_list_empty (&context->fences))
     return FENCE_CHECK_TIMEOUT;
   else
     return -1;
@@ -134,7 +134,7 @@ _cogl_fence_submit (CoglFenceClosure *fence)
 #endif
 
  done:
-  COGL_TAILQ_INSERT_TAIL (&context->fences, fence, list);
+  _cogl_list_insert (context->fences.prev, &fence->link);
 
   if (!context->fences_poll_source)
     {
@@ -166,7 +166,7 @@ cogl_framebuffer_add_fence_callback (CoglFramebuffer *framebuffer,
 
   if (journal->entries->len)
     {
-      COGL_TAILQ_INSERT_TAIL (&journal->pending_fences, fence, list);
+      _cogl_list_insert (journal->pending_fences.prev, &fence->link);
       fence->type = FENCE_TYPE_PENDING;
     }
   else
@@ -179,16 +179,15 @@ void
 cogl_framebuffer_cancel_fence_callback (CoglFramebuffer *framebuffer,
                                         CoglFenceClosure *fence)
 {
-  CoglJournal *journal = framebuffer->journal;
   CoglContext *context = framebuffer->context;
 
   if (fence->type == FENCE_TYPE_PENDING)
     {
-      COGL_TAILQ_REMOVE (&journal->pending_fences, fence, list);
+      _cogl_list_remove (&fence->link);
     }
   else
     {
-      COGL_TAILQ_REMOVE (&context->fences, fence, list);
+      _cogl_list_remove (&fence->link);
 
       if (fence->type == FENCE_TYPE_WINSYS)
         {
@@ -212,15 +211,15 @@ _cogl_fence_cancel_fences_for_framebuffer (CoglFramebuffer *framebuffer)
 {
   CoglJournal *journal = framebuffer->journal;
   CoglContext *context = framebuffer->context;
-  CoglFenceClosure *fence, *next;
+  CoglFenceClosure *fence, *tmp;
 
-  while (!COGL_TAILQ_EMPTY (&journal->pending_fences))
+  while (!_cogl_list_empty (&journal->pending_fences))
     {
-      fence = COGL_TAILQ_FIRST (&journal->pending_fences);
+      fence = _cogl_container_of (journal->pending_fences.next, fence, link);
       cogl_framebuffer_cancel_fence_callback (framebuffer, fence);
     }
 
-  COGL_TAILQ_FOREACH_SAFE (fence, &context->fences, list, next)
+  _cogl_list_for_each_safe (fence, tmp, &context->fences, link)
     {
       if (fence->framebuffer == framebuffer)
         cogl_framebuffer_cancel_fence_callback (framebuffer, fence);
diff --git a/cogl/cogl-gles2-context-private.h b/cogl/cogl-gles2-context-private.h
index 5afb296..c9d4bcc 100644
--- a/cogl/cogl-gles2-context-private.h
+++ b/cogl/cogl-gles2-context-private.h
@@ -33,18 +33,14 @@
 
 #include "cogl-object-private.h"
 #include "cogl-framebuffer-private.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 
-typedef struct _CoglGLES2Offscreen CoglGLES2Offscreen;
-
-COGL_LIST_HEAD (CoglGLES2OffscreenList, CoglGLES2Offscreen);
-
-struct _CoglGLES2Offscreen
+typedef struct _CoglGLES2Offscreen
 {
-  COGL_LIST_ENTRY (CoglGLES2Offscreen) list_node;
+  CoglList link;
   CoglOffscreen *original_offscreen;
   CoglGLFramebuffer gl_framebuffer;
-};
+} CoglGLES2Offscreen;
 
 typedef struct
 {
@@ -143,7 +139,7 @@ struct _CoglGLES2Context
 
   GLuint current_fbo_handle;
 
-  CoglGLES2OffscreenList foreign_offscreens;
+  CoglList foreign_offscreens;
 
   CoglGLES2Vtable *vtable;
 
diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c
index 2d0ab52..4063fdc 100644
--- a/cogl/cogl-gles2-context.c
+++ b/cogl/cogl-gles2-context.c
@@ -1435,7 +1435,7 @@ gl_tex_image_2d_wrapper (GLenum target,
 static void
 _cogl_gles2_offscreen_free (CoglGLES2Offscreen *gles2_offscreen)
 {
-  COGL_LIST_REMOVE (gles2_offscreen, list_node);
+  _cogl_list_remove (&gles2_offscreen->link);
   g_slice_free (CoglGLES2Offscreen, gles2_offscreen);
 }
 
@@ -1513,10 +1513,12 @@ _cogl_gles2_context_free (CoglGLES2Context *gles2_context)
   winsys = ctx->display->renderer->winsys_vtable;
   winsys->destroy_gles2_context (gles2_context);
 
-  while (gles2_context->foreign_offscreens.lh_first)
+  while (!_cogl_list_empty (&gles2_context->foreign_offscreens))
     {
       CoglGLES2Offscreen *gles2_offscreen =
-        gles2_context->foreign_offscreens.lh_first;
+        _cogl_container_of (gles2_context->foreign_offscreens.next,
+                            gles2_offscreen,
+                            link);
 
       /* Note: this will also indirectly free the gles2_offscreen by
        * calling the destroy notify for the _user_data */
@@ -1572,7 +1574,7 @@ cogl_gles2_context_new (CoglContext *ctx, CoglError **error)
 
   gles2_ctx->context = ctx;
 
-  COGL_LIST_INIT (&gles2_ctx->foreign_offscreens);
+  _cogl_list_init (&gles2_ctx->foreign_offscreens);
 
   winsys = ctx->display->renderer->winsys_vtable;
   gles2_ctx->winsys = winsys->context_create_gles2_context (ctx, error);
@@ -1694,9 +1696,9 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
       return NULL;
     }
 
-  for (gles2_offscreen = gles2_context->foreign_offscreens.lh_first;
-       gles2_offscreen;
-       gles2_offscreen = gles2_offscreen->list_node.le_next)
+  _cogl_list_for_each (gles2_offscreen,
+                       &gles2_context->foreign_offscreens,
+                       link)
     {
       if (gles2_offscreen->original_offscreen == offscreen)
         return gles2_offscreen;
@@ -1740,9 +1742,8 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
 
   gles2_offscreen->original_offscreen = offscreen;
 
-  COGL_LIST_INSERT_HEAD (&gles2_context->foreign_offscreens,
-                         gles2_offscreen,
-                         list_node);
+  _cogl_list_insert (&gles2_context->foreign_offscreens,
+                     &gles2_offscreen->link);
 
   /* So we avoid building up an ever growing collection of ancillary
    * buffers for wrapped framebuffers, we make sure that the wrappers
diff --git a/cogl/cogl-journal-private.h b/cogl/cogl-journal-private.h
index b73fbd1..63cbc23 100644
--- a/cogl/cogl-journal-private.h
+++ b/cogl/cogl-journal-private.h
@@ -59,7 +59,7 @@ typedef struct _CoglJournal
 
   int fast_read_pixel_count;
 
-  CoglFenceList pending_fences;
+  CoglList pending_fences;
 
 } CoglJournal;
 
diff --git a/cogl/cogl-journal.c b/cogl/cogl-journal.c
index 518a797..703f162 100644
--- a/cogl/cogl-journal.c
+++ b/cogl/cogl-journal.c
@@ -153,7 +153,7 @@ _cogl_journal_new (CoglFramebuffer *framebuffer)
   journal->entries = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
   journal->vertices = g_array_new (FALSE, FALSE, sizeof (float));
 
-  COGL_TAILQ_INIT (&journal->pending_fences);
+  _cogl_list_init (&journal->pending_fences);
 
   return _cogl_journal_object_new (journal);
 }
@@ -1262,11 +1262,11 @@ _cogl_journal_all_entries_within_bounds (CoglJournal *journal,
 static void
 post_fences (CoglJournal *journal)
 {
-  CoglFenceClosure *fence, *next;
+  CoglFenceClosure *fence, *tmp;
 
-  COGL_TAILQ_FOREACH_SAFE (fence, &journal->pending_fences, list, next)
+  _cogl_list_for_each_safe (fence, tmp, &journal->pending_fences, link)
     {
-      COGL_TAILQ_REMOVE (&journal->pending_fences, fence, list);
+      _cogl_list_remove (&fence->link);
       _cogl_fence_submit (fence);
     }
 }
diff --git a/cogl/cogl-list.c b/cogl/cogl-list.c
new file mode 100644
index 0000000..3fbc675
--- /dev/null
+++ b/cogl/cogl-list.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright © 2008-2011 Kristian Høgsberg
+ * Copyright © 2011, 2012 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/* This list implementation is based on the Wayland source code */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "cogl-list.h"
+
+void
+_cogl_list_init (CoglList *list)
+{
+  list->prev = list;
+  list->next = list;
+}
+
+void
+_cogl_list_insert (CoglList *list, CoglList *elm)
+{
+  elm->prev = list;
+  elm->next = list->next;
+  list->next = elm;
+  elm->next->prev = elm;
+}
+
+void
+_cogl_list_remove (CoglList *elm)
+{
+  elm->prev->next = elm->next;
+  elm->next->prev = elm->prev;
+  elm->next = NULL;
+  elm->prev = NULL;
+}
+
+int
+_cogl_list_length (CoglList *list)
+{
+  CoglList *e;
+  int count;
+
+  count = 0;
+  e = list->next;
+  while (e != list)
+    {
+      e = e->next;
+      count++;
+    }
+
+  return count;
+}
+
+int
+_cogl_list_empty (CoglList *list)
+{
+  return list->next == list;
+}
+
+void
+_cogl_list_insert_list (CoglList *list,
+                        CoglList *other)
+{
+  if (_cogl_list_empty (other))
+    return;
+
+  other->next->prev = list;
+  other->prev->next = list->next;
+  list->next->prev = other->prev;
+  list->next = other->next;
+}
diff --git a/cogl/cogl-list.h b/cogl/cogl-list.h
new file mode 100644
index 0000000..7d716a8
--- /dev/null
+++ b/cogl/cogl-list.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2008 Kristian Høgsberg
+ * Copyright © 2012, 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/* This list implementation is based on the Wayland source code */
+
+#ifndef COGL_LIST_H
+#define COGL_LIST_H
+
+/**
+ * CoglList - linked list
+ *
+ * The list head is of "CoglList" type, and must be initialized
+ * using cogl_list_init().  All entries in the list must be of the same
+ * type.  The item type must have a "CoglList" member. This
+ * member will be initialized by cogl_list_insert(). There is no need to
+ * call cogl_list_init() on the individual item. To query if the list is
+ * empty in O(1), use cogl_list_empty().
+ *
+ * Let's call the list reference "CoglList foo_list", the item type as
+ * "item_t", and the item member as "CoglList link". The following code
+ *
+ * The following code will initialize a list:
+ *
+ *      cogl_list_init (foo_list);
+ *      cogl_list_insert (foo_list, item1);      Pushes item1 at the head
+ *      cogl_list_insert (foo_list, item2);      Pushes item2 at the head
+ *      cogl_list_insert (item2, item3);         Pushes item3 after item2
+ *
+ * The list now looks like [item2, item3, item1]
+ *
+ * Will iterate the list in ascending order:
+ *
+ *      item_t *item;
+ *      cogl_list_for_each(item, foo_list, link) {
+ *              Do_something_with_item(item);
+ *      }
+ */
+
+typedef struct _CoglList CoglList;
+
+struct _CoglList
+{
+  CoglList *prev;
+  CoglList *next;
+};
+
+void
+_cogl_list_init (CoglList *list);
+
+void
+_cogl_list_insert (CoglList *list,
+                   CoglList *elm);
+
+void
+_cogl_list_remove (CoglList *elm);
+
+int
+_cogl_list_length (CoglList *list);
+
+int
+_cogl_list_empty (CoglList *list);
+
+void
+_cogl_list_insert_list (CoglList *list,
+                        CoglList *other);
+
+#ifdef __GNUC__
+#define _cogl_container_of(ptr, sample, member)                         \
+  (__typeof__(sample))((char *)(ptr)    -                               \
+                       ((char *)&(sample)->member - (char *)(sample)))
+#else
+#define _cogl_container_of(ptr, sample, member)                 \
+  (void *)((char *)(ptr)        -                               \
+           ((char *)&(sample)->member - (char *)(sample)))
+#endif
+
+#define _cogl_list_for_each(pos, head, member)                          \
+  for (pos = 0, pos = _cogl_container_of((head)->next, pos, member);    \
+       &pos->member != (head);                                          \
+       pos = _cogl_container_of(pos->member.next, pos, member))
+
+#define _cogl_list_for_each_safe(pos, tmp, head, member)                \
+  for (pos = 0, tmp = 0,                                                \
+         pos = _cogl_container_of((head)->next, pos, member),           \
+         tmp = _cogl_container_of((pos)->member.next, tmp, member);     \
+       &pos->member != (head);                                          \
+       pos = tmp,                                                       \
+         tmp = _cogl_container_of(pos->member.next, tmp, member))
+
+#define _cogl_list_for_each_reverse(pos, head, member)                  \
+  for (pos = 0, pos = _cogl_container_of((head)->prev, pos, member);    \
+       &pos->member != (head);                                          \
+       pos = _cogl_container_of(pos->member.prev, pos, member))
+
+#define _cogl_list_for_each_reverse_safe(pos, tmp, head, member)        \
+  for (pos = 0, tmp = 0,                                                \
+         pos = _cogl_container_of((head)->prev, pos, member),           \
+         tmp = _cogl_container_of((pos)->member.prev, tmp, member);     \
+       &pos->member != (head);                                          \
+       pos = tmp,                                                       \
+         tmp = _cogl_container_of(pos->member.prev, tmp, member))
+
+#endif /* COGL_LIST_H */
diff --git a/cogl/cogl-memory-stack.c b/cogl/cogl-memory-stack.c
index 5f4547e..2aefcc9 100644
--- a/cogl/cogl-memory-stack.c
+++ b/cogl/cogl-memory-stack.c
@@ -53,26 +53,22 @@
 #endif
 
 #include "cogl-memory-stack-private.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 
 #include <stdint.h>
 
 #include <glib.h>
 
-typedef struct _CoglMemorySubStack CoglMemorySubStack;
-
-COGL_TAILQ_HEAD (CoglMemorySubStackList, CoglMemorySubStack);
-
-struct _CoglMemorySubStack
+typedef struct _CoglMemorySubStack
 {
-  COGL_TAILQ_ENTRY (CoglMemorySubStack) list_node;
+  CoglList link;
   size_t bytes;
   uint8_t *data;
-};
+} CoglMemorySubStack;
 
 struct _CoglMemoryStack
 {
-  CoglMemorySubStackList sub_stacks;
+  CoglList sub_stacks;
 
   CoglMemorySubStack *sub_stack;
   size_t sub_stack_offset;
@@ -93,7 +89,7 @@ _cogl_memory_stack_add_sub_stack (CoglMemoryStack *stack,
 {
   CoglMemorySubStack *sub_stack =
     _cogl_memory_sub_stack_alloc (sub_stack_bytes);
-  COGL_TAILQ_INSERT_TAIL (&stack->sub_stacks, sub_stack, list_node);
+  _cogl_list_insert (stack->sub_stacks.prev, &sub_stack->link);
   stack->sub_stack = sub_stack;
   stack->sub_stack_offset = 0;
 }
@@ -103,7 +99,7 @@ _cogl_memory_stack_new (size_t initial_size_bytes)
 {
   CoglMemoryStack *stack = g_slice_new0 (CoglMemoryStack);
 
-  COGL_TAILQ_INIT (&stack->sub_stacks);
+  _cogl_list_init (&stack->sub_stacks);
 
   _cogl_memory_stack_add_sub_stack (stack, initial_size_bytes);
 
@@ -128,9 +124,9 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
    * is made then we may need to skip over one or more of the
    * sub-stacks that are too small for the requested allocation
    * size... */
-  for (sub_stack = sub_stack->list_node.tqe_next;
-       sub_stack;
-       sub_stack = sub_stack->list_node.tqe_next)
+  for (sub_stack = _cogl_container_of (sub_stack->link.next, sub_stack, link);
+       &sub_stack->link != &stack->sub_stacks;
+       sub_stack = _cogl_container_of (sub_stack->link.next, sub_stack, link))
     {
       if (sub_stack->bytes >= bytes)
         {
@@ -147,11 +143,11 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
    * requested allocation if that's bigger.
    */
 
-  sub_stack = COGL_TAILQ_LAST (&stack->sub_stacks, CoglMemorySubStackList);
+  sub_stack = _cogl_container_of (stack->sub_stacks.prev, sub_stack, link);
 
   _cogl_memory_stack_add_sub_stack (stack, MAX (sub_stack->bytes, bytes) * 2);
 
-  sub_stack = COGL_TAILQ_LAST (&stack->sub_stacks, CoglMemorySubStackList);
+  sub_stack = _cogl_container_of (stack->sub_stacks.prev, sub_stack, link);
 
   stack->sub_stack_offset += bytes;
 
@@ -161,7 +157,9 @@ _cogl_memory_stack_alloc (CoglMemoryStack *stack, size_t bytes)
 void
 _cogl_memory_stack_rewind (CoglMemoryStack *stack)
 {
-  stack->sub_stack = COGL_TAILQ_FIRST (&stack->sub_stacks);
+  stack->sub_stack = _cogl_container_of (stack->sub_stacks.next,
+                                         stack->sub_stack,
+                                         link);
   stack->sub_stack_offset = 0;
 }
 
@@ -175,11 +173,12 @@ _cogl_memory_sub_stack_free (CoglMemorySubStack *sub_stack)
 void
 _cogl_memory_stack_free (CoglMemoryStack *stack)
 {
-  CoglMemorySubStack *sub_stack;
 
-  while ((sub_stack = COGL_TAILQ_FIRST (&stack->sub_stacks)))
+  while (!_cogl_list_empty (&stack->sub_stacks))
     {
-      COGL_TAILQ_REMOVE (&stack->sub_stacks, sub_stack, list_node);
+      CoglMemorySubStack *sub_stack =
+        _cogl_container_of (stack->sub_stacks.next, sub_stack, link);
+      _cogl_list_remove (&sub_stack->link);
       _cogl_memory_sub_stack_free (sub_stack);
     }
 
diff --git a/cogl/cogl-node-private.h b/cogl/cogl-node-private.h
index f1b505c..ee2246c 100644
--- a/cogl/cogl-node-private.h
+++ b/cogl/cogl-node-private.h
@@ -29,12 +29,10 @@
 #define __COGL_NODE_PRIVATE_H
 
 #include "cogl-object-private.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 
 typedef struct _CoglNode CoglNode;
 
-COGL_LIST_HEAD (CoglNodeList, CoglNode);
-
 /* Pipelines and layers represent their state in a tree structure where
  * some of the state relating to a given pipeline or layer may actually
  * be owned by one if is ancestors in the tree. We have a common data
@@ -49,10 +47,10 @@ struct _CoglNode
   CoglNode *parent;
 
   /* The list entry here contains pointers to the node's siblings */
-  COGL_LIST_ENTRY (CoglNode) list_node;
+  CoglList link;
 
   /* List of children */
-  CoglNodeList children;
+  CoglList children;
 
   /* TRUE if the node took a strong reference on its parent. Weak
    * pipelines for instance don't take a reference on their parent. */
diff --git a/cogl/cogl-node.c b/cogl/cogl-node.c
index ab32e28..88bf991 100644
--- a/cogl/cogl-node.c
+++ b/cogl/cogl-node.c
@@ -36,7 +36,7 @@ void
 _cogl_pipeline_node_init (CoglNode *node)
 {
   node->parent = NULL;
-  COGL_LIST_INIT (&node->children);
+  _cogl_list_init (&node->children);
 }
 
 void
@@ -59,7 +59,7 @@ _cogl_pipeline_node_set_parent_real (CoglNode *node,
   if (node->parent)
     unparent (node);
 
-  COGL_LIST_INSERT_HEAD (&parent->children, node, list_node);
+  _cogl_list_insert (&parent->children, &node->link);
 
   node->parent = parent;
   node->has_parent_reference = take_strong_reference;
@@ -80,9 +80,9 @@ _cogl_pipeline_node_unparent_real (CoglNode *node)
   if (parent == NULL)
     return;
 
-  _COGL_RETURN_IF_FAIL (!COGL_LIST_EMPTY (&parent->children));
+  _COGL_RETURN_IF_FAIL (!_cogl_list_empty (&parent->children));
 
-  COGL_LIST_REMOVE (node, list_node);
+  _cogl_list_remove (&node->link);
 
   if (node->has_parent_reference)
     cogl_object_unref (parent);
@@ -97,7 +97,7 @@ _cogl_pipeline_node_foreach_child (CoglNode *node,
 {
   CoglNode *child, *next;
 
-  COGL_LIST_FOREACH_SAFE (child, &node->children, list_node, next)
+  _cogl_list_for_each_safe (child, next, &node->children, link)
     callback (child, user_data);
 }
 
diff --git a/cogl/cogl-onscreen-private.h b/cogl/cogl-onscreen-private.h
index e960dc3..1fd62ea 100644
--- a/cogl/cogl-onscreen-private.h
+++ b/cogl/cogl-onscreen-private.h
@@ -26,8 +26,8 @@
 
 #include "cogl-onscreen.h"
 #include "cogl-framebuffer-private.h"
-#include "cogl-queue.h"
 #include "cogl-closure-list-private.h"
+#include "cogl-list.h"
 
 #include <glib.h>
 
@@ -35,30 +35,22 @@
 #include <windows.h>
 #endif
 
-typedef struct _CoglOnscreenEvent CoglOnscreenEvent;
-
-COGL_TAILQ_HEAD (CoglOnscreenEventList, CoglOnscreenEvent);
-
-struct _CoglOnscreenEvent
+typedef struct _CoglOnscreenEvent
 {
-  COGL_TAILQ_ENTRY (CoglOnscreenEvent) list_node;
+  CoglList link;
 
   CoglOnscreen *onscreen;
   CoglFrameInfo *info;
   CoglFrameEvent type;
-};
+} CoglOnscreenEvent;
 
-typedef struct _CoglOnscreenQueuedDirty CoglOnscreenQueuedDirty;
-
-COGL_TAILQ_HEAD (CoglOnscreenQueuedDirtyList, CoglOnscreenQueuedDirty);
-
-struct _CoglOnscreenQueuedDirty
+typedef struct _CoglOnscreenQueuedDirty
 {
-  COGL_TAILQ_ENTRY (CoglOnscreenQueuedDirty) list_node;
+  CoglList link;
 
   CoglOnscreen *onscreen;
   CoglOnscreenDirtyInfo info;
-};
+} CoglOnscreenQueuedDirty;
 
 struct _CoglOnscreen
 {
@@ -80,12 +72,12 @@ struct _CoglOnscreen
 
   CoglBool swap_throttled;
 
-  CoglClosureList frame_closures;
+  CoglList frame_closures;
 
   CoglBool resizable;
-  CoglClosureList resize_closures;
+  CoglList resize_closures;
 
-  CoglClosureList dirty_closures;
+  CoglList dirty_closures;
 
   int64_t frame_counter;
   int64_t swap_frame_counter; /* frame counter at last all to
diff --git a/cogl/cogl-onscreen.c b/cogl/cogl-onscreen.c
index f686b14..c115a6e 100644
--- a/cogl/cogl-onscreen.c
+++ b/cogl/cogl-onscreen.c
@@ -47,9 +47,9 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
 
-  COGL_LIST_INIT (&onscreen->frame_closures);
-  COGL_LIST_INIT (&onscreen->resize_closures);
-  COGL_LIST_INIT (&onscreen->dirty_closures);
+  _cogl_list_init (&onscreen->frame_closures);
+  _cogl_list_init (&onscreen->resize_closures);
+  _cogl_list_init (&onscreen->dirty_closures);
 
   framebuffer->config = onscreen_template->config;
   cogl_object_ref (framebuffer->config.swap_chain);
@@ -122,23 +122,20 @@ static void
 _cogl_dispatch_onscreen_cb (CoglContext *context)
 {
   CoglOnscreenEvent *event, *tmp;
-  CoglOnscreenEventList queue;
+  CoglList queue;
 
   /* Dispatching the event callback may cause another frame to be
    * drawn which in may cause another event to be queued immediately.
    * To make sure this loop will only dispatch one set of events we'll
    * steal the queue and iterate that separately */
-  COGL_TAILQ_INIT (&queue);
-  COGL_TAILQ_CONCAT (&queue, &context->onscreen_events_queue, list_node);
-  COGL_TAILQ_INIT (&context->onscreen_events_queue);
+  _cogl_list_init (&queue);
+  _cogl_list_insert_list (&queue, &context->onscreen_events_queue);
+  _cogl_list_init (&context->onscreen_events_queue);
 
   _cogl_closure_disconnect (context->onscreen_dispatch_idle);
   context->onscreen_dispatch_idle = NULL;
 
-  COGL_TAILQ_FOREACH_SAFE (event,
-                           &queue,
-                           list_node,
-                           tmp)
+  _cogl_list_for_each_safe (event, tmp, &queue, link)
     {
       CoglOnscreen *onscreen = event->onscreen;
       CoglFrameInfo *info = event->info;
@@ -151,12 +148,12 @@ _cogl_dispatch_onscreen_cb (CoglContext *context)
       g_slice_free (CoglOnscreenEvent, event);
     }
 
-  while (!COGL_TAILQ_EMPTY (&context->onscreen_dirty_queue))
+  while (!_cogl_list_empty (&context->onscreen_dirty_queue))
     {
       CoglOnscreenQueuedDirty *qe =
-        COGL_TAILQ_FIRST (&context->onscreen_dirty_queue);
+        _cogl_container_of (context->onscreen_dirty_queue.next, qe, link);
 
-      COGL_TAILQ_REMOVE (&context->onscreen_dirty_queue, qe, list_node);
+      _cogl_list_remove (&qe->link);
 
       _cogl_closure_list_invoke (&qe->onscreen->dirty_closures,
                                  CoglOnscreenDirtyCallback,
@@ -194,7 +191,7 @@ _cogl_onscreen_queue_dirty (CoglOnscreen *onscreen,
 
   qe->onscreen = cogl_object_ref (onscreen);
   qe->info = *info;
-  COGL_TAILQ_INSERT_TAIL (&ctx->onscreen_dirty_queue, qe, list_node);
+  _cogl_list_insert (ctx->onscreen_dirty_queue.prev, &qe->link);
 
   _cogl_onscreen_queue_dispatch_idle (onscreen);
 }
@@ -226,7 +223,7 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
   event->info = cogl_object_ref (info);
   event->type = type;
 
-  COGL_TAILQ_INSERT_TAIL (&ctx->onscreen_events_queue, event, list_node);
+  _cogl_list_insert (ctx->onscreen_events_queue.prev, &event->link);
 
   _cogl_onscreen_queue_dispatch_idle (onscreen);
 }
diff --git a/cogl/cogl-pipeline-layer.c b/cogl/cogl-pipeline-layer.c
index bb77f6b..a401773 100644
--- a/cogl/cogl-pipeline-layer.c
+++ b/cogl/cogl-pipeline-layer.c
@@ -346,7 +346,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
 
   /* Identify the case where the layer is new with no owner or
    * dependants and so we don't need to do anything. */
-  if (COGL_LIST_EMPTY (&COGL_NODE (layer)->children) &&
+  if (_cogl_list_empty (&COGL_NODE (layer)->children) &&
       layer->owner == NULL)
     goto init_layer_state;
 
@@ -368,7 +368,7 @@ _cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
    * they have dependants - either direct children, or another
    * pipeline as an owner.
    */
-  if (!COGL_LIST_EMPTY (&COGL_NODE (layer)->children) ||
+  if (!_cogl_list_empty (&COGL_NODE (layer)->children) ||
       layer->owner != required_owner)
     {
       CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index a185b3c..72917de 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -34,7 +34,7 @@
 #include "cogl-matrix.h"
 #include "cogl-object-private.h"
 #include "cogl-profile.h"
-#include "cogl-queue.h"
+#include "cogl-list.h"
 #include "cogl-boxed-value.h"
 #include "cogl-pipeline-snippet-private.h"
 #include "cogl-pipeline-state.h"
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index b9264ed..19a8a19 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -431,7 +431,7 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
                                      destroy_weak_children_cb,
                                      NULL);
 
-  g_assert (COGL_LIST_EMPTY (&COGL_NODE (pipeline)->children));
+  g_assert (_cogl_list_empty (&COGL_NODE (pipeline)->children));
 
   _cogl_pipeline_unparent (COGL_NODE (pipeline));
 
@@ -1212,7 +1212,7 @@ _cogl_pipeline_pre_change_notify (CoglPipeline     *pipeline,
   /* If there are still children remaining though we'll need to
    * perform a copy-on-write and reparent the dependants as children
    * of the copy. */
-  if (!COGL_LIST_EMPTY (&COGL_NODE (pipeline)->children))
+  if (!_cogl_list_empty (&COGL_NODE (pipeline)->children))
     {
       CoglPipeline *new_authority;
 
diff --git a/cogl/cogl-poll.c b/cogl/cogl-poll.c
index e29d997..c50d648 100644
--- a/cogl/cogl-poll.c
+++ b/cogl/cogl-poll.c
@@ -57,7 +57,7 @@ cogl_poll_renderer_get_info (CoglRenderer *renderer,
   *n_poll_fds = renderer->poll_fds->len;
   *timeout = -1;
 
-  if (!COGL_LIST_EMPTY (&renderer->idle_closures))
+  if (!_cogl_list_empty (&renderer->idle_closures))
     {
       *timeout = 0;
       return renderer->poll_fds_age;
diff --git a/cogl/cogl-queue.h b/cogl/cogl-queue.h
deleted file mode 100644
index 7020ae0..0000000
--- a/cogl/cogl-queue.h
+++ /dev/null
@@ -1,647 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- *      The Regents of the University of California.  All rights reserved.
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *      @(#)queue.h     8.5 (Berkeley) 8/20/94
- * $FreeBSD$
- */
-
-#ifndef _COGL_QUEUE_H_
-#define _COGL_QUEUE_H_
-
-/*
- * This file defines four types of data structures: singly-linked lists,
- * singly-linked tail queues, lists and tail queues.
- *
- * A singly-linked list is headed by a single forward pointer. The elements
- * are singly linked for minimum space and pointer manipulation overhead at
- * the expense of O(n) removal for arbitrary elements. New elements can be
- * added to the list after an existing element or at the head of the list.
- * Elements being removed from the head of the list should use the explicit
- * macro for this purpose for optimum efficiency. A singly-linked list may
- * only be traversed in the forward direction.  Singly-linked lists are ideal
- * for applications with large datasets and few or no removals or for
- * implementing a LIFO queue.
- *
- * A singly-linked tail queue is headed by a pair of pointers, one to the
- * head of the list and the other to the tail of the list. The elements are
- * singly linked for minimum space and pointer manipulation overhead at the
- * expense of O(n) removal for arbitrary elements. New elements can be added
- * to the list after an existing element, at the head of the list, or at the
- * end of the list. Elements being removed from the head of the tail queue
- * should use the explicit macro for this purpose for optimum efficiency.
- * A singly-linked tail queue may only be traversed in the forward direction.
- * Singly-linked tail queues are ideal for applications with large datasets
- * and few or no removals or for implementing a FIFO queue.
- *
- * A list is headed by a single forward pointer (or an array of forward
- * pointers for a hash table header). The elements are doubly linked
- * so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before
- * or after an existing element or at the head of the list. A list
- * may only be traversed in the forward direction.
- *
- * A tail queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or
- * after an existing element, at the head of the list, or at the end of
- * the list. A tail queue may be traversed in either direction.
- *
- * For details on the use of these macros, see the queue(3) manual page.
- *
- *
- *                              SLIST   LIST    STAILQ  TAILQ
- * _HEAD                        +       +       +       +
- * _HEAD_INITIALIZER            +       +       +       +
- * _ENTRY                       +       +       +       +
- * _INIT                        +       +       +       +
- * _EMPTY                       +       +       +       +
- * _FIRST                       +       +       +       +
- * _NEXT                        +       +       +       +
- * _PREV                        -       -       -       +
- * _LAST                        -       -       +       +
- * _FOREACH                     +       +       +       +
- * _FOREACH_SAFE                +       +       +       +
- * _FOREACH_REVERSE             -       -       -       +
- * _FOREACH_REVERSE_SAFE        -       -       -       +
- * _INSERT_HEAD                 +       +       +       +
- * _INSERT_BEFORE               -       +       -       +
- * _INSERT_AFTER                +       +       +       +
- * _INSERT_TAIL                 -       -       +       +
- * _CONCAT                      -       -       +       +
- * _REMOVE_AFTER                +       -       +       -
- * _REMOVE_HEAD                 +       -       +       -
- * _REMOVE                      +       +       +       +
- * _SWAP                        +       +       +       +
- *
- */
-#ifdef COGL_QUEUE_MACRO_DEBUG
-/* Store the last 2 places the queue element or head was altered */
-struct cogl_qm_trace {
-        char * lastfile;
-        int lastline;
-        char * prevfile;
-        int prevline;
-};
-
-#define COGL_TRACEBUF struct cogl_qm_trace trace;
-#define COGL_TRASHIT(x) do {(x) = (void *)-1;} while (0)
-#define COGL_QMD_SAVELINK(name, link) void **name = (void *)&(link)
-
-#define COGL_QMD_TRACE_HEAD(head) do {                                  \
-        (head)->trace.prevline = (head)->trace.lastline;                \
-        (head)->trace.prevfile = (head)->trace.lastfile;                \
-        (head)->trace.lastline = __LINE__;                              \
-        (head)->trace.lastfile = __FILE__;                              \
-} while (0)
-
-#define COGL_QMD_TRACE_ELEM(elem) do {                                  \
-        (elem)->trace.prevline = (elem)->trace.lastline;                \
-        (elem)->trace.prevfile = (elem)->trace.lastfile;                \
-        (elem)->trace.lastline = __LINE__;                              \
-        (elem)->trace.lastfile = __FILE__;                              \
-} while (0)
-
-#else
-#define COGL_QMD_TRACE_ELEM(elem)
-#define COGL_QMD_TRACE_HEAD(head)
-#define COGL_QMD_SAVELINK(name, link)
-#define COGL_TRACEBUF
-#define COGL_TRASHIT(x)
-#endif  /* COGL_QUEUE_MACRO_DEBUG */
-
-/*
- * Singly-linked List declarations.
- */
-#define COGL_SLIST_HEAD(name, type)                                     \
-typedef struct _ ## name {                                              \
-  type *slh_first; /* first element */                                  \
-} name
-
-#define COGL_SLIST_HEAD_INITIALIZER(head)                               \
-        { NULL }
-
-#define COGL_SLIST_ENTRY(type)                                          \
-struct {                                                                \
-  type *sle_next;  /* next element */                                   \
-}
-
-/*
- * Singly-linked List functions.
- */
-#define COGL_SLIST_EMPTY(head)  ((head)->slh_first == NULL)
-
-#define COGL_SLIST_FIRST(head)  ((head)->slh_first)
-
-#define COGL_SLIST_FOREACH(var, head, field)                            \
-        for ((var) = COGL_SLIST_FIRST((head));                          \
-            (var);                                                      \
-            (var) = COGL_SLIST_NEXT((var), field))
-
-#define COGL_SLIST_FOREACH_SAFE(var, head, field, tvar)                 \
-        for ((var) = COGL_SLIST_FIRST((head));                          \
-            (var) && ((tvar) = COGL_SLIST_NEXT((var), field), 1);       \
-            (var) = (tvar))
-
-#define COGL_SLIST_FOREACH_PREVPTR(var, varp, head, field)              \
-        for ((varp) = &COGL_SLIST_FIRST((head));                        \
-            ((var) = *(varp)) != NULL;                                  \
-            (varp) = &COGL_SLIST_NEXT((var), field))
-
-#define COGL_SLIST_INIT(head) do {                                      \
-        COGL_SLIST_FIRST((head)) = NULL;                                \
-} while (0)
-
-#define COGL_SLIST_INSERT_AFTER(slistelm, elm, field) do {              \
-        COGL_SLIST_NEXT((elm), field) = COGL_SLIST_NEXT((slistelm), field);  \
-        COGL_SLIST_NEXT((slistelm), field) = (elm);                     \
-} while (0)
-
-#define COGL_SLIST_INSERT_HEAD(head, elm, field) do {                   \
-        COGL_SLIST_NEXT((elm), field) = COGL_SLIST_FIRST((head));       \
-        COGL_SLIST_FIRST((head)) = (elm);                               \
-} while (0)
-
-#define COGL_SLIST_NEXT(elm, field)  ((elm)->field.sle_next)
-
-#define COGL_SLIST_REMOVE(head, elm, type, field) do {                  \
-        COGL_QMD_SAVELINK(oldnext, (elm)->field.sle_next);              \
-        if (COGL_SLIST_FIRST((head)) == (elm)) {                        \
-                COGL_SLIST_REMOVE_HEAD((head), field);                  \
-        }                                                               \
-        else {                                                          \
-                type *curelm = COGL_SLIST_FIRST((head));                \
-                while (COGL_SLIST_NEXT(curelm, field) != (elm))         \
-                        curelm = COGL_SLIST_NEXT(curelm, field);        \
-                COGL_SLIST_REMOVE_AFTER(curelm, field);                 \
-        }                                                               \
-        COGL_TRASHIT(*oldnext);                                         \
-} while (0)
-
-#define COGL_SLIST_REMOVE_AFTER(elm, field) do {                        \
-        COGL_SLIST_NEXT(elm, field) =                                   \
-            COGL_SLIST_NEXT(COGL_SLIST_NEXT(elm, field), field);        \
-} while (0)
-
-#define COGL_SLIST_REMOVE_HEAD(head, field) do {                        \
-    COGL_SLIST_FIRST((head)) =                                          \
-      COGL_SLIST_NEXT(COGL_SLIST_FIRST((head)), field);                 \
-} while (0)
-
-#define COGL_SLIST_SWAP(head1, head2, type) do {                        \
-        type *swap_first = COGL_SLIST_FIRST(head1);                     \
-        COGL_SLIST_FIRST(head1) = COGL_SLIST_FIRST(head2);              \
-        COGL_SLIST_FIRST(head2) = swap_first;                           \
-} while (0)
-
-/*
- * Singly-linked Tail queue declarations.
- */
-#define COGL_STAILQ_HEAD(name, type)                                    \
-typedef struct _ ## name {                                              \
-        type *stqh_first;/* first element */                            \
-        type **stqh_last;/* addr of last next element */                \
-} name
-
-#define COGL_STAILQ_HEAD_INITIALIZER(head)                              \
-        { NULL, &(head).stqh_first }
-
-#define COGL_STAILQ_ENTRY(type)                                         \
-struct {                                                                \
-        type *stqe_next; /* next element */                             \
-}
-
-/*
- * Singly-linked Tail queue functions.
- */
-#define COGL_STAILQ_CONCAT(head1, head2) do {                           \
-        if (!COGL_STAILQ_EMPTY((head2))) {                              \
-                *(head1)->stqh_last = (head2)->stqh_first;              \
-                (head1)->stqh_last = (head2)->stqh_last;                \
-                COGL_STAILQ_INIT((head2));                              \
-        }                                                               \
-} while (0)
-
-#define COGL_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
-
-#define COGL_STAILQ_FIRST(head) ((head)->stqh_first)
-
-#define COGL_STAILQ_FOREACH(var, head, field)                           \
-        for((var) = COGL_STAILQ_FIRST((head));                          \
-           (var);                                                       \
-           (var) = COGL_STAILQ_NEXT((var), field))
-
-
-#define COGL_STAILQ_FOREACH_SAFE(var, head, field, tvar)                \
-        for ((var) = COGL_STAILQ_FIRST((head));                         \
-            (var) && ((tvar) = COGL_STAILQ_NEXT((var), field), 1);      \
-            (var) = (tvar))
-
-#define COGL_STAILQ_INIT(head) do {                                     \
-        COGL_STAILQ_FIRST((head)) = NULL;                               \
-        (head)->stqh_last = &COGL_STAILQ_FIRST((head));                 \
-} while (0)
-
-#define COGL_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {          \
-    if ((COGL_STAILQ_NEXT((elm), field) =                               \
-         COGL_STAILQ_NEXT((tqelm), field)) == NULL)                     \
-      (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field);              \
-    COGL_STAILQ_NEXT((tqelm), field) = (elm);                           \
-} while (0)
-
-#define COGL_STAILQ_INSERT_HEAD(head, elm, field) do {                  \
-    if ((COGL_STAILQ_NEXT((elm), field) =                               \
-         COGL_STAILQ_FIRST((head))) == NULL)                            \
-      (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field);              \
-    COGL_STAILQ_FIRST((head)) = (elm);                                  \
-  } while (0)
-
-#define COGL_STAILQ_INSERT_TAIL(head, elm, field) do {                  \
-        COGL_STAILQ_NEXT((elm), field) = NULL;                          \
-        *(head)->stqh_last = (elm);                                     \
-        (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field);            \
-} while (0)
-
-#define COGL_STAILQ_LAST(head, type, field)                             \
-        (COGL_STAILQ_EMPTY((head)) ?                                    \
-                NULL :                                                  \
-                ((type *)(void *)                                       \
-                 ((char *)((head)->stqh_last) -                         \
-                  __offsetof(struct type, field))))
-
-#define COGL_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
-
-#define COGL_STAILQ_REMOVE(head, elm, type, field) do {                 \
-        COGL_QMD_SAVELINK(oldnext, (elm)->field.stqe_next);             \
-        if (COGL_STAILQ_FIRST((head)) == (elm)) {                       \
-                COGL_STAILQ_REMOVE_HEAD((head), field);                 \
-        }                                                               \
-        else {                                                          \
-                type *curelm = COGL_STAILQ_FIRST((head));               \
-                while (COGL_STAILQ_NEXT(curelm, field) != (elm))        \
-                        curelm = COGL_STAILQ_NEXT(curelm, field);       \
-                COGL_STAILQ_REMOVE_AFTER(head, curelm, field);          \
-        }                                                               \
-        COGL_TRASHIT(*oldnext);                                         \
-} while (0)
-
-#define COGL_STAILQ_REMOVE_AFTER(head, elm, field) do {                 \
-        if ((COGL_STAILQ_NEXT(elm, field) =                             \
-             COGL_STAILQ_NEXT(COGL_STAILQ_NEXT(elm, field),             \
-                              field)) == NULL)                          \
-                (head)->stqh_last = &COGL_STAILQ_NEXT((elm), field);    \
-} while (0)
-
-#define COGL_STAILQ_REMOVE_HEAD(head, field) do {                       \
-        if ((COGL_STAILQ_FIRST((head)) =                                \
-             COGL_STAILQ_NEXT(COGL_STAILQ_FIRST((head)), field)) == NULL) \
-                (head)->stqh_last = &COGL_STAILQ_FIRST((head));         \
-} while (0)
-
-#define COGL_STAILQ_SWAP(head1, head2, type) do {                       \
-        type *swap_first = COGL_STAILQ_FIRST(head1);                    \
-        type **swap_last = (head1)->stqh_last;                          \
-        COGL_STAILQ_FIRST(head1) = COGL_STAILQ_FIRST(head2);            \
-        (head1)->stqh_last = (head2)->stqh_last;                        \
-        COGL_STAILQ_FIRST(head2) = swap_first;                          \
-        (head2)->stqh_last = swap_last;                                 \
-        if (COGL_STAILQ_EMPTY(head1))                                   \
-                (head1)->stqh_last = &COGL_STAILQ_FIRST(head1);         \
-        if (COGL_STAILQ_EMPTY(head2))                                   \
-                (head2)->stqh_last = &COGL_STAILQ_FIRST(head2);         \
-} while (0)
-
-
-/*
- * List declarations.
- */
-#define COGL_LIST_HEAD(name, type)                                      \
-typedef struct _ ## name {                                              \
-        type *lh_first;  /* first element */                            \
-} name
-
-#define COGL_LIST_HEAD_INITIALIZER(head)                                \
-        { NULL }
-
-#define COGL_LIST_ENTRY(type)                                           \
-struct {                                                                \
-        type *le_next;   /* next element */                             \
-        type **le_prev;  /* address of previous next element */         \
-}
-
-/*
- * List functions.
- */
-
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define COGL_QMD_LIST_CHECK_HEAD(head, field) do {                      \
-        if (COGL_LIST_FIRST((head)) != NULL &&                          \
-            COGL_LIST_FIRST((head))->field.le_prev !=                   \
-             &COGL_LIST_FIRST((head)))                                  \
-                panic("Bad list head %p first->prev != head", (head));  \
-} while (0)
-
-#define COGL_QMD_LIST_CHECK_NEXT(elm, field) do {                       \
-        if (COGL_LIST_NEXT((elm), field) != NULL &&                     \
-            COGL_LIST_NEXT((elm), field)->field.le_prev !=              \
-             &((elm)->field.le_next))                                   \
-                panic("Bad link elm %p next->prev != elm", (elm));      \
-} while (0)
-
-#define COGL_QMD_LIST_CHECK_PREV(elm, field) do {                       \
-        if (*(elm)->field.le_prev != (elm))                             \
-                panic("Bad link elm %p prev->next != elm", (elm));      \
-} while (0)
-#else
-#define COGL_QMD_LIST_CHECK_HEAD(head, field)
-#define COGL_QMD_LIST_CHECK_NEXT(elm, field)
-#define COGL_QMD_LIST_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define COGL_LIST_EMPTY(head)   ((head)->lh_first == NULL)
-
-#define COGL_LIST_FIRST(head)   ((head)->lh_first)
-
-#define COGL_LIST_FOREACH(var, head, field)                             \
-        for ((var) = COGL_LIST_FIRST((head));                           \
-            (var);                                                      \
-            (var) = COGL_LIST_NEXT((var), field))
-
-#define COGL_LIST_FOREACH_SAFE(var, head, field, tvar)                  \
-        for ((var) = COGL_LIST_FIRST((head));                           \
-            (var) && ((tvar) = COGL_LIST_NEXT((var), field), 1);        \
-            (var) = (tvar))
-
-#define COGL_LIST_INIT(head) do {                                       \
-        COGL_LIST_FIRST((head)) = NULL;                                 \
-} while (0)
-
-#define COGL_LIST_INSERT_AFTER(listelm, elm, field) do {                \
-        COGL_QMD_LIST_CHECK_NEXT(listelm, field);                       \
-        if ((COGL_LIST_NEXT((elm), field) =                             \
-             COGL_LIST_NEXT((listelm), field)) != NULL)                 \
-                COGL_LIST_NEXT((listelm), field)->field.le_prev =       \
-                    &COGL_LIST_NEXT((elm), field);                      \
-        COGL_LIST_NEXT((listelm), field) = (elm);                       \
-        (elm)->field.le_prev = &COGL_LIST_NEXT((listelm), field);       \
-} while (0)
-
-#define COGL_LIST_INSERT_BEFORE(listelm, elm, field) do {               \
-        COGL_QMD_LIST_CHECK_PREV(listelm, field);                       \
-        (elm)->field.le_prev = (listelm)->field.le_prev;                \
-        COGL_LIST_NEXT((elm), field) = (listelm);                       \
-        *(listelm)->field.le_prev = (elm);                              \
-        (listelm)->field.le_prev = &COGL_LIST_NEXT((elm), field);       \
-} while (0)
-
-#define COGL_LIST_INSERT_HEAD(head, elm, field) do {                    \
-        COGL_QMD_LIST_CHECK_HEAD((head), field);                        \
-        if ((COGL_LIST_NEXT((elm), field) =                             \
-             COGL_LIST_FIRST((head))) != NULL)                          \
-          COGL_LIST_FIRST((head))->field.le_prev =                      \
-            &COGL_LIST_NEXT((elm), field);                              \
-        COGL_LIST_FIRST((head)) = (elm);                                \
-        (elm)->field.le_prev = &COGL_LIST_FIRST((head));                \
-} while (0)
-
-#define COGL_LIST_NEXT(elm, field)   ((elm)->field.le_next)
-
-#define COGL_LIST_REMOVE(elm, field) do {                               \
-        COGL_QMD_SAVELINK(oldnext, (elm)->field.le_next);               \
-        COGL_QMD_SAVELINK(oldprev, (elm)->field.le_prev);               \
-        COGL_QMD_LIST_CHECK_NEXT(elm, field);                           \
-        COGL_QMD_LIST_CHECK_PREV(elm, field);                           \
-        if (COGL_LIST_NEXT((elm), field) != NULL)                       \
-                COGL_LIST_NEXT((elm), field)->field.le_prev =           \
-                    (elm)->field.le_prev;                               \
-        *(elm)->field.le_prev = COGL_LIST_NEXT((elm), field);           \
-        COGL_TRASHIT(*oldnext);                                         \
-        COGL_TRASHIT(*oldprev);                                         \
-} while (0)
-
-#define COGL_LIST_SWAP(head1, head2, type, field) do {                  \
-        type *swap_tmp = COGL_LIST_FIRST((head1));                      \
-        COGL_LIST_FIRST((head1)) = COGL_LIST_FIRST((head2));            \
-        COGL_LIST_FIRST((head2)) = swap_tmp;                            \
-        if ((swap_tmp = COGL_LIST_FIRST((head1))) != NULL)              \
-                swap_tmp->field.le_prev = &COGL_LIST_FIRST((head1));    \
-        if ((swap_tmp = COGL_LIST_FIRST((head2))) != NULL)              \
-                swap_tmp->field.le_prev = &COGL_LIST_FIRST((head2));    \
-} while (0)
-
-/*
- * Tail queue declarations.
- */
-#define COGL_TAILQ_HEAD(name, type)                                     \
-typedef struct _ ## name {                                              \
-        type *tqh_first; /* first element */                            \
-        type **tqh_last; /* addr of last next element */                \
-        COGL_TRACEBUF                                                   \
-} name
-
-#define COGL_TAILQ_HEAD_INITIALIZER(head)                               \
-        { NULL, &(head).tqh_first }
-
-#define COGL_TAILQ_ENTRY(type)                                          \
-struct {                                                                \
-        type *tqe_next;  /* next element */                             \
-        type **tqe_prev; /* address of previous next element */         \
-        COGL_TRACEBUF                                                   \
-}
-
-/*
- * Tail queue functions.
- */
-#if (defined(_KERNEL) && defined(INVARIANTS))
-#define COGL_QMD_TAILQ_CHECK_HEAD(head, field) do {                     \
-        if (!COGL_TAILQ_EMPTY(head) &&                                  \
-            COGL_TAILQ_FIRST((head))->field.tqe_prev !=                 \
-             &COGL_TAILQ_FIRST((head)))                                 \
-                panic("Bad tailq head %p first->prev != head", (head)); \
-} while (0)
-
-#define COGL_QMD_TAILQ_CHECK_TAIL(head, field) do {                     \
-        if (*(head)->tqh_last != NULL)                                  \
-                panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head));  \
-} while (0)
-
-#define COGL_QMD_TAILQ_CHECK_NEXT(elm, field) do {                      \
-        if (COGL_TAILQ_NEXT((elm), field) != NULL &&                    \
-            COGL_TAILQ_NEXT((elm), field)->field.tqe_prev !=            \
-             &((elm)->field.tqe_next))                                  \
-                panic("Bad link elm %p next->prev != elm", (elm));      \
-} while (0)
-
-#define COGL_QMD_TAILQ_CHECK_PREV(elm, field) do {                      \
-        if (*(elm)->field.tqe_prev != (elm))                            \
-                panic("Bad link elm %p prev->next != elm", (elm));      \
-} while (0)
-#else
-#define COGL_QMD_TAILQ_CHECK_HEAD(head, field)
-#define COGL_QMD_TAILQ_CHECK_TAIL(head, headname)
-#define COGL_QMD_TAILQ_CHECK_NEXT(elm, field)
-#define COGL_QMD_TAILQ_CHECK_PREV(elm, field)
-#endif /* (_KERNEL && INVARIANTS) */
-
-#define COGL_TAILQ_CONCAT(head1, head2, field) do {                     \
-        if (!COGL_TAILQ_EMPTY(head2)) {                                 \
-                *(head1)->tqh_last = (head2)->tqh_first;                \
-                (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
-                (head1)->tqh_last = (head2)->tqh_last;                  \
-                COGL_TAILQ_INIT((head2));                               \
-                COGL_QMD_TRACE_HEAD(head1);                             \
-                COGL_QMD_TRACE_HEAD(head2);                             \
-        }                                                               \
-} while (0)
-
-#define COGL_TAILQ_EMPTY(head)  ((head)->tqh_first == NULL)
-
-#define COGL_TAILQ_FIRST(head)  ((head)->tqh_first)
-
-#define COGL_TAILQ_FOREACH(var, head, field)                            \
-        for ((var) = COGL_TAILQ_FIRST((head));                          \
-            (var);                                                      \
-            (var) = COGL_TAILQ_NEXT((var), field))
-
-#define COGL_TAILQ_FOREACH_SAFE(var, head, field, tvar)                 \
-        for ((var) = COGL_TAILQ_FIRST((head));                          \
-            (var) && ((tvar) = COGL_TAILQ_NEXT((var), field), 1);       \
-            (var) = (tvar))
-
-#define COGL_TAILQ_FOREACH_REVERSE(var, head, headname, field)          \
-        for ((var) = COGL_TAILQ_LAST((head), headname);                 \
-            (var);                                                      \
-            (var) = COGL_TAILQ_PREV((var), headname, field))
-
-#define COGL_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
-        for ((var) = COGL_TAILQ_LAST((head), headname);                 \
-            (var) && ((tvar) = COGL_TAILQ_PREV((var), headname, field), 1); \
-            (var) = (tvar))
-
-#define COGL_TAILQ_INIT(head) do {                                      \
-        COGL_TAILQ_FIRST((head)) = NULL;                                \
-        (head)->tqh_last = &COGL_TAILQ_FIRST((head));                   \
-        COGL_QMD_TRACE_HEAD(head);                                      \
-} while (0)
-
-#define COGL_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {         \
-        COGL_QMD_TAILQ_CHECK_NEXT(listelm, field);                      \
-        if ((COGL_TAILQ_NEXT((elm), field) =                            \
-             COGL_TAILQ_NEXT((listelm), field)) != NULL)                \
-                COGL_TAILQ_NEXT((elm), field)->field.tqe_prev =         \
-                    &COGL_TAILQ_NEXT((elm), field);                     \
-        else {                                                          \
-                (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field);      \
-                COGL_QMD_TRACE_HEAD(head);                              \
-        }                                                               \
-        COGL_TAILQ_NEXT((listelm), field) = (elm);                      \
-        (elm)->field.tqe_prev = &COGL_TAILQ_NEXT((listelm), field);     \
-        COGL_QMD_TRACE_ELEM(&(elm)->field);                             \
-        COGL_QMD_TRACE_ELEM(&listelm->field);                           \
-} while (0)
-
-#define COGL_TAILQ_INSERT_BEFORE(listelm, elm, field) do {              \
-        COGL_QMD_TAILQ_CHECK_PREV(listelm, field);                      \
-        (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
-        COGL_TAILQ_NEXT((elm), field) = (listelm);                      \
-        *(listelm)->field.tqe_prev = (elm);                             \
-        (listelm)->field.tqe_prev = &COGL_TAILQ_NEXT((elm), field);     \
-        COGL_QMD_TRACE_ELEM(&(elm)->field);                             \
-        COGL_QMD_TRACE_ELEM(&listelm->field);                           \
-} while (0)
-
-#define COGL_TAILQ_INSERT_HEAD(head, elm, field) do {                   \
-        COGL_QMD_TAILQ_CHECK_HEAD(head, field);                         \
-        if ((COGL_TAILQ_NEXT((elm), field) =                            \
-             COGL_TAILQ_FIRST((head))) != NULL)                         \
-                COGL_TAILQ_FIRST((head))->field.tqe_prev =              \
-                    &COGL_TAILQ_NEXT((elm), field);                     \
-        else                                                            \
-                (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field);      \
-        COGL_TAILQ_FIRST((head)) = (elm);                               \
-        (elm)->field.tqe_prev = &COGL_TAILQ_FIRST((head));              \
-        COGL_QMD_TRACE_HEAD(head);                                      \
-        COGL_QMD_TRACE_ELEM(&(elm)->field);                             \
-} while (0)
-
-#define COGL_TAILQ_INSERT_TAIL(head, elm, field) do {                   \
-        COGL_QMD_TAILQ_CHECK_TAIL(head, field);                         \
-        COGL_TAILQ_NEXT((elm), field) = NULL;                           \
-        (elm)->field.tqe_prev = (head)->tqh_last;                       \
-        *(head)->tqh_last = (elm);                                      \
-        (head)->tqh_last = &COGL_TAILQ_NEXT((elm), field);              \
-        COGL_QMD_TRACE_HEAD(head);                                      \
-        COGL_QMD_TRACE_ELEM(&(elm)->field);                             \
-} while (0)
-
-#define COGL_TAILQ_LAST(head, headname)                                 \
-        (*(((headname *)((head)->tqh_last))->tqh_last))
-
-#define COGL_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
-
-#define COGL_TAILQ_PREV(elm, headname, field)                           \
-        (*(((headname *)((elm)->field.tqe_prev))->tqh_last))
-
-#define COGL_TAILQ_REMOVE(head, elm, field) do {                        \
-        COGL_QMD_SAVELINK(oldnext, (elm)->field.tqe_next);              \
-        COGL_QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);              \
-        COGL_QMD_TAILQ_CHECK_NEXT(elm, field);                          \
-        COGL_QMD_TAILQ_CHECK_PREV(elm, field);                          \
-        if ((COGL_TAILQ_NEXT((elm), field)) != NULL)                    \
-                COGL_TAILQ_NEXT((elm), field)->field.tqe_prev =         \
-                    (elm)->field.tqe_prev;                              \
-        else {                                                          \
-                (head)->tqh_last = (elm)->field.tqe_prev;               \
-                COGL_QMD_TRACE_HEAD(head);                              \
-        }                                                               \
-        *(elm)->field.tqe_prev = COGL_TAILQ_NEXT((elm), field);         \
-        COGL_TRASHIT(*oldnext);                                         \
-        COGL_TRASHIT(*oldprev);                                         \
-        COGL_QMD_TRACE_ELEM(&(elm)->field);                             \
-} while (0)
-
-#define COGL_TAILQ_SWAP(head1, head2, type, field) do {                 \
-        type *swap_first = (head1)->tqh_first;                          \
-        type **swap_last = (head1)->tqh_last;                           \
-        (head1)->tqh_first = (head2)->tqh_first;                        \
-        (head1)->tqh_last = (head2)->tqh_last;                          \
-        (head2)->tqh_first = swap_first;                                \
-        (head2)->tqh_last = swap_last;                                  \
-        if ((swap_first = (head1)->tqh_first) != NULL)                  \
-                swap_first->field.tqe_prev = &(head1)->tqh_first;       \
-        else                                                            \
-                (head1)->tqh_last = &(head1)->tqh_first;                \
-        if ((swap_first = (head2)->tqh_first) != NULL)                  \
-                swap_first->field.tqe_prev = &(head2)->tqh_first;       \
-        else                                                            \
-                (head2)->tqh_last = &(head2)->tqh_first;                \
-} while (0)
-
-#endif /* !_COGL_QUEUE_H_ */
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index 62aca7e..efc20a3 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -56,7 +56,7 @@ struct _CoglRenderer
   int poll_fds_age;
   GList *poll_sources;
 
-  CoglClosureList idle_closures;
+  CoglList idle_closures;
 
   GList *outputs;
 
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index bfd91cd..6f978c6 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -187,7 +187,7 @@ cogl_renderer_new (void)
 
   renderer->poll_fds = g_array_new (FALSE, TRUE, sizeof (CoglPollFD));
 
-  COGL_LIST_INIT (&renderer->idle_closures);
+  _cogl_list_init (&renderer->idle_closures);
 
 #ifdef COGL_HAS_XLIB_SUPPORT
   renderer->xlib_enable_event_retrieval = TRUE;
diff --git a/cogl/cogl-sdl.c b/cogl/cogl-sdl.c
index 602cac0..324bfd8 100644
--- a/cogl/cogl-sdl.c
+++ b/cogl/cogl-sdl.c
@@ -100,6 +100,6 @@ cogl_sdl_idle (CoglContext *context)
    * to make sure the blocking returns immediately. We'll post our
    * dummy event to make sure that happens
    */
-  if (!COGL_LIST_EMPTY (&renderer->idle_closures))
+  if (!_cogl_list_empty (&renderer->idle_closures))
     _cogl_sdl_push_wakeup_event (context);
 }
diff --git a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
index 0b06dd4..9fa9cbf 100644
--- a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
+++ b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
@@ -38,6 +38,7 @@
 #include "cogl-pipeline-layer-private.h"
 #include "cogl-blend-string.h"
 #include "cogl-snippet-private.h"
+#include "cogl-list.h"
 
 #ifdef COGL_PIPELINE_FRAGEND_GLSL
 
@@ -66,13 +67,9 @@ typedef struct _UnitState
   unsigned int combine_constant_used:1;
 } UnitState;
 
-typedef struct _LayerData LayerData;
-
-COGL_LIST_HEAD (LayerDataList, LayerData);
-
-struct _LayerData
+typedef struct _LayerData
 {
-  COGL_LIST_ENTRY (LayerData) list_node;
+  CoglList link;
 
   /* Layer index for the for the previous layer. This isn't
      necessarily the same as this layer's index - 1 because the
@@ -81,7 +78,7 @@ struct _LayerData
   int previous_layer_index;
 
   CoglPipelineLayer *layer;
-};
+} LayerData;
 
 typedef struct
 {
@@ -97,7 +94,7 @@ typedef struct
      in reverse order. As soon as we're about to generate code for
      layer we'll remove it from the list so we don't generate it
      again */
-  LayerDataList layers;
+  CoglList layers;
 } CoglPipelineShaderState;
 
 static CoglUserDataKey shader_state_key;
@@ -349,7 +346,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
   g_string_set_size (ctx->codegen_source_buffer, 0);
   shader_state->header = ctx->codegen_header_buffer;
   shader_state->source = ctx->codegen_source_buffer;
-  COGL_LIST_INIT (&shader_state->layers);
+  _cogl_list_init (&shader_state->layers);
 
   add_layer_declarations (pipeline, shader_state);
   add_global_declarations (pipeline, shader_state);
@@ -750,7 +747,7 @@ ensure_layer_generated (CoglPipeline *pipeline,
   LayerData *layer_data;
 
   /* Find the layer that corresponds to this layer_num */
-  COGL_LIST_FOREACH (layer_data, &shader_state->layers, list_node)
+  _cogl_list_for_each (layer_data, &shader_state->layers, link)
     {
       layer = layer_data->layer;
 
@@ -765,7 +762,7 @@ ensure_layer_generated (CoglPipeline *pipeline,
  found:
 
   /* Remove the layer from the list so we don't generate it again */
-  COGL_LIST_REMOVE (layer_data, list_node);
+  _cogl_list_remove (&layer_data->link);
 
   combine_authority =
     _cogl_pipeline_layer_get_authority (layer,
@@ -882,13 +879,18 @@ _cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline,
   layer_data = g_slice_new (LayerData);
   layer_data->layer = layer;
 
-  if (COGL_LIST_EMPTY (&shader_state->layers))
-    layer_data->previous_layer_index = -1;
+  if (_cogl_list_empty (&shader_state->layers))
+    {
+      layer_data->previous_layer_index = -1;
+    }
   else
-    layer_data->previous_layer_index
-      = COGL_LIST_FIRST (&shader_state->layers)->layer->index;
+    {
+      LayerData *first =
+        _cogl_container_of (shader_state->layers.next, first, link);
+      layer_data->previous_layer_index = first->layer->index;
+    }
 
-  COGL_LIST_INSERT_HEAD (&shader_state->layers, layer_data, list_node);
+  _cogl_list_insert (&shader_state->layers, &layer_data->link);
 
   return TRUE;
 }
@@ -988,20 +990,25 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
          for the last layer. If the value of this layer depends on any
          previous layers then it will recursively generate the code
          for those layers */
-      if (!COGL_LIST_EMPTY (&shader_state->layers))
+      if (!_cogl_list_empty (&shader_state->layers))
         {
           CoglPipelineLayer *last_layer;
           LayerData *layer_data, *tmp;
 
-          last_layer = COGL_LIST_FIRST (&shader_state->layers)->layer;
+          layer_data = _cogl_container_of (shader_state->layers.next,
+                                           layer_data,
+                                           link);
+          last_layer = layer_data->layer;
 
           ensure_layer_generated (pipeline, last_layer->index);
           g_string_append_printf (shader_state->source,
                                   "  cogl_color_out = cogl_layer%i;\n",
                                   last_layer->index);
 
-          COGL_LIST_FOREACH_SAFE (layer_data, &shader_state->layers,
-                                  list_node, tmp)
+          _cogl_list_for_each_safe (layer_data,
+                                    tmp,
+                                    &shader_state->layers,
+                                    link)
             g_slice_free (LayerData, layer_data);
         }
       else
diff --git a/doc/reference/cogl2/Makefile.am b/doc/reference/cogl2/Makefile.am
index e4556c3..9424c51 100644
--- a/doc/reference/cogl2/Makefile.am
+++ b/doc/reference/cogl2/Makefile.am
@@ -78,7 +78,6 @@ IGNORE_HFILES=\
 	cogl-gl-header.h			\
 	cogl-glsl-shader-boilerplate.h		\
 	cogl-profile.h				\
-	cogl-queue.h				\
 	cogl-rectangle-map.h			\
 	cogl-spans.h 				\
 	cogl-texture-driver.h			\
-- 
1.7.11.3.g3c3efa5



More information about the Cogl mailing list