or *detached* from the pool (which keeps the real resource, but forgets
its meta-data, so the resource is no longer tracked).
+In many cases, a combination of both methods is needed: some resources
+are marked as temporary, while some others are permanent. When the
+an operation is completed successfully (and @rp_commit() is called),
+all temporary resources are freed and the permanent ones detached.
+When the operation fails, @rp_delete() deletes all resources. By default,
+all resources are created as temporary. You can make a resource permanent
+by calling @res_permanent(), or change the default in `resource->default_res_flags`.
+
For each thread, LibUCW remembers the currently active resource pool.
One pool can be used for at most one thread at a time. All functions
which create resources do so in the active pool. All other functions
/*
* The UCW Library -- Resource Pools
*
- * (c) 2008 Martin Mares <mj@ucw.cz>
+ * (c) 2008--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.
rp = xmalloc_zero(sizeof(*rp));
clist_init(&rp->resources);
rp->name = name;
+ rp->default_res_flags = RES_FLAG_TEMP;
return rp;
}
rp_free(rp);
}
+void
+rp_commit(struct respool *rp)
+{
+ struct resource *r;
+ while (r = clist_head(&rp->resources))
+ {
+ ASSERT(r->rpool == rp);
+ if (r->flags & RES_FLAG_TEMP)
+ res_free(r);
+ else
+ res_detach(r);
+ }
+ rp_free(rp);
+}
+
void
rp_dump(struct respool *rp, uns indent)
{
struct resource *r = (rp->mpool ? mp_alloc_fast(rp->mpool, size) : xmalloc(size));
r->rpool = rp;
clist_add_tail(&rp->resources, &r->n);
+ r->flags = rp->default_res_flags;
return r;
}
void
res_dump(struct resource *r, uns indent)
{
- printf("%*s%p %s", indent, "", r, r->rclass->name);
+ printf("%*s%p %s %s", indent, "", r, ((r->flags & RES_FLAG_TEMP) ? "TEMP" : "PERM"), r->rclass->name);
if (r->rclass->dump)
r->rclass->dump(r, indent+4);
else
const char *name;
struct mempool *mpool; // If set, resources are allocated from the mempool, otherwise by xmalloc()
struct resource *subpool_of;
+ uns default_res_flags; // RES_FLAG_xxx for newly allocated resources
};
/**
struct resource {
cnode n;
struct respool *rpool;
+ uns flags; // RES_FLAG_xxx
const struct res_class *rclass;
void *priv; // Private to the class
// More data specific for the particular class can follow
};
+/** Resource flags **/
+enum resource_flags {
+ RES_FLAG_TEMP = 1, // Resource is temporary
+};
+
/**
* Creates a new resource pool. If a memory pool is given, meta-data of all resources
* will be allocated from this pool. Otherwise, they will be malloc'ed.
void rp_delete(struct respool *rp); /** Deletes a resource pool, freeing all resources. **/
void rp_detach(struct respool *rp); /** Deletes a resource pool, detaching all resources. **/
+void rp_commit(struct respool *rp); /** Deletes a resource pool. Temporary resources are freed, stable resources are detached. **/
void rp_dump(struct respool *rp, uns indent); /** Prints out a debugging dump of a pool to stdout. **/
/** Returns a pointer to the currently active resource pool or NULL, if none exists. **/
void res_dump(struct resource *r, uns indent); /** Prints out a debugging dump of the resource to stdout. **/
void res_free(struct resource *r); /** Frees a resource, unlinking it from its pool. **/
+/** Marks a resource as temporary (sets @RES_FLAG_TEMP). **/
+static inline void res_temporary(struct resource *r)
+{
+ r->flags |= RES_FLAG_TEMP;
+}
+
+/** Marks a resource as permanent (clears @RES_FLAG_TEMP). **/
+static inline void res_permanent(struct resource *r)
+{
+ r->flags &= RES_FLAG_TEMP;
+}
+
/***
* === Resource classes
*