Release Clutter 1.11.4 (snapshot)
[profile/ivi/clutter.git] / clutter / clutter-id-pool.c
1 /*
2  * Clutter.
3  *
4  * An OpenGL based 'interactive canvas' library.
5  *
6  * Authored By Matthew Allum  <mallum@openedhand.com>
7  *
8  * Copyright (C) 2006-2008 OpenedHand
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22  *
23  *
24  *
25  * ClutterIDPool: pool of reusable integer ids associated with pointers.
26  *
27  * Author: Øyvind Kolås <pippin@o-hand-com>
28  *
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "clutter-debug.h"
36 #include "clutter-id-pool.h"
37
38 struct _ClutterIDPool
39 {
40   GArray *array;     /* Array of pointers    */
41   GSList *free_ids;  /* A stack of freed ids */
42 };
43
44 ClutterIDPool *
45 _clutter_id_pool_new  (guint initial_size)
46 {
47   ClutterIDPool *self;
48
49   self = g_slice_new (ClutterIDPool);
50
51   self->array = g_array_sized_new (FALSE, FALSE, 
52                                    sizeof (gpointer), initial_size);
53   self->free_ids = NULL;
54   return self;
55 }
56
57 void
58 _clutter_id_pool_free (ClutterIDPool *id_pool)
59 {
60   g_return_if_fail (id_pool != NULL);
61
62   g_array_free (id_pool->array, TRUE);
63   g_slist_free (id_pool->free_ids);
64   g_slice_free (ClutterIDPool, id_pool);
65 }
66
67 guint32
68 _clutter_id_pool_add (ClutterIDPool *id_pool,
69                       gpointer       ptr)
70 {
71   gpointer *array;
72   guint32 retval;
73
74   g_return_val_if_fail (id_pool != NULL, 0);
75
76   if (id_pool->free_ids) /* There are items on our freelist, reuse one */
77     {
78       array = (void*) id_pool->array->data;
79       retval = GPOINTER_TO_UINT (id_pool->free_ids->data);
80
81       id_pool->free_ids = g_slist_remove (id_pool->free_ids,
82                                           id_pool->free_ids->data);
83       array[retval] = ptr;
84       return retval;
85     }
86
87   /* Allocate new id */
88   retval = id_pool->array->len;
89   g_array_append_val (id_pool->array, ptr);
90
91   return retval;
92 }
93
94 void
95 _clutter_id_pool_remove (ClutterIDPool *id_pool,
96                          guint32        id_)
97 {
98   gpointer *array;
99
100   g_return_if_fail (id_pool != NULL);
101
102   array = (void*) id_pool->array->data;
103
104   array[id_] = NULL;
105
106   id_pool->free_ids = g_slist_prepend (id_pool->free_ids,
107                                        GUINT_TO_POINTER (id_));
108 }
109
110 gpointer
111 _clutter_id_pool_lookup (ClutterIDPool *id_pool,
112                          guint32        id_)
113 {
114   gpointer *array;
115
116   g_return_val_if_fail (id_pool != NULL, NULL);
117   g_return_val_if_fail (id_pool->array != NULL, NULL);
118
119   array = (void*) id_pool->array->data;
120
121   if (id_ >= id_pool->array->len || array[id_] == NULL)
122     {
123       g_warning ("The required ID of %u does not refer to an existing actor; "
124                  "this usually implies that the pick() of an actor is not "
125                  "correctly implemented or that there is an error in the "
126                  "glReadPixels() implementation of the GL driver.", id_);
127       return NULL;
128     }
129
130   return array[id_];
131 }