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 \
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 = {
}
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 = {
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;
}
}
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 = {
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;
}
--- /dev/null
+/*
+ * The UCW Library -- Resources for Sub-pools
+ *
+ * (c) 2011 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>
+
+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
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)
}
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 *
}
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
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);
/*
* FIXME:
* - check other candidates for resourcification
- * - respool as a resource in another respool?
* - unit tests
* - automatic freeing of trans pool on thread exit
*/
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 {
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)
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)
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
while (tx != t)
{
printf("Recovering transaction %p:\n", tx);
- rp_dump(tx->rpool);
+ rp_dump(tx->rpool, 0);
tx = tx->prev_trans;
}
}
while (t)
{
printf("Transaction %p:\n", t);
- rp_dump(t->rpool);
+ rp_dump(t->rpool, 0);
t = t->prev_trans;
}
}