]> mj.ucw.cz Git - libucw.git/blob - ucw/resource.c
io-careful: Do not fail if a system call is interrupted by a signal
[libucw.git] / ucw / resource.c
1 /*
2  *      The UCW Library -- Resource Pools
3  *
4  *      (c) 2008--2011 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/resource.h>
12 #include <ucw/mempool.h>
13
14 #include <stdio.h>
15
16 struct respool *
17 rp_new(const char *name, struct mempool *mp)
18 {
19   struct respool *rp;
20
21   if (mp)
22     {
23       rp = mp_alloc_zero(mp, sizeof(*rp));
24       rp->mpool = mp;
25     }
26   else
27     rp = xmalloc_zero(sizeof(*rp));
28   clist_init(&rp->resources);
29   rp->name = name;
30   rp->default_res_flags = RES_FLAG_TEMP;
31   return rp;
32 }
33
34 static void
35 rp_free(struct respool *rp)
36 {
37   if (rp->subpool_of)
38     res_detach(rp->subpool_of);
39   if (!rp->mpool)
40     xfree(rp);
41   if (rp_current() == rp)
42     rp_switch(NULL);
43 }
44
45 void
46 rp_delete(struct respool *rp)
47 {
48   struct resource *r;
49   while (r = clist_tail(&rp->resources))
50     {
51       ASSERT(r->rpool == rp);
52       res_free(r);
53     }
54   rp_free(rp);
55 }
56
57 void
58 rp_detach(struct respool *rp)
59 {
60   struct resource *r;
61   while (r = clist_head(&rp->resources))
62     {
63       ASSERT(r->rpool == rp);
64       res_detach(r);
65     }
66   rp_free(rp);
67 }
68
69 void
70 rp_commit(struct respool *rp)
71 {
72   struct resource *r;
73   while (r = clist_head(&rp->resources))
74     {
75       ASSERT(r->rpool == rp);
76       if (r->flags & RES_FLAG_TEMP)
77         res_free(r);
78       else
79         res_detach(r);
80     }
81   rp_free(rp);
82 }
83
84 void
85 rp_dump(struct respool *rp, uint indent)
86 {
87   printf("%*sResource pool %s at %p (%s)%s:\n",
88          indent, "",
89          (rp->name ? : "(noname)"),
90          rp,
91          (rp->mpool ? "mempool-based" : "freestanding"),
92          (rp->subpool_of ? " (subpool)" : "")
93          );
94   CLIST_FOR_EACH(struct resource *, r, rp->resources)
95     res_dump(r, indent+4);
96 }
97
98 struct resource *
99 res_alloc(const struct res_class *rc)
100 {
101   struct respool *rp = rp_current();
102   ASSERT(rp);
103   uint size = (rc->res_size ? : sizeof(struct resource));
104   struct resource *r;
105   if (rp->mpool)
106     {
107       r = mp_alloc_fast(rp->mpool, size);
108       r->flags = 0;
109     }
110   else
111     {
112       r = xmalloc(size);
113       r->flags = RES_FLAG_XFREE;
114     }
115   res_add(r);
116   return r;
117 }
118
119 void
120 res_add(struct resource *r)
121 {
122   struct respool *rp = rp_current();
123   ASSERT(rp);
124   r->rpool = rp;
125   clist_add_tail(&rp->resources, &r->n);
126   r->flags &= ~RES_FLAG_TEMP;
127   r->flags |= rp->default_res_flags & RES_FLAG_TEMP;
128 }
129
130 void
131 res_drop(struct resource *r)
132 {
133   clist_remove(&r->n);
134   if (r->flags & RES_FLAG_XFREE)
135     xfree(r);
136 }
137
138 void
139 res_detach(struct resource *r)
140 {
141   if (!r)
142     return;
143   if (r->rclass->detach)
144     r->rclass->detach(r);
145   res_drop(r);
146 }
147
148 void
149 res_free(struct resource *r)
150 {
151   if (!r)
152     return;
153   if (r->rclass->free)
154     r->rclass->free(r);
155   res_drop(r);
156 }
157
158 void
159 res_dump(struct resource *r, uint indent)
160 {
161   printf("%*s%p %s %s", indent, "", r, ((r->flags & RES_FLAG_TEMP) ? "TEMP" : "PERM"), r->rclass->name);
162   if (r->rclass->dump)
163     r->rclass->dump(r, indent+4);
164   else
165     putchar('\n');
166 }
167
168 #ifdef TEST
169
170 #include <ucw/fastbuf.h>
171
172 int main(void)
173 {
174   // struct mempool *mp = mp_new(4096);
175   struct respool *rp = rp_new("test", NULL);
176   rp_switch(rp);
177   struct fastbuf *f = bfdopen_shared(1, 0);
178   rp_dump(rp, 0);
179   bputsn(f, "Hello, all worlds!");
180   bclose(f);
181   rp_delete(rp);
182   return 0;
183 }
184
185 #endif