1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: gsmemraw.h 8022 2007-06-05 22:23:38Z giles $ */
15 /* Client interface for "raw memory" allocator */
16 
17 /* Initial version 02/03/1998 by John Desrosiers (soho@crl.com) */
18 /* Completely rewritten 6/26/1998 by L. Peter Deutsch <ghost@aladdin.com> */
19 
20 #ifndef gsmemraw_INCLUDED
21 #  define gsmemraw_INCLUDED
22 
23 #if 0
24 
25 /* gsmemraw was an abstract base class.
26  * it is no longer in use, instead use the concrete base class is gs_memory_t
27  * since gs_memory_t contains interfaces that must be availiable throughout the system
28  * is is unadvisable to have a class below it without these.
29  */
30 
31 
32 /*
33  * This interface provides minimal memory allocation and freeing capability.
34  * It is meant to be used for "wholesale" allocation of blocks -- typically,
35  * but not only, via malloc -- which are then divided up into "retail"
36  * objects.  However, since it is a subset (superclass) of the "retail"
37  * interface defined in gsmemory.h, retail allocators implement it as
38  * well, and in fact the malloc interface defined in gsmalloc.h is used for
39  * both wholesale and retail allocation.
40  */
41 
42 /*
43  * Define the structure for reporting memory manager statistics.
44  */
45 typedef struct gs_memory_status_s {
46     /*
47      * "Allocated" space is the total amount of space acquired from
48      * the parent of the memory manager.  It includes space used for
49      * allocated data, space available for allocation, and overhead.
50      */
51     ulong allocated;
52     /*
53      * "Used" space is the amount of space used by allocated data
54      * plus overhead.
55      */
56     ulong used;
57 } gs_memory_status_t;
58 
59 /* Define the abstract type for the memory manager. */
60 #ifndef gs_raw_memory_t_DEFINED
61 #define gs_raw_memory_t_DEFINED
62 typedef struct gs_raw_memory_s gs_raw_memory_t;
63 #endif
64 
65 /* Define the procedures for raw memory management.  Memory managers have no
66  * standard constructor: each implementation defines its own, and is
67  * responsible for calling its superclass' initialization code first.
68  * Similarly, each implementation's destructor (release) must first take
69  * care of its own cleanup and then call the superclass' release.
70  *
71  * The allocation procedures must align objects as strictly as malloc.
72  * Formerly, the procedures were required to align objects as strictly
73  * as the compiler aligned structure members.  However, the ANSI C standard
74  * does not require this -- it only requires malloc to align blocks
75  * strictly enough to prevent hardware access faults.  Thus, for example,
76  * on the x86, malloc need not align blocks at all.  And in fact, we have
77  * found one compiler (Microsoft VC 6) that 8-byte aligns 'double' members
78  * of structures, but whose malloc only 4-byte aligns its blocks.
79  * Ghostscript allocators could enforce the stricter alignment, but the
80  * few dozen lines of code required to implement this were rejected during
81  * code review as introducing too much risk for too little payoff.  As a
82  * consequence of this,
83  *
84  *	CLIENTS CANNOT ASSUME THAT BLOCKS RETURNED BY ANY OF THE ALLOCATION
85  *	PROCEDURES ARE ALIGNED ANY MORE STRICTLY THAN IS REQUIRED BY THE
86  *	HARDWARE.
87  *
88  * In particular, clients cannot assume that blocks returned by an allocator
89  * can be processed efficiently in any unit larger than a single byte: there
90  * is no guarantee that accessing any larger quantity will not require two
91  * memory accesses at the hardware level.  Clients that want to process data
92  * efficiently in larger units must use ALIGNMENT_MOD to determine the
93  * actual alignment of the data in memory.
94  */
95 
96 		/*
97 		 * Allocate bytes.  The bytes are always aligned maximally
98 		 * if the processor requires alignment.
99 		 *
100 		 * Note that the object memory level can allocate bytes as
101 		 * either movable or immovable: raw memory blocks are
102 		 * always immovable.
103 		 */
104 
105 #define gs_memory_t_proc_alloc_bytes(proc, mem_t)\
106   byte *proc(mem_t *mem, uint nbytes, client_name_t cname)
107 
108 #define gs_alloc_bytes_immovable(mem, nbytes, cname)\
109   ((mem)->procs.alloc_bytes_immovable(mem, nbytes, cname))
110 
111 		/*
112 		 * Resize an object to a new number of elements.  At the raw
113 		 * memory level, the "element" is a byte; for object memory
114 		 * (gsmemory.h), the object may be an an array of either
115 		 * bytes or structures.  The new size may be larger than,
116 		 * the same as, or smaller than the old.  If the new size is
117 		 * the same as the old, resize_object returns the same
118 		 * object; otherwise, it preserves the first min(old_size,
119 		 * new_size) bytes of the object's contents.
120 		 */
121 
122 #define gs_memory_t_proc_resize_object(proc, mem_t)\
123   void *proc(mem_t *mem, void *obj, uint new_num_elements,\
124 	     client_name_t cname)
125 
126 #define gs_resize_object(mem, obj, newn, cname)\
127   ((mem)->procs.resize_object(mem, obj, newn, cname))
128 
129 		/*
130 		 * Free an object (at the object memory level, this includes
131 		 * everything except strings).  Note: data == 0 must be
132 		 * allowed, and must be a no-op.
133 		 */
134 
135 #define gs_memory_t_proc_free_object(proc, mem_t)\
136   void proc(mem_t *mem, void *data, client_name_t cname)
137 
138 #define gs_free_object(mem, data, cname)\
139   ((mem)->procs.free_object(mem, data, cname))
140 
141 		/*
142 		 * Report status (assigned, used).
143 		 */
144 
145 #define gs_memory_t_proc_status(proc, mem_t)\
146   void proc(mem_t *mem, gs_memory_status_t *status)
147 
148 #define gs_memory_status(mem, pst)\
149   ((mem)->procs.status(mem, pst))
150 
151 		/*
152 		 * Return the stable allocator for this allocator.  The
153 		 * stable allocator allocates from the same heap and in
154 		 * the same VM space, but is not subject to save and restore.
155 		 * (It is the client's responsibility to avoid creating
156 		 * dangling pointers.)
157 		 *
158 		 * Note that the stable allocator may be the same allocator
159 		 * as this one.
160 		 */
161 
162 #define gs_memory_t_proc_stable(proc, mem_t)\
163   mem_t *proc(mem_t *mem)
164 
165 #define gs_memory_stable(mem)\
166   ((mem)->procs.stable(mem))
167 
168 		/*
169 		 * Free one or more of: data memory acquired by the allocator
170 		 * (FREE_ALL_DATA), overhead structures other than the
171 		 * allocator itself (FREE_ALL_STRUCTURES), and the allocator
172 		 * itself (FREE_ALL_ALLOCATOR).  Note that this requires
173 		 * allocators to keep track of all the memory they have ever
174 		 * acquired, and where they acquired it.  Note that this
175 		 * operation propagates to the stable allocator (if
176 		 * different).
177 		 */
178 
179 #define FREE_ALL_DATA 1
180 #define FREE_ALL_STRUCTURES 2
181 #define FREE_ALL_ALLOCATOR 4
182 #define FREE_ALL_EVERYTHING\
183   (FREE_ALL_DATA | FREE_ALL_STRUCTURES | FREE_ALL_ALLOCATOR)
184 
185 #define gs_memory_t_proc_free_all(proc, mem_t)\
186   void proc(mem_t *mem, uint free_mask, client_name_t cname)
187 
188 #define gs_memory_free_all(mem, free_mask, cname)\
189   ((mem)->procs.free_all(mem, free_mask, cname))
190 /* Backward compatibility */
191 #define gs_free_all(mem)\
192   gs_memory_free_all(mem, FREE_ALL_DATA, "(free_all)")
193 
194 		/*
195 		 * Consolidate free space.  This may be used as part of (or
196 		 * as an alternative to) garbage collection, or before
197 		 * giving up on an attempt to allocate.
198 		 */
199 
200 #define gs_memory_t_proc_consolidate_free(proc, mem_t)\
201   void proc(mem_t *mem)
202 
203 #define gs_consolidate_free(mem)\
204   ((mem)->procs.consolidate_free(mem))
205 
206 /* Define the members of the procedure structure. */
207 #define gs_raw_memory_procs(mem_t)\
208     gs_memory_t_proc_alloc_bytes((*alloc_bytes_immovable), mem_t);\
209     gs_memory_t_proc_resize_object((*resize_object), mem_t);\
210     gs_memory_t_proc_free_object((*free_object), mem_t);\
211     gs_memory_t_proc_stable((*stable), mem_t);\
212     gs_memory_t_proc_status((*status), mem_t);\
213     gs_memory_t_proc_free_all((*free_all), mem_t);\
214     gs_memory_t_proc_consolidate_free((*consolidate_free), mem_t)
215 
216 /*
217  * Define an abstract raw-memory allocator instance.
218  * Subclasses may have additional state.
219  */
220 typedef struct gs_raw_memory_procs_s {
221     gs_raw_memory_procs(gs_raw_memory_t);
222 } gs_raw_memory_procs_t;
223 
224 
225 
226 struct gs_raw_memory_s {
227     gs_raw_memory_t *stable_memory;	/* cache the stable allocator */
228     gs_raw_memory_procs_t procs;
229 };
230 
231 #endif /* 0 */
232 #endif /* gsmemraw_INCLUDED */
233