add blend mode tests
[swfdec.git] / swfdec / swfdec_cache.c
blob1528fac9c5f223bf0703b4bd10d9cbcbb0c01d9d
1 /* Swfdec
2 * Copyright (C) 2005 David Schleef <ds@schleef.org>
3 * 2007-2008 Benjamin Otte <otte@gnome.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301 USA
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "swfdec_cache.h"
26 #include "swfdec_debug.h"
29 G_DEFINE_TYPE (SwfdecCache, swfdec_cache, G_TYPE_OBJECT)
31 enum {
32 PROP_0,
33 PROP_CACHE_SIZE,
34 PROP_MAX_CACHE_SIZE,
37 /* NB: assumes that the cached was already removed from cache->list */
38 static void
39 swfdec_cache_remove (SwfdecCache *cache, SwfdecCached *cached)
41 cache->size -= swfdec_cached_get_size (cached);
42 g_signal_handlers_disconnect_matched (cached,
43 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, cache);
44 g_object_unref (cached);
47 static void
48 swfdec_cache_dispose (GObject *object)
50 SwfdecCache *cache = SWFDEC_CACHE (object);
51 SwfdecCached *cached;
53 if (cache->queue) {
54 while ((cached = g_queue_pop_tail (cache->queue)))
55 swfdec_cache_remove (cache, cached);
56 g_queue_free (cache->queue);
58 g_assert (cache->size == 0);
60 G_OBJECT_CLASS (swfdec_cache_parent_class)->dispose (object);
63 static void
64 swfdec_cache_get_property (GObject *object, guint param_id, GValue *value,
65 GParamSpec *pspec)
67 SwfdecCache *cache = SWFDEC_CACHE (object);
69 switch (param_id) {
70 case PROP_CACHE_SIZE:
71 g_value_set_ulong (value, cache->size);
72 break;
73 case PROP_MAX_CACHE_SIZE:
74 g_value_set_ulong (value, cache->max_size);
75 break;
76 default:
77 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
78 break;
82 static void
83 swfdec_cache_set_property (GObject *object, guint param_id, const GValue *value,
84 GParamSpec *pspec)
86 SwfdecCache *cache = SWFDEC_CACHE (object);
88 switch (param_id) {
89 case PROP_MAX_CACHE_SIZE:
90 swfdec_cache_set_max_cache_size (cache, g_value_get_ulong (value));
91 break;
92 default:
93 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
94 break;
98 static void
99 swfdec_cache_class_init (SwfdecCacheClass * g_class)
101 GObjectClass *object_class = G_OBJECT_CLASS (g_class);
103 object_class->dispose = swfdec_cache_dispose;
104 object_class->get_property = swfdec_cache_get_property;
105 object_class->set_property = swfdec_cache_set_property;
107 /* FIXME: should be g_param_spec_size(), but no such thing exists */
108 g_object_class_install_property (object_class, PROP_CACHE_SIZE,
109 g_param_spec_ulong ("cache-size", "cache-size", "current size of cache",
110 0, G_MAXULONG, 0, G_PARAM_READABLE));
111 g_object_class_install_property (object_class, PROP_MAX_CACHE_SIZE,
112 g_param_spec_ulong ("max-cache-size", "max-cache-size", "maximum allowed size of cache",
113 0, G_MAXULONG, 1024 * 1024, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
116 static void
117 swfdec_cache_init (SwfdecCache *cache)
119 cache->queue = g_queue_new ();
122 SwfdecCache *
123 swfdec_cache_new (gsize max_size)
125 return g_object_new (SWFDEC_TYPE_CACHE, "max-cache-size", max_size, NULL);
128 gsize
129 swfdec_cache_get_cache_size (SwfdecCache *cache)
131 g_return_val_if_fail (SWFDEC_IS_CACHE (cache), 0);
133 return cache->size;
136 gsize
137 swfdec_cache_get_max_cache_size (SwfdecCache *cache)
139 g_return_val_if_fail (SWFDEC_IS_CACHE (cache), 0);
141 return cache->max_size;
144 void
145 swfdec_cache_set_max_cache_size (SwfdecCache *cache, gsize max_size)
147 g_return_if_fail (SWFDEC_IS_CACHE (cache));
149 cache->max_size = max_size;
150 swfdec_cache_shrink (cache, max_size);
151 g_object_notify (G_OBJECT (cache), "max-cache-size");
154 void
155 swfdec_cache_shrink (SwfdecCache *cache, gsize size)
157 SwfdecCached *cached;
159 g_return_if_fail (SWFDEC_IS_CACHE (cache));
161 if (size >= cache->size)
162 return;
164 do {
165 cached = g_queue_pop_tail (cache->queue);
166 g_assert (cached);
167 swfdec_cache_remove (cache, cached);
168 } while (size < cache->size);
169 g_object_notify (G_OBJECT (cache), "cache-size");
172 static void
173 swfdec_cache_use_cached (SwfdecCached *cached, SwfdecCache *cache)
175 /* move cached item to the front of the queue */
176 g_queue_remove (cache->queue, cached);
177 g_queue_push_head (cache->queue, cached);
180 static void
181 swfdec_cache_unuse_cached (SwfdecCached *cached, SwfdecCache *cache)
183 /* move cached item to the front of the queue */
184 g_queue_remove (cache->queue, cached);
185 swfdec_cache_remove (cache, cached);
188 void
189 swfdec_cache_add (SwfdecCache *cache, SwfdecCached *cached)
191 gsize needed_size;
193 g_return_if_fail (SWFDEC_IS_CACHE (cache));
194 g_return_if_fail (SWFDEC_IS_CACHED (cached));
196 needed_size = swfdec_cached_get_size (cached);
197 if (needed_size > cache->max_size)
198 return;
200 g_object_ref (cached);
201 swfdec_cache_shrink (cache, cache->max_size - needed_size);
202 cache->size += needed_size;
203 g_signal_connect (cached, "use", G_CALLBACK (swfdec_cache_use_cached), cache);
204 g_signal_connect (cached, "unuse", G_CALLBACK (swfdec_cache_unuse_cached), cache);
205 g_queue_push_head (cache->queue, cached);