]> mj.ucw.cz Git - libucw.git/commitdiff
Resources for file descriptors and memory blocks.
authorMartin Mares <mj@ucw.cz>
Tue, 2 Sep 2008 20:06:58 +0000 (22:06 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 29 Mar 2011 10:55:05 +0000 (12:55 +0200)
ucw/res-fd.c [new file with mode: 0644]
ucw/res-mem.c [new file with mode: 0644]
ucw/respool.c
ucw/respool.h

diff --git a/ucw/res-fd.c b/ucw/res-fd.c
new file mode 100644 (file)
index 0000000..44ce4a3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *     The UCW Library -- Resources for File Descriptors
+ *
+ *     (c) 2008 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>
+#include <unistd.h>
+
+static void
+fd_res_free(struct resource *r)
+{
+  close((int)(intptr_t) r->priv);
+}
+
+static void
+fd_res_dump(struct resource *r)
+{
+  printf(" fd=%d", (int)(intptr_t) r->priv);
+}
+
+static const struct res_class fd_res_class = {
+  .name = "fd",
+  .dump = fd_res_dump,
+  .free = fd_res_free,
+};
+
+struct resource *
+res_for_fd(int fd)
+{
+  return res_new(&fd_res_class, (void*)(intptr_t) fd);
+}
+
+#ifdef TEST
+
+int main(void)
+{
+  struct respool *rp = rp_new("test", NULL);
+  rp_switch(rp);
+  res_for_fd(1);
+  rp_dump(rp);
+  rp_delete(rp);
+  return 0;
+}
+
+#endif
diff --git a/ucw/res-mem.c b/ucw/res-mem.c
new file mode 100644 (file)
index 0000000..7eee582
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *     The UCW Library -- Resources for Memory Blocks
+ *
+ *     (c) 2008 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>
+#include <stdlib.h>
+#include <string.h>
+
+struct res_mem {
+  struct resource r;
+  size_t size;                 // Just for sake of readable resource dumps
+};
+
+static void
+mem_res_free(struct resource *r)
+{
+  xfree(r->priv);
+}
+
+static void
+mem_res_dump(struct resource *r)
+{
+  struct res_mem *rm = (struct res_mem *) r;
+  printf(" size=%zu", rm->size);
+}
+
+static const struct res_class mem_res_class = {
+  .name = "mem",
+  .dump = mem_res_dump,
+  .free = mem_res_free,
+  .res_size = sizeof(struct res_mem),
+};
+
+void *
+res_malloc(size_t size, struct resource **ptr)
+{
+  void *p = xmalloc(size);
+  struct resource *r = res_new(&mem_res_class, p);
+  ((struct res_mem *) r) -> size = size;
+  if (ptr)
+    *ptr = r;
+  return p;
+}
+
+void *
+res_malloc_zero(size_t size, struct resource **ptr)
+{
+  void *p = res_malloc(size, ptr);
+  bzero(p, size);
+  return p;
+}
+
+void *
+res_realloc(struct resource *r, size_t size)
+{
+  struct res_mem *rm = (struct res_mem *) r;
+  r->priv = xrealloc(r->priv, size);
+  rm->size = size;
+  return r->priv;
+}
+
+#ifdef TEST
+
+int main(void)
+{
+  struct respool *rp = rp_new("test", NULL);
+  rp_switch(rp);
+  struct resource *r;
+  char *p = res_malloc(3, &r);
+  p[0] = p[1] = p[2] = 1;
+  rp_dump(rp);
+  p = res_realloc(r, 5);
+  p[3] = p[4] = 2;
+  rp_dump(rp);
+  rp_delete(rp);
+  return 0;
+}
+
+#endif
index 9a747cd40d72be1fd3f61105b74f783bdd98d0d5..d596a7ae3c2c61f8ef4f7693a683c68880a1b363 100644 (file)
@@ -35,9 +35,14 @@ rp_delete(struct respool *rp)
 {
   struct resource *r;
   while (r = clist_tail(&rp->resources))
-    res_free(r);
+    {
+      ASSERT(r->rpool == rp);
+      res_free(r);
+    }
   if (!rp->mpool)
     xfree(rp);
+  if (rp_current() == rp)
+    rp_switch(NULL);
 }
 
 void
@@ -49,19 +54,21 @@ rp_dump(struct respool *rp)
 }
 
 struct resource *
-res_alloc(void)
+res_alloc(const struct res_class *rc)
 {
   struct respool *rp = rp_current();
   if (!rp)
     return NULL;
 
-  struct resource *r = (rp->mpool ? mp_alloc_fast(rp->mpool, sizeof(*r)) : xmalloc(sizeof(*r)));
+  uns size = (rc->res_size ? : sizeof(struct resource));
+  struct resource *r = (rp->mpool ? mp_alloc_fast(rp->mpool, size) : xmalloc(size));
+  r->rpool = rp;
   clist_add_tail(&rp->resources, &r->n);
   return r;
 }
 
-static inline void
-res_do_free(struct resource *r)
+void
+res_drop(struct resource *r)
 {
   clist_remove(&r->n);
   if (!r->rpool->mpool)
@@ -73,7 +80,7 @@ res_detach(struct resource *r)
 {
   if (r->rclass->detach)
     r->rclass->detach(r);
-  res_do_free(r);
+  res_drop(r);
 }
 
 void
@@ -81,7 +88,7 @@ res_free(struct resource *r)
 {
   if (r->rclass->free)
     r->rclass->free(r);
-  res_do_free(r);
+  res_drop(r);
 }
 
 void
@@ -95,10 +102,18 @@ res_dump(struct resource *r)
 
 #ifdef TEST
 
+#include "ucw/fastbuf.h"
+
 int main(void)
 {
+  // struct mempool *mp = mp_new(4096);
   struct respool *rp = rp_new("test", NULL);
+  rp_switch(rp);
+  struct fastbuf *f = bfdopen_shared(1, 0);
   rp_dump(rp);
+  bputsn(f, "Hello, all worlds!");
+  bclose(f);
+  rp_delete(rp);
   return 0;
 }
 
index e06762e322cce04e88d2771c97689b89b0dfef47..39f310c121e2c3ee545697dcde8b86358a8958e4 100644 (file)
@@ -7,6 +7,13 @@
  *     of the GNU Lesser General Public License.
  */
 
+/*
+ * FIXME:
+ *     - check other candidates for resourcification
+ *     - respool as a resource in another respool?
+ *     - unit tests
+ */
+
 #ifndef _UCW_RESPOOL_H
 #define _UCW_RESPOOL_H
 
@@ -22,7 +29,7 @@ struct respool {
 struct resource {
   cnode n;
   struct respool *rpool;
-  struct res_class *rclass;
+  const struct res_class *rclass;
   void *priv;                                          // Private to the class
 };
 
@@ -31,6 +38,7 @@ struct res_class {
   void (*detach)(struct resource *r);
   void (*free)(struct resource *r);
   void (*dump)(struct resource *r);
+  uns res_size;                                                // Size of the resource structure (0=default)
 };
 
 struct respool *rp_new(const char *name, struct mempool *mp);
@@ -52,15 +60,16 @@ rp_switch(struct respool *rp)
   return orp;
 }
 
-struct resource *res_alloc(void);                      // Returns NULL if there is no pool active
+struct resource *res_alloc(const struct res_class *rc);        // Returns NULL if there is no pool active
+void res_drop(struct resource *r);
 void res_detach(struct resource *r);
 void res_free(struct resource *r);
 void res_dump(struct resource *r);
 
 static inline struct resource *                                // Returns NULL if there is no pool active
-res_new(struct res_class *rc, void *priv)
+res_new(const struct res_class *rc, void *priv)
 {
-  struct resource *r = res_alloc();
+  struct resource *r = res_alloc(rc);
   if (r)
     {
       r->rclass = rc;
@@ -69,4 +78,12 @@ res_new(struct res_class *rc, void *priv)
   return r;
 }
 
+/* Various special types of resources */
+
+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);  // Allocates memory and creates a resource for it
+void *res_malloc_zero(size_t size, struct resource **ptr);     // Allocates zero-initialized memory and creates a resource for it
+void *res_realloc(struct resource *res, size_t size);
+
 #endif