Initialize the gmime for upstream
[platform/upstream/gmime.git] / util / cache.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*  GMime
3  *  Copyright (C) 2000-2012 Jeffrey Stedfast
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public License
7  *  as published by the Free Software Foundation; either version 2.1
8  *  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.
14  *
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
17  *  Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
18  *  02110-1301, USA.
19  */
20
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "cache.h"
27
28
29 static void
30 cache_node_free (gpointer node_data)
31 {
32         CacheNode *node = (CacheNode *) node_data;
33         Cache *cache = node->cache;
34         
35         cache->free_node (node);
36         g_free (node->key);
37         
38         g_slice_free1 (cache->node_size, node);
39 }
40
41
42 Cache *
43 cache_new (CacheNodeExpireFunc expire, CacheNodeFreeFunc free_node, size_t node_size, size_t max_size)
44 {
45         Cache *cache;
46         
47         cache = g_new (Cache, 1);
48         list_init (&cache->list);
49         cache->expire = expire;
50         cache->free_node = free_node;
51         cache->node_hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, cache_node_free);
52         cache->node_size = node_size;
53         cache->max_size = max_size;
54         cache->size = 0;
55         
56         return cache;
57 }
58
59
60 void
61 cache_free (Cache *cache)
62 {
63         g_hash_table_destroy (cache->node_hash);
64         g_free (cache);
65 }
66
67
68 void
69 cache_expire_unused (Cache *cache)
70 {
71         ListNode *node, *prev;
72         
73         node = cache->list.tailpred;
74         while (node->prev && cache->size > cache->max_size) {
75                 prev = node->prev;
76                 if (cache->expire (cache, (CacheNode *) node)) {
77                         list_unlink (node);
78                         g_hash_table_remove (cache->node_hash, ((CacheNode *) node)->key);
79                         cache->size--;
80                 }
81                 node = prev;
82         }
83 }
84
85 CacheNode *
86 cache_node_insert (Cache *cache, const char *key)
87 {
88         CacheNode *node;
89         
90         cache->size++;
91         
92         if (cache->size > cache->max_size)
93                 cache_expire_unused (cache);
94         
95         node = g_slice_alloc (cache->node_size);
96         node->key = g_strdup (key);
97         node->cache = cache;
98         
99         g_hash_table_insert (cache->node_hash, node->key, node);
100         list_prepend (&cache->list, (ListNode *) node);
101         
102         return node;
103 }
104
105 CacheNode *
106 cache_node_lookup (Cache *cache, const char *key, gboolean use)
107 {
108         CacheNode *node;
109         
110         node = g_hash_table_lookup (cache->node_hash, key);
111         if (node && use) {
112                 list_unlink ((ListNode *) node);
113                 list_prepend (&cache->list, (ListNode *) node);
114         }
115         
116         return node;
117 }
118
119 void
120 cache_node_expire (CacheNode *node)
121 {
122         Cache *cache;
123         
124         cache = node->cache;
125         list_unlink ((ListNode *) node);
126         g_hash_table_remove (cache->node_hash, node->key);
127         cache->size--;
128 }