--- /dev/null
+/*
+ * The UCW Library -- Resources for File Descriptors
+ *
+ * (c) 2008 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include "ucw/lib.h"
+#include "ucw/respool.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+static void
+fd_res_free(struct resource *r)
+{
+ close((int)(intptr_t) r->priv);
+}
+
+static void
+fd_res_dump(struct resource *r)
+{
+ printf(" fd=%d", (int)(intptr_t) r->priv);
+}
+
+static const struct res_class fd_res_class = {
+ .name = "fd",
+ .dump = fd_res_dump,
+ .free = fd_res_free,
+};
+
+struct resource *
+res_for_fd(int fd)
+{
+ return res_new(&fd_res_class, (void*)(intptr_t) fd);
+}
+
+#ifdef TEST
+
+int main(void)
+{
+ struct respool *rp = rp_new("test", NULL);
+ rp_switch(rp);
+ res_for_fd(1);
+ rp_dump(rp);
+ rp_delete(rp);
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * The UCW Library -- Resources for Memory Blocks
+ *
+ * (c) 2008 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include "ucw/lib.h"
+#include "ucw/respool.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct res_mem {
+ struct resource r;
+ size_t size; // Just for sake of readable resource dumps
+};
+
+static void
+mem_res_free(struct resource *r)
+{
+ xfree(r->priv);
+}
+
+static void
+mem_res_dump(struct resource *r)
+{
+ struct res_mem *rm = (struct res_mem *) r;
+ printf(" size=%zu", rm->size);
+}
+
+static const struct res_class mem_res_class = {
+ .name = "mem",
+ .dump = mem_res_dump,
+ .free = mem_res_free,
+ .res_size = sizeof(struct res_mem),
+};
+
+void *
+res_malloc(size_t size, struct resource **ptr)
+{
+ void *p = xmalloc(size);
+ struct resource *r = res_new(&mem_res_class, p);
+ ((struct res_mem *) r) -> size = size;
+ if (ptr)
+ *ptr = r;
+ return p;
+}
+
+void *
+res_malloc_zero(size_t size, struct resource **ptr)
+{
+ void *p = res_malloc(size, ptr);
+ bzero(p, size);
+ return p;
+}
+
+void *
+res_realloc(struct resource *r, size_t size)
+{
+ struct res_mem *rm = (struct res_mem *) r;
+ r->priv = xrealloc(r->priv, size);
+ rm->size = size;
+ return r->priv;
+}
+
+#ifdef TEST
+
+int main(void)
+{
+ struct respool *rp = rp_new("test", NULL);
+ rp_switch(rp);
+ struct resource *r;
+ char *p = res_malloc(3, &r);
+ p[0] = p[1] = p[2] = 1;
+ rp_dump(rp);
+ p = res_realloc(r, 5);
+ p[3] = p[4] = 2;
+ rp_dump(rp);
+ rp_delete(rp);
+ return 0;
+}
+
+#endif
{
struct resource *r;
while (r = clist_tail(&rp->resources))
- res_free(r);
+ {
+ ASSERT(r->rpool == rp);
+ res_free(r);
+ }
if (!rp->mpool)
xfree(rp);
+ if (rp_current() == rp)
+ rp_switch(NULL);
}
void
}
struct resource *
-res_alloc(void)
+res_alloc(const struct res_class *rc)
{
struct respool *rp = rp_current();
if (!rp)
return NULL;
- struct resource *r = (rp->mpool ? mp_alloc_fast(rp->mpool, sizeof(*r)) : xmalloc(sizeof(*r)));
+ uns size = (rc->res_size ? : sizeof(struct resource));
+ struct resource *r = (rp->mpool ? mp_alloc_fast(rp->mpool, size) : xmalloc(size));
+ r->rpool = rp;
clist_add_tail(&rp->resources, &r->n);
return r;
}
-static inline void
-res_do_free(struct resource *r)
+void
+res_drop(struct resource *r)
{
clist_remove(&r->n);
if (!r->rpool->mpool)
{
if (r->rclass->detach)
r->rclass->detach(r);
- res_do_free(r);
+ res_drop(r);
}
void
{
if (r->rclass->free)
r->rclass->free(r);
- res_do_free(r);
+ res_drop(r);
}
void
#ifdef TEST
+#include "ucw/fastbuf.h"
+
int main(void)
{
+ // struct mempool *mp = mp_new(4096);
struct respool *rp = rp_new("test", NULL);
+ rp_switch(rp);
+ struct fastbuf *f = bfdopen_shared(1, 0);
rp_dump(rp);
+ bputsn(f, "Hello, all worlds!");
+ bclose(f);
+ rp_delete(rp);
return 0;
}
* of the GNU Lesser General Public License.
*/
+/*
+ * FIXME:
+ * - check other candidates for resourcification
+ * - respool as a resource in another respool?
+ * - unit tests
+ */
+
#ifndef _UCW_RESPOOL_H
#define _UCW_RESPOOL_H
struct resource {
cnode n;
struct respool *rpool;
- struct res_class *rclass;
+ const struct res_class *rclass;
void *priv; // Private to the class
};
void (*detach)(struct resource *r);
void (*free)(struct resource *r);
void (*dump)(struct resource *r);
+ uns res_size; // Size of the resource structure (0=default)
};
struct respool *rp_new(const char *name, struct mempool *mp);
return orp;
}
-struct resource *res_alloc(void); // Returns NULL if there is no pool active
+struct resource *res_alloc(const struct res_class *rc); // Returns NULL if there is no pool active
+void res_drop(struct resource *r);
void res_detach(struct resource *r);
void res_free(struct resource *r);
void res_dump(struct resource *r);
static inline struct resource * // Returns NULL if there is no pool active
-res_new(struct res_class *rc, void *priv)
+res_new(const struct res_class *rc, void *priv)
{
- struct resource *r = res_alloc();
+ struct resource *r = res_alloc(rc);
if (r)
{
r->rclass = rc;
return r;
}
+/* Various special types of resources */
+
+struct resource *res_for_fd(int fd); // Creates a resource that closes a given file descriptor
+
+void *res_malloc(size_t size, struct resource **ptr); // Allocates memory and creates a resource for it
+void *res_malloc_zero(size_t size, struct resource **ptr); // Allocates zero-initialized memory and creates a resource for it
+void *res_realloc(struct resource *res, size_t size);
+
#endif