1 /******************************************************************************/
2 /* pfixtools: a collection of postfix related tools */
4 /* ________________________________________________________________________ */
6 /* Redistribution and use in source and binary forms, with or without */
7 /* modification, are permitted provided that the following conditions */
10 /* 1. Redistributions of source code must retain the above copyright */
11 /* notice, this list of conditions and the following disclaimer. */
12 /* 2. Redistributions in binary form must reproduce the above copyright */
13 /* notice, this list of conditions and the following disclaimer in the */
14 /* documentation and/or other materials provided with the distribution. */
15 /* 3. The names of its contributors may not be used to endorse or promote */
16 /* products derived from this software without specific prior written */
19 /* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */
21 /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
22 /* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */
23 /* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
24 /* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */
25 /* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */
26 /* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
27 /* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */
28 /* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */
29 /* THE POSSIBILITY OF SUCH DAMAGE. */
30 /******************************************************************************/
33 * Copyright © 2008 Florent Bruneau
38 #include "resources.h"
40 typedef struct resource_t {
44 resource_destructor_t destructor;
48 #define RESOURCE_INIT { NULL, NULL, 0, NULL }
50 static A(resource_t) resources = ARRAY_INIT;
52 #define RESOURCE_KEY \
54 m_strcpy(rskey, BUFSIZ, ns); \
55 m_strcat(rskey, BUFSIZ, "@@"); \
56 m_strcat(rskey, BUFSIZ, key);
58 static inline void resource_wipe(resource_t *res)
60 static const resource_t vr = RESOURCE_INIT;
61 if (res->destructor) {
62 res->destructor(res->data);
68 static inline resource_t *resource_find(const char *key, bool create)
70 foreach (resource_t* res, resources) {
71 if (strcmp(res->key, key) == 0) {
76 resource_t res = RESOURCE_INIT;
77 res.key = m_strdup(key);
78 array_add(resources, res);
79 return &array_last(resources);
84 void *resource_get(const char *ns, const char *key)
87 resource_t *entry = resource_find(rskey, false);
96 bool resource_set(const char *ns, const char *key, void *data,
97 resource_destructor_t destructor) {
99 resource_t *entry = resource_find(rskey, true);
100 if (entry->data != NULL) {
101 if (entry->destructor) {
102 entry->destructor(entry->data);
105 entry->refcount += 1;
107 entry->destructor = destructor;
111 void resource_release(const char *ns, const char *key)
114 resource_t *entry = resource_find(rskey, false);
116 assert(entry->refcount > 0);
121 void resource_garbage_collect(void)
124 foreach (resource_t *res, resources) {
125 if (res->key != NULL && res->refcount == 0) {
126 debug("resource gc: %s not referenced anymore", res->key);
128 } else if (res->key != NULL) {
129 debug("resource gc: keeping %s, still %d references",
130 res->key, res->refcount);
132 array_elt(resources, used) = *res;
137 debug("resource gc: before %d resources, after %d",
138 array_len(resources), used);
139 array_len(resources) = used;
142 static void resources_exit(void)
144 array_deep_wipe(resources, resource_wipe);
146 module_exit(resources_exit);