67448c3b301bcc9d187694e9628c97938b06130b
[platform/upstream/bash.git] / include / ocache.h
1 /* ocache.h -- a minimal object caching implementation. */
2
3 /* Copyright (C) 2002 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
7    Bash is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #if !defined (_OCACHE_H_)
22 #define _OCACHE_H_ 1
23
24 #ifndef PTR_T
25
26 #if defined (__STDC__)
27 #  define PTR_T void *
28 #else
29 #  define PTR_T char *
30 #endif
31
32 #endif /* PTR_T */
33
34 #define OC_MEMSET(memp, xch, nbytes)                                    \
35 do {                                                                    \
36   if ((nbytes) <= 32) {                                                 \
37     register char * mzp = (char *)(memp);                               \
38     unsigned long mctmp = (nbytes);                                     \
39     register long mcn;                                                  \
40     if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }     \
41     switch (mctmp) {                                                    \
42       case 0: for(;;) { *mzp++ = xch;                                   \
43       case 7:      *mzp++ = xch;                                        \
44       case 6:      *mzp++ = xch;                                        \
45       case 5:      *mzp++ = xch;                                        \
46       case 4:      *mzp++ = xch;                                        \
47       case 3:      *mzp++ = xch;                                        \
48       case 2:      *mzp++ = xch;                                        \
49       case 1:      *mzp++ = xch; if(mcn <= 0) break; mcn--; }           \
50     }                                                                   \
51   } else                                                                \
52     memset ((memp), (xch), (nbytes));                                   \
53 } while(0)
54
55 typedef struct objcache {
56         PTR_T   data;
57         int     cs;             /* cache size, number of objects */
58         int     nc;             /* number of cache entries */
59 } sh_obj_cache_t;
60
61 /* Create an object cache C of N pointers to OTYPE. */
62 #define ocache_create(c, otype, n) \
63         do { \
64                 (c).data = xmalloc((n) * sizeof (otype *)); \
65                 (c).cs = (n); \
66                 (c).nc = 0; \
67         } while (0)
68
69 /* Destroy an object cache C. */
70 #define ocache_destroy(c) \
71         do { \
72                 if ((c).data) \
73                         xfree ((c).data); \
74                 (c).data = 0; \
75                 (c).cs = (c).nc = 0; \
76         } while (0)
77
78 /* Free all cached items, which are pointers to OTYPE, in object cache C. */
79 #define ocache_flush(c, otype) \
80         do { \
81                 while ((c).nc > 0) \
82                         xfree (((otype **)((c).data))[--(c).nc]); \
83         } while (0)
84
85 /*
86  * Allocate a new item of type pointer to OTYPE, using data from object
87  * cache C if any cached items exist, otherwise calling xmalloc.  Return
88  * the object in R.
89  */
90 #define ocache_alloc(c, otype, r) \
91         do { \
92                 if ((c).nc > 0) { \
93                         (r) = (otype *)((otype **)((c).data))[--(c).nc]; \
94                 } else \
95                         (r) = (otype *)xmalloc (sizeof (otype)); \
96         } while (0)
97
98 /*
99  * Free an item R of type pointer to OTYPE, adding to object cache C if
100  * there is room and calling xfree if the cache is full.  If R is added
101  * to the object cache, the contents are scrambled.
102  */
103 #define ocache_free(c, otype, r) \
104         do { \
105                 if ((c).nc < (c).cs) { \
106                         OC_MEMSET ((r), 0xdf, sizeof(otype)); \
107                         ((otype **)((c).data))[(c).nc++] = (r); \
108                 } else \
109                         xfree (r); \
110         } while (0)
111
112 /*
113  * One may declare and use an object cache as (for instance):
114  *
115  *      sh_obj_cache_t wdcache = {0, 0, 0};
116  *      sh_obj_cache_t wlcache = {0, 0, 0};
117  *
118  *      ocache_create(wdcache, WORD_DESC, 30);
119  *      ocache_create(wlcache, WORD_LIST, 30);
120  *
121  *      WORD_DESC *wd;
122  *      ocache_alloc (wdcache, WORD_DESC, wd);
123  *
124  *      WORD_LIST *wl;
125  *      ocache_alloc (wlcache, WORD_LIST, wl);
126  *
127  *      ocache_free(wdcache, WORD_DESC, wd);
128  *      ocache_free(wlcache, WORD_LIST, wl);
129  *
130  * The use is almost arbitrary.
131  */
132
133 #endif /* _OCACHE_H  */