From c41d616c80443a7755eab3e9135ae618427e5407 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 17 Apr 2011 17:21:53 +0200 Subject: [PATCH] Resources: Implemented subpools I also had to extend the pool/resource dumping functions, so that they can print complex structures. All functions pass the amount of indent to apply and the resource->dump callback is expected to include a `\n' after its output. --- ucw/Makefile | 2 +- ucw/fastbuf.c | 4 +-- ucw/res-fd.c | 6 ++-- ucw/res-mem.c | 8 +++--- ucw/res-subpool.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ ucw/respool.c | 25 ++++++++++------ ucw/respool.h | 10 ++++--- ucw/trans.c | 4 +-- 8 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 ucw/res-subpool.c diff --git a/ucw/Makefile b/ucw/Makefile index 6f076ed7..8d787711 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -34,7 +34,7 @@ LIBUCW_MODS= \ bbuf gary \ getopt \ strtonum \ - respool trans res-fd res-mem + respool trans res-fd res-mem res-subpool LIBUCW_MAIN_INCLUDES= \ lib.h log.h threads.h \ diff --git a/ucw/fastbuf.c b/ucw/fastbuf.c index 83c3b079..4068aab8 100644 --- a/ucw/fastbuf.c +++ b/ucw/fastbuf.c @@ -301,10 +301,10 @@ static void fb_res_free(struct resource *r) bclose(f); } -static void fb_res_dump(struct resource *r) +static void fb_res_dump(struct resource *r, uns indent UNUSED) { struct fastbuf *f = r->priv; - printf(" name=%s", f->name); + printf(" name=%s\n", f->name); } static const struct res_class fb_res_class = { diff --git a/ucw/res-fd.c b/ucw/res-fd.c index 44ce4a36..ab04b8e7 100644 --- a/ucw/res-fd.c +++ b/ucw/res-fd.c @@ -20,9 +20,9 @@ fd_res_free(struct resource *r) } static void -fd_res_dump(struct resource *r) +fd_res_dump(struct resource *r, uns indent UNUSED) { - printf(" fd=%d", (int)(intptr_t) r->priv); + printf(" fd=%d\n", (int)(intptr_t) r->priv); } static const struct res_class fd_res_class = { @@ -44,7 +44,7 @@ int main(void) struct respool *rp = rp_new("test", NULL); rp_switch(rp); res_for_fd(1); - rp_dump(rp); + rp_dump(rp, 0); rp_delete(rp); return 0; } diff --git a/ucw/res-mem.c b/ucw/res-mem.c index b65b9169..10cb1d4b 100644 --- a/ucw/res-mem.c +++ b/ucw/res-mem.c @@ -26,10 +26,10 @@ mem_res_free(struct resource *r) } static void -mem_res_dump(struct resource *r) +mem_res_dump(struct resource *r, uns indent UNUSED) { struct res_mem *rm = (struct res_mem *) r; - printf(" size=%zu", rm->size); + printf(" size=%zu, ptr=%p\n", rm->size, r->priv); } static const struct res_class mem_res_class = { @@ -77,10 +77,10 @@ int main(void) struct resource *r; char *p = res_malloc(3, &r); p[0] = p[1] = p[2] = 1; - rp_dump(rp); + rp_dump(rp, 0); p = res_realloc(r, 5); p[3] = p[4] = 2; - rp_dump(rp); + rp_dump(rp, 0); rp_delete(rp); return 0; } diff --git a/ucw/res-subpool.c b/ucw/res-subpool.c new file mode 100644 index 00000000..5b427130 --- /dev/null +++ b/ucw/res-subpool.c @@ -0,0 +1,73 @@ +/* + * The UCW Library -- Resources for Sub-pools + * + * (c) 2011 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 + +static void +subpool_res_free(struct resource *r) +{ + struct respool *rp = r->priv; + rp->subpool_of = NULL; + rp_delete(rp); +} + +static void +subpool_res_detach(struct resource *r) +{ + struct respool *rp = r->priv; + rp->subpool_of = NULL; +} + +static void +subpool_res_dump(struct resource *r, uns indent) +{ + printf(":\n"); + rp_dump(r->priv, indent); +} + +static const struct res_class subpool_res_class = { + .name = "subpool", + .dump = subpool_res_dump, + .detach = subpool_res_detach, + .free = subpool_res_free, +}; + +struct resource * +res_subpool(struct respool *rp) +{ + ASSERT(!rp->subpool_of); + struct resource *r = res_new(&subpool_res_class, rp); + ASSERT(r); + ASSERT(r->rpool != rp); // Avoid simple loops + rp->subpool_of = r; + return r; +} + +#ifdef TEST + +int main(void) +{ + struct respool *rp = rp_new("interior", NULL); + struct respool *rp2 = rp_new("exterior", NULL); + rp_switch(rp); + res_malloc(10, NULL); + rp_switch(rp2); + res_malloc(7, NULL); + res_subpool(rp); + rp_dump(rp2, 0); + // rp_delete(rp); + // rp_dump(rp2, 0); + rp_delete(rp2); + return 0; +} + +#endif diff --git a/ucw/respool.c b/ucw/respool.c index 6a1687f3..31cfc58a 100644 --- a/ucw/respool.c +++ b/ucw/respool.c @@ -33,6 +33,8 @@ rp_new(const char *name, struct mempool *mp) static void rp_free(struct respool *rp) { + if (rp->subpool_of) + res_detach(rp->subpool_of); if (!rp->mpool) xfree(rp); if (rp_current() == rp) @@ -64,11 +66,17 @@ rp_detach(struct respool *rp) } void -rp_dump(struct respool *rp) +rp_dump(struct respool *rp, uns indent) { - printf("Resource pool %s at %p (%s):\n", (rp->name ? : "(noname)"), rp, (rp->mpool ? "mempool-based" : "freestanding")); + printf("%*sResource pool %s at %p (%s)%s:\n", + indent, "", + (rp->name ? : "(noname)"), + rp, + (rp->mpool ? "mempool-based" : "freestanding"), + (rp->subpool_of ? " (subpool)" : "") + ); CLIST_FOR_EACH(struct resource *, r, rp->resources) - res_dump(r); + res_dump(r, indent+4); } struct resource * @@ -110,12 +118,13 @@ res_free(struct resource *r) } void -res_dump(struct resource *r) +res_dump(struct resource *r, uns indent) { - printf("\t%p %s", r, r->rclass->name); + printf("%*s%p %s", indent, "", r, r->rclass->name); if (r->rclass->dump) - r->rclass->dump(r); - putchar('\n'); + r->rclass->dump(r, indent+4); + else + putchar('\n'); } #ifdef TEST @@ -128,7 +137,7 @@ int main(void) struct respool *rp = rp_new("test", NULL); rp_switch(rp); struct fastbuf *f = bfdopen_shared(1, 0); - rp_dump(rp); + rp_dump(rp, 0); bputsn(f, "Hello, all worlds!"); bclose(f); rp_delete(rp); diff --git a/ucw/respool.h b/ucw/respool.h index 9764f129..24cc1df2 100644 --- a/ucw/respool.h +++ b/ucw/respool.h @@ -10,7 +10,6 @@ /* * FIXME: * - check other candidates for resourcification - * - respool as a resource in another respool? * - unit tests * - automatic freeing of trans pool on thread exit */ @@ -25,6 +24,7 @@ struct respool { clist resources; const char *name; struct mempool *mpool; // If set, resources are allocated from the mempool, otherwise by xmalloc() + struct resource *subpool_of; }; struct resource { @@ -39,14 +39,14 @@ struct res_class { const char *name; void (*detach)(struct resource *r); void (*free)(struct resource *r); - void (*dump)(struct resource *r); + void (*dump)(struct resource *r, uns indent); uns res_size; // Size of the resource structure (0=default) }; struct respool *rp_new(const char *name, struct mempool *mp); void rp_delete(struct respool *rp); void rp_detach(struct respool *rp); -void rp_dump(struct respool *rp); +void rp_dump(struct respool *rp, uns indent); static inline struct respool * rp_current(void) @@ -67,7 +67,7 @@ struct resource *res_alloc(const struct res_class *rc) LIKE_MALLOC; // Returns N void res_drop(struct resource *r); void res_detach(struct resource *r); void res_free(struct resource *r); -void res_dump(struct resource *r); +void res_dump(struct resource *r, uns indent); static inline struct resource * // Returns NULL if there is no pool active res_new(const struct res_class *rc, void *priv) @@ -89,4 +89,6 @@ void *res_malloc(size_t size, struct resource **ptr) LIKE_MALLOC; // Allocates m void *res_malloc_zero(size_t size, struct resource **ptr) LIKE_MALLOC; // Allocates zero-initialized memory and creates a resource for it void *res_realloc(struct resource *res, size_t size); +struct resource *res_subpool(struct respool *rp); // Make @rp a sub-pool of the current pool + #endif diff --git a/ucw/trans.c b/ucw/trans.c index fffcf750..d91437b4 100644 --- a/ucw/trans.c +++ b/ucw/trans.c @@ -159,7 +159,7 @@ trans_dump(void) while (tx != t) { printf("Recovering transaction %p:\n", tx); - rp_dump(tx->rpool); + rp_dump(tx->rpool, 0); tx = tx->prev_trans; } } @@ -172,7 +172,7 @@ trans_dump(void) while (t) { printf("Transaction %p:\n", t); - rp_dump(t->rpool); + rp_dump(t->rpool, 0); t = t->prev_trans; } } -- 2.39.5