]> mj.ucw.cz Git - libucw.git/commitdiff
Implemented temporary resources
authorMartin Mares <mj@ucw.cz>
Tue, 19 Apr 2011 12:32:05 +0000 (14:32 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 19 Apr 2011 12:32:05 +0000 (14:32 +0200)
ucw/doc/trans.txt
ucw/respool.c
ucw/respool.h

index d2c10df31ba6b2753075000edaddfb34eb9e92f1..349055f72ef37e0d8abf282a342950192500d6f5 100644 (file)
@@ -22,6 +22,14 @@ 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).
 
+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
index 31cfc58a8272cb4bb88eb6fc6d7793a30d6e88ad..a4978fdf51ad030ff323cd00aa2b3336acd9d951 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     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.
@@ -27,6 +27,7 @@ rp_new(const char *name, struct mempool *mp)
     rp = xmalloc_zero(sizeof(*rp));
   clist_init(&rp->resources);
   rp->name = name;
+  rp->default_res_flags = RES_FLAG_TEMP;
   return rp;
 }
 
@@ -65,6 +66,21 @@ rp_detach(struct respool *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)
 {
@@ -90,6 +106,7 @@ res_alloc(const struct res_class *rc)
   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;
 }
 
@@ -120,7 +137,7 @@ res_free(struct resource *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
index a12552ab83e1ed3b801ddad8605d9b10bde5c8ea..2c312cffd9e2912f0bff702b7403c7895ccfe1f1 100644 (file)
@@ -23,6 +23,7 @@ struct respool {
   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
 };
 
 /**
@@ -33,11 +34,17 @@ struct respool {
 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.
@@ -46,6 +53,7 @@ struct respool *rp_new(const char *name, struct mempool *mp);
 
 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. **/
@@ -71,6 +79,18 @@ struct resource *res_alloc(const struct res_class *rc) LIKE_MALLOC;  // Returns N
 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
  *