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) \ 35do { \ 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 55typedef 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 */ 134