From: Martin Mares Date: Sun, 17 Apr 2011 18:38:26 +0000 (+0200) Subject: Resource pools documented X-Git-Tag: v5.0~74^2~24 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=ccba34ac4f5f44658a537bbdf1d0594227901f24;p=libucw.git Resource pools documented --- diff --git a/ucw/doc/trans.txt b/ucw/doc/trans.txt index f56c6c36..5e5ec71e 100644 --- a/ucw/doc/trans.txt +++ b/ucw/doc/trans.txt @@ -1,11 +1,44 @@ Transactions and resource tracking ================================== +LibUCW is equipped with a general system for keeping track of resources +(allocated memory, open files, ...) and freeing them when requested to. + +The resource tracker can be used either separately (in the form of explicitly +managed resource pools) or within a transactional layer, which offers +exceptions similar to those in higher-level languages. An exception +then rolls back the transaction, freeing all temporary resources allocated +within the transaction. + +Resource pools: ucw/respool.h +----------------------------- + +A resource pool contains a stack of resources. When a new resource +is created, it is pushed onto the stack. When freeing the pool, the +resources are freed in the opposite order, which allows a resource +refer to data of previously created resources. + +A resource can be also freed separately (which unlinks it from the pool), +or *detached* from the pool (which keeps the real resource, but forgets +its meta-data, so the resource is no longer tracked). + +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 +operating on resources work on both active and in-active pools. + +!!ucw/respool.h + +Transactions: ucw/trans.h +------------------------- + Assorted notes: - A transaction is tied to a thread which has created it. A transaction can create a sub-transaction, so every thread keeps a stack of running - transactions in its per-thread data. + transactions in its per-thread data. Calling @trans_init() is optional, + but @trans_cleanup() should be used before a thread exits in order to + free resources used by transaction system. - Every transaction keeps a resource pool containing resources, which have been created during the transaction. Whenever the transaction is @@ -82,3 +115,9 @@ Assorted notes: are of course destroyed during the `longjmp()`. FIXME: Interaction between exceptions, pools and other libucw modules. + +FIXME: Unit tests + +FIXME: Resourcification of more libucw objects + +FIXME: Do we want to allow res_alloc() when no pool is active. diff --git a/ucw/respool.h b/ucw/respool.h index 24cc1df2..a12552ab 100644 --- a/ucw/respool.h +++ b/ucw/respool.h @@ -7,19 +7,17 @@ * of the GNU Lesser General Public License. */ -/* - * FIXME: - * - check other candidates for resourcification - * - unit tests - * - automatic freeing of trans pool on thread exit - */ - #ifndef _UCW_RESPOOL_H #define _UCW_RESPOOL_H #include "ucw/clists.h" #include "ucw/threads.h" +/** + * A resource pool. It contains a name of the pool (which is printed + * in all debugging dumps, otherwise it is not used) and a bunch of + * fields for internal use. + **/ struct respool { clist resources; const char *name; @@ -27,6 +25,11 @@ struct respool { struct resource *subpool_of; }; +/** + * Each resource is represented by this structure. It is linked to a resource + * pool it belongs to. It contains a pointer to a resource class (which describes how to + * handle the resource) and data private to the resource class. + **/ struct resource { cnode n; struct respool *rpool; @@ -35,27 +38,27 @@ struct resource { // More data specific for the particular class can follow }; -struct res_class { - const char *name; - void (*detach)(struct resource *r); - void (*free)(struct resource *r); - void (*dump)(struct resource *r, uns indent); - uns res_size; // Size of the resource structure (0=default) -}; - +/** + * 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. + **/ 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, uns indent); -static inline struct respool * -rp_current(void) +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_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. **/ +static inline struct respool *rp_current(void) { - return ucwlib_thread_context()->current_respool; // May be NULL + return ucwlib_thread_context()->current_respool; } -static inline struct respool * -rp_switch(struct respool *rp) +/** + * Makes the given resource pool active; returns a pointer to the previously active pool + * or NULL, if there was none. Calling with @rp equal to NULL deactivates the pool. + **/ +static inline struct respool *rp_switch(struct respool *rp) { struct ucwlib_context *ctx = ucwlib_thread_context(); struct respool *orp = ctx->current_respool; @@ -64,13 +67,52 @@ rp_switch(struct respool *rp) } struct resource *res_alloc(const struct res_class *rc) LIKE_MALLOC; // Returns NULL if there is no pool active -void res_drop(struct resource *r); + +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. **/ + +/*** + * === Resource classes + * + * A resource class describes how to handle a particular type of resources. + * Most importantly, it defines a set of callbacks for performing operations + * on the resources: + * + * * dump() should print a description of the resource used for debugging + * to the standard output. The description should end with a newline character + * and in case of a multi-line description, the subsequent lines should be + * indented by @indent spaces. + * * free() frees the resource; the struct resource is freed automatically afterwards. + * * detach() breaks the link between the struct resource and the real resource; + * the struct resource is freed automatically afterwards, while the resource + * continues to live. + * + * The following functions are intended for use by the resource classes only. + ***/ + +/** The structure describing a resource class. **/ +struct res_class { + const char *name; // The name of the class (included in debugging dumps) + void (*detach)(struct resource *r); // The callbacks + void (*free)(struct resource *r); + void (*dump)(struct resource *r, uns indent); + uns res_size; // Size of the resource structure (0=default) +}; + +/** Unlinks a resource from a pool and releases its meta-data. However, the resource itself is kept. **/ void res_detach(struct resource *r); -void res_free(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) +/** + * Unlinks a resource from a pool and releases its meta-data. Unlike @res_detach(), + * it does not invoke any callbacks. + **/ +void res_drop(struct resource *r); + +/** + * Creates a new resource of the specific class, setting its private data to @priv. + * Returns NULL if there is no resource pool active. + **/ +static inline struct resource *res_new(const struct res_class *rc, void *priv) { struct resource *r = res_alloc(rc); if (r) @@ -81,14 +123,21 @@ res_new(const struct res_class *rc, void *priv) return r; } -/* Various special types of resources */ +/*** + * === Pre-defined resource classes + ***/ -struct resource *res_for_fd(int fd); // Creates a resource that closes a given file descriptor +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) LIKE_MALLOC; // Allocates memory and creates a resource for it -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); +void *res_malloc(size_t size, struct resource **ptr) LIKE_MALLOC; /** Allocates memory and creates a resource for it. **/ +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); /** Re-allocates memory obtained by @res_malloc() or @res_malloc_zero(). **/ -struct resource *res_subpool(struct respool *rp); // Make @rp a sub-pool of the current pool +/** + * Converts the resource pool @rp to a resource inside the current resource pool (i.e., its sub-pool). + * You can delete the sub-pool either by freeing this resource, or by calling + * @rp_delete() on it, which removes the resource automatically. + **/ +struct resource *res_subpool(struct respool *rp); #endif