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 CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */
20 /* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */
23 /* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
24 /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */
25 /* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
26 /* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */
27 /* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
28 /* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
29 /* POSSIBILITY OF SUCH DAMAGE. */
31 /* Copyright (c) 2006-2008 the Authors */
32 /* see AUTHORS and source files for details */
33 /******************************************************************************/
36 * Copyright © 2008 Florent Bruneau
41 #include "resources.h"
43 typedef struct resource_t {
47 resource_destructor_t destructor;
51 #define RESOURCE_INIT { NULL, NULL, 0, NULL }
53 static A(resource_t) resources = ARRAY_INIT;
55 #define RESOURCE_KEY \
57 m_strcpy(rskey, BUFSIZ, ns); \
58 m_strcat(rskey, BUFSIZ, "@@"); \
59 m_strcat(rskey, BUFSIZ, key);
61 static inline void resource_wipe(resource_t *res)
63 static const resource_t vr = RESOURCE_INIT;
64 if (res->destructor) {
65 res->destructor(res->data);
71 static inline resource_t *resource_find(const char *key, bool create)
73 foreach (resource_t* res, resources) {
74 if (strcmp(res->key, key) == 0) {
79 resource_t res = RESOURCE_INIT;
80 res.key = m_strdup(key);
81 array_add(resources, res);
82 return &array_last(resources);
87 void *resource_get(const char *ns, const char *key)
90 resource_t *entry = resource_find(rskey, false);
99 bool resource_set(const char *ns, const char *key, void *data,
100 resource_destructor_t destructor) {
102 resource_t *entry = resource_find(rskey, true);
103 if (entry->data != NULL) {
104 if (entry->destructor) {
105 entry->destructor(entry->data);
108 entry->refcount += 1;
110 entry->destructor = destructor;
114 void resource_release(const char *ns, const char *key)
117 resource_t *entry = resource_find(rskey, false);
119 assert(entry->refcount > 0);
124 void resource_garbage_collect(void)
127 foreach (resource_t *res, resources) {
128 if (res->key != NULL && res->refcount == 0) {
129 debug("resource gc: %s not referenced anymore", res->key);
131 } else if (res->key != NULL) {
132 debug("resource gc: keeping %s, still %d references",
133 res->key, res->refcount);
135 array_elt(resources, used) = *res;
140 debug("resource gc: before %d resources, after %d",
141 array_len(resources), used);
142 array_len(resources) = used;
145 static void resources_exit(void)
147 array_deep_wipe(resources, resource_wipe);
149 module_exit(resources_exit);