From aeb6304585a714ebff73955095d9b49863ebb199 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Tue, 2 Sep 2008 22:06:58 +0200 Subject: [PATCH] Resources for file descriptors and memory blocks. --- ucw/res-fd.c | 52 ++++++++++++++++++++++++++++++ ucw/res-mem.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ ucw/respool.c | 29 ++++++++++++----- ucw/respool.h | 25 ++++++++++++--- 4 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 ucw/res-fd.c create mode 100644 ucw/res-mem.c diff --git a/ucw/res-fd.c b/ucw/res-fd.c new file mode 100644 index 00000000..44ce4a36 --- /dev/null +++ b/ucw/res-fd.c @@ -0,0 +1,52 @@ +/* + * The UCW Library -- Resources for File Descriptors + * + * (c) 2008 Martin Mares + * + * 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 +#include + +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 diff --git a/ucw/res-mem.c b/ucw/res-mem.c new file mode 100644 index 00000000..7eee5827 --- /dev/null +++ b/ucw/res-mem.c @@ -0,0 +1,87 @@ +/* + * The UCW Library -- Resources for Memory Blocks + * + * (c) 2008 Martin Mares + * + * 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 +#include +#include + +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 diff --git a/ucw/respool.c b/ucw/respool.c index 9a747cd4..d596a7ae 100644 --- a/ucw/respool.c +++ b/ucw/respool.c @@ -35,9 +35,14 @@ rp_delete(struct respool *rp) { 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 @@ -49,19 +54,21 @@ rp_dump(struct respool *rp) } 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) @@ -73,7 +80,7 @@ res_detach(struct resource *r) { if (r->rclass->detach) r->rclass->detach(r); - res_do_free(r); + res_drop(r); } void @@ -81,7 +88,7 @@ res_free(struct resource *r) { if (r->rclass->free) r->rclass->free(r); - res_do_free(r); + res_drop(r); } void @@ -95,10 +102,18 @@ res_dump(struct resource *r) #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; } diff --git a/ucw/respool.h b/ucw/respool.h index e06762e3..39f310c1 100644 --- a/ucw/respool.h +++ b/ucw/respool.h @@ -7,6 +7,13 @@ * 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 @@ -22,7 +29,7 @@ struct respool { struct resource { cnode n; struct respool *rpool; - struct res_class *rclass; + const struct res_class *rclass; void *priv; // Private to the class }; @@ -31,6 +38,7 @@ struct res_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); @@ -52,15 +60,16 @@ rp_switch(struct respool *rp) 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; @@ -69,4 +78,12 @@ res_new(struct res_class *rc, void *priv) 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 -- 2.39.5