133 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* ocache.h -- a minimal object caching implementation. */
 | |
| 
 | |
| /* Copyright (C) 2002 Free Software Foundation, Inc.
 | |
| 
 | |
|    This file is part of GNU Bash, the Bourne Again SHell.
 | |
| 
 | |
|    Bash is free software; you can redistribute it and/or modify it under
 | |
|    the terms of the GNU General Public License as published by the Free
 | |
|    Software Foundation; either version 2, or (at your option) any later
 | |
|    version.
 | |
| 
 | |
|    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
 | |
|    WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
|    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 | |
|    for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License along
 | |
|    with Bash; see the file COPYING.  If not, write to the Free Software
 | |
|    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
 | |
| 
 | |
| #if !defined (_OCACHE_H_)
 | |
| #define	_OCACHE_H_ 1
 | |
| 
 | |
| #ifndef PTR_T
 | |
| 
 | |
| #if defined (__STDC__)
 | |
| #  define PTR_T void *
 | |
| #else
 | |
| #  define PTR_T char *
 | |
| #endif
 | |
| 
 | |
| #endif /* PTR_T */
 | |
| 
 | |
| #define OC_MEMSET(memp, xch, nbytes)					\
 | |
| do {									\
 | |
|   if ((nbytes) <= 32) {							\
 | |
|     register char * mzp = (char *)(memp);				\
 | |
|     unsigned long mctmp = (nbytes);					\
 | |
|     register long mcn;							\
 | |
|     if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp &= 7; }	\
 | |
|     switch (mctmp) {							\
 | |
|       case 0: for(;;) { *mzp++ = xch;					\
 | |
|       case 7:	   *mzp++ = xch;					\
 | |
|       case 6:	   *mzp++ = xch;					\
 | |
|       case 5:	   *mzp++ = xch;					\
 | |
|       case 4:	   *mzp++ = xch;					\
 | |
|       case 3:	   *mzp++ = xch;					\
 | |
|       case 2:	   *mzp++ = xch;					\
 | |
|       case 1:	   *mzp++ = xch; if(mcn <= 0) break; mcn--; }		\
 | |
|     }									\
 | |
|   } else								\
 | |
|     memset ((memp), (xch), (nbytes));					\
 | |
| } while(0)
 | |
| 
 | |
| typedef struct objcache {
 | |
| 	PTR_T	data;
 | |
| 	int	cs;		/* cache size, number of objects */
 | |
| 	int	nc;		/* number of cache entries */
 | |
| } sh_obj_cache_t;
 | |
| 
 | |
| /* Create an object cache C of N pointers to OTYPE. */
 | |
| #define ocache_create(c, otype, n) \
 | |
| 	do { \
 | |
| 		(c).data = xmalloc((n) * sizeof (otype *)); \
 | |
| 		(c).cs = (n); \
 | |
| 		(c).nc = 0; \
 | |
| 	} while (0)
 | |
| 
 | |
| /* Destroy an object cache C. */
 | |
| #define ocache_destroy(c) \
 | |
| 	do { \
 | |
| 		if ((c).data) \
 | |
| 			xfree ((c).data); \
 | |
| 		(c).data = 0; \
 | |
| 		(c).cs = (c).nc = 0; \
 | |
| 	} while (0)
 | |
| 
 | |
| /* Free all cached items, which are pointers to OTYPE, in object cache C. */
 | |
| #define ocache_flush(c, otype) \
 | |
| 	do { \
 | |
| 		while ((c).nc > 0) \
 | |
| 			xfree (((otype **)((c).data))[--(c).nc]); \
 | |
| 	} while (0)
 | |
| 
 | |
| /*
 | |
|  * Allocate a new item of type pointer to OTYPE, using data from object
 | |
|  * cache C if any cached items exist, otherwise calling xmalloc.  Return
 | |
|  * the object in R.
 | |
|  */
 | |
| #define ocache_alloc(c, otype, r) \
 | |
| 	do { \
 | |
| 		if ((c).nc > 0) { \
 | |
| 			(r) = (otype *)((otype **)((c).data))[--(c).nc]; \
 | |
| 		} else \
 | |
| 			(r) = (otype *)xmalloc (sizeof (otype)); \
 | |
| 	} while (0)
 | |
| 
 | |
| /*
 | |
|  * Free an item R of type pointer to OTYPE, adding to object cache C if
 | |
|  * there is room and calling xfree if the cache is full.  If R is added
 | |
|  * to the object cache, the contents are scrambled.
 | |
|  */
 | |
| #define ocache_free(c, otype, r) \
 | |
| 	do { \
 | |
| 		if ((c).nc < (c).cs) { \
 | |
| 			OC_MEMSET ((r), 0xdf, sizeof(otype)); \
 | |
| 			((otype **)((c).data))[(c).nc++] = (r); \
 | |
| 		} else \
 | |
| 			xfree (r); \
 | |
| 	} while (0)
 | |
| 
 | |
| /*
 | |
|  * One may declare and use an object cache as (for instance):
 | |
|  *
 | |
|  *	sh_obj_cache_t wdcache = {0, 0, 0};
 | |
|  *	sh_obj_cache_t wlcache = {0, 0, 0};
 | |
|  *
 | |
|  *	ocache_create(wdcache, WORD_DESC, 30);
 | |
|  *	ocache_create(wlcache, WORD_LIST, 30);
 | |
|  *
 | |
|  *	WORD_DESC *wd;
 | |
|  *	ocache_alloc (wdcache, WORD_DESC, wd);
 | |
|  *
 | |
|  *	WORD_LIST *wl;
 | |
|  *	ocache_alloc (wlcache, WORD_LIST, wl);
 | |
|  *
 | |
|  *	ocache_free(wdcache, WORD_DESC, wd);
 | |
|  *	ocache_free(wlcache, WORD_LIST, wl);
 | |
|  *
 | |
|  * The use is almost arbitrary.
 | |
|  */
 | |
| 
 | |
| #endif /* _OCACHE_H  */
 | 
