Mercurial > hg > xemacs-beta
comparison src/lrecord.h @ 380:8626e4521993 r21-2-5
Import from CVS: tag r21-2-5
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:07:10 +0200 |
parents | c5d627a313b1 |
children | 74fd4e045ea6 |
comparison
equal
deleted
inserted
replaced
379:76b7d63099ad | 380:8626e4521993 |
---|---|
48 a `next' pointer. Lcrecords have a `struct lcrecord_header' | 48 a `next' pointer. Lcrecords have a `struct lcrecord_header' |
49 at the top, which contains a `struct lrecord_header' and | 49 at the top, which contains a `struct lrecord_header' and |
50 a `next' pointer, and are allocated using alloc_lcrecord(). | 50 a `next' pointer, and are allocated using alloc_lcrecord(). |
51 | 51 |
52 Creating a new lcrecord type is fairly easy; just follow the | 52 Creating a new lcrecord type is fairly easy; just follow the |
53 lead of some existing type (e.g. hashtables). Note that you | 53 lead of some existing type (e.g. hash tables). Note that you |
54 do not need to supply all the methods (see below); reasonable | 54 do not need to supply all the methods (see below); reasonable |
55 defaults are provided for many of them. Alternatively, if you're | 55 defaults are provided for many of them. Alternatively, if you're |
56 just looking for a way of encapsulating data (which possibly | 56 just looking for a way of encapsulating data (which possibly |
57 could contain Lisp_Objects in it), you may well be able to use | 57 could contain Lisp_Objects in it), you may well be able to use |
58 the opaque type. */ | 58 the opaque type. */ |
87 * implementing the scheme described in the 'It would be better | 87 * implementing the scheme described in the 'It would be better |
88 * ...' paragraph above. | 88 * ...' paragraph above. |
89 */ | 89 */ |
90 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 90 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
91 /* index into lrecord_implementations_table[] */ | 91 /* index into lrecord_implementations_table[] */ |
92 unsigned type:8; | 92 unsigned char type; |
93 /* 1 if the object is marked during GC, 0 otherwise. */ | 93 /* 1 if the object is marked during GC, 0 otherwise. */ |
94 unsigned mark:1; | 94 char mark; |
95 /* 1 if the object resides in pure (read-only) space */ | 95 /* 1 if the object resides in pure (read-only) space */ |
96 unsigned pure:1; | 96 char pure; |
97 #else | 97 #else |
98 CONST struct lrecord_implementation *implementation; | 98 CONST struct lrecord_implementation *implementation; |
99 #endif | 99 #endif |
100 }; | 100 }; |
101 | 101 |
102 struct lrecord_implementation; | 102 struct lrecord_implementation; |
103 int lrecord_type_index (CONST struct lrecord_implementation *implementation); | 103 int lrecord_type_index (CONST struct lrecord_implementation *implementation); |
104 | 104 |
105 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 105 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
106 # define set_lheader_implementation(header,imp) do \ | 106 # define set_lheader_implementation(header,imp) do { \ |
107 { \ | 107 struct lrecord_header* SLI_header = (header); \ |
108 (header)->type = lrecord_type_index (imp); \ | 108 (SLI_header)->type = lrecord_type_index (imp); \ |
109 (header)->mark = 0; \ | 109 (SLI_header)->mark = 0; \ |
110 (header)->pure = 0; \ | 110 (SLI_header)->pure = 0; \ |
111 } while (0) | 111 } while (0) |
112 #else | 112 #else |
113 # define set_lheader_implementation(header,imp) \ | 113 # define set_lheader_implementation(header,imp) \ |
114 ((void) ((header)->implementation = (imp))) | 114 ((void) ((header)->implementation = (imp))) |
115 #endif | 115 #endif |
116 | 116 |
117 struct lcrecord_header | 117 struct lcrecord_header |
118 { | 118 { |
119 struct lrecord_header lheader; | 119 struct lrecord_header lheader; |
120 /* The "next" field is normally used to chain all lrecords together | 120 |
121 /* The `next' field is normally used to chain all lrecords together | |
121 so that the GC can find (and free) all of them. | 122 so that the GC can find (and free) all of them. |
122 "alloc_lcrecord" threads records together. | 123 `alloc_lcrecord' threads records together. |
123 | 124 |
124 The "next" field may be used for other purposes as long as some | 125 The `next' field may be used for other purposes as long as some |
125 other mechanism is provided for letting the GC do its work. (For | 126 other mechanism is provided for letting the GC do its work. |
126 example, the event and marker datatypes allocate members out of | 127 |
127 memory chunks, and are able to find all unmarked members by | 128 For example, the event and marker object types allocate members |
128 sweeping through the elements of the list of chunks) */ | 129 out of memory chunks, and are able to find all unmarked members |
130 by sweeping through the elements of the list of chunks. */ | |
129 struct lcrecord_header *next; | 131 struct lcrecord_header *next; |
130 /* This is just for debugging/printing convenience. | 132 |
131 Having this slot doesn't hurt us much spacewise, since an lcrecord | 133 /* The `uid' field is just for debugging/printing convenience. |
132 already has the above slots together with malloc overhead. */ | 134 Having this slot doesn't hurt us much spacewise, since an |
135 lcrecord already has the above slots plus malloc overhead. */ | |
133 unsigned int uid :31; | 136 unsigned int uid :31; |
134 /* A flag that indicates whether this lcrecord is on a "free list". | 137 |
135 Free lists are used to minimize the number of calls to malloc() | 138 /* The `free' field is a flag that indicates whether this lcrecord |
136 when we're repeatedly allocating and freeing a number of the | 139 is on a "free list". Free lists are used to minimize the number |
137 same sort of lcrecord. Lcrecords on a free list always get | 140 of calls to malloc() when we're repeatedly allocating and freeing |
138 marked in a different fashion, so we can use this flag as a | 141 a number of the same sort of lcrecord. Lcrecords on a free list |
139 sanity check to make sure that free lists only have freed lcrecords | 142 always get marked in a different fashion, so we can use this flag |
140 and there are no freed lcrecords elsewhere. */ | 143 as a sanity check to make sure that free lists only have freed |
144 lcrecords and there are no freed lcrecords elsewhere. */ | |
141 unsigned int free :1; | 145 unsigned int free :1; |
142 }; | 146 }; |
143 | 147 |
144 /* Used for lcrecords in an lcrecord-list. */ | 148 /* Used for lcrecords in an lcrecord-list. */ |
145 struct free_lcrecord_header | 149 struct free_lcrecord_header |
147 struct lcrecord_header lcheader; | 151 struct lcrecord_header lcheader; |
148 Lisp_Object chain; | 152 Lisp_Object chain; |
149 }; | 153 }; |
150 | 154 |
151 /* This as the value of lheader->implementation->finalizer | 155 /* This as the value of lheader->implementation->finalizer |
152 * means that this record is already marked */ | 156 means that this record is already marked */ |
153 void this_marks_a_marked_record (void *, int); | 157 void this_marks_a_marked_record (void *, int); |
154 | 158 |
155 /* see alloc.c for an explanation */ | 159 /* see alloc.c for an explanation */ |
156 Lisp_Object this_one_is_unmarkable (Lisp_Object obj, | 160 Lisp_Object this_one_is_unmarkable (Lisp_Object obj, |
157 void (*markobj) (Lisp_Object)); | 161 void (*markobj) (Lisp_Object)); |
230 this_marks_a_marked_record) | 234 this_marks_a_marked_record) |
231 #endif | 235 #endif |
232 | 236 |
233 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 237 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
234 | 238 |
235 # define MARKED_RECORD_HEADER_P(lheader) (lheader)->mark | 239 # define MARKED_RECORD_HEADER_P(lheader) ((lheader)->mark) |
236 # define MARK_RECORD_HEADER(lheader) (lheader)->mark = 1 | 240 # define MARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 1)) |
237 # define UNMARK_RECORD_HEADER(lheader) (lheader)->mark = 0 | 241 # define UNMARK_RECORD_HEADER(lheader) ((void) ((lheader)->mark = 0)) |
238 | 242 |
239 #else /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ | 243 #else /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ |
240 | 244 |
241 # define MARKED_RECORD_HEADER_P(lheader) \ | 245 # define MARKED_RECORD_HEADER_P(lheader) \ |
242 (((lheader)->implementation->finalizer) == this_marks_a_marked_record) | 246 ((lheader)->implementation->finalizer == this_marks_a_marked_record) |
243 # define MARK_RECORD_HEADER(lheader) \ | 247 # define MARK_RECORD_HEADER(lheader) ((void) (((lheader)->implementation)++)) |
244 do { (((lheader)->implementation)++); } while (0) | 248 # define UNMARK_RECORD_HEADER(lheader) ((void) (((lheader)->implementation)--)) |
245 # define UNMARK_RECORD_HEADER(lheader) \ | |
246 do { (((lheader)->implementation)--); } while (0) | |
247 | 249 |
248 #endif /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ | 250 #endif /* ! USE_INDEXED_LRECORD_IMPLEMENTATION */ |
249 | 251 |
250 #define UNMARKABLE_RECORD_HEADER_P(lheader) \ | 252 #define UNMARKABLE_RECORD_HEADER_P(lheader) \ |
251 ((LHEADER_IMPLEMENTATION (lheader)->marker) \ | 253 (LHEADER_IMPLEMENTATION (lheader)->marker == this_one_is_unmarkable) |
252 == this_one_is_unmarkable) | |
253 | 254 |
254 /* Declaring the following structures as const puts them in the | 255 /* Declaring the following structures as const puts them in the |
255 text (read-only) segment, which makes debugging inconvenient | 256 text (read-only) segment, which makes debugging inconvenient |
256 because this segment is not mapped when processing a core- | 257 because this segment is not mapped when processing a core- |
257 dump file */ | 258 dump file */ |
323 #ifdef ERROR_CHECK_TYPECHECK | 324 #ifdef ERROR_CHECK_TYPECHECK |
324 | 325 |
325 # define DECLARE_LRECORD(c_name, structtype) \ | 326 # define DECLARE_LRECORD(c_name, structtype) \ |
326 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ | 327 extern CONST_IF_NOT_DEBUG struct lrecord_implementation \ |
327 lrecord_##c_name[]; \ | 328 lrecord_##c_name[]; \ |
328 INLINE structtype *error_check_##c_name (Lisp_Object _obj); \ | 329 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ |
329 INLINE structtype * \ | 330 INLINE structtype * \ |
330 error_check_##c_name (Lisp_Object _obj) \ | 331 error_check_##c_name (Lisp_Object obj) \ |
331 { \ | 332 { \ |
332 XUNMARK (_obj); \ | 333 XUNMARK (obj); \ |
333 assert (RECORD_TYPEP (_obj, lrecord_##c_name) || \ | 334 assert (RECORD_TYPEP (obj, lrecord_##c_name) || \ |
334 MARKED_RECORD_P (_obj)); \ | 335 MARKED_RECORD_P (obj)); \ |
335 return (structtype *) XPNTR (_obj); \ | 336 return (structtype *) XPNTR (obj); \ |
336 } \ | 337 } \ |
337 extern Lisp_Object Q##c_name##p | 338 extern Lisp_Object Q##c_name##p |
338 | 339 |
339 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ | 340 # define DECLARE_NONRECORD(c_name, type_enum, structtype) \ |
340 INLINE structtype *error_check_##c_name (Lisp_Object _obj); \ | 341 INLINE structtype *error_check_##c_name (Lisp_Object obj); \ |
341 INLINE structtype * \ | 342 INLINE structtype * \ |
342 error_check_##c_name (Lisp_Object _obj) \ | 343 error_check_##c_name (Lisp_Object obj) \ |
343 { \ | 344 { \ |
344 XUNMARK (_obj); \ | 345 XUNMARK (obj); \ |
345 assert (XGCTYPE (_obj) == type_enum); \ | 346 assert (XGCTYPE (obj) == type_enum); \ |
346 return (structtype *) XPNTR (_obj); \ | 347 return (structtype *) XPNTR (obj); \ |
347 } \ | 348 } \ |
348 extern Lisp_Object Q##c_name##p | 349 extern Lisp_Object Q##c_name##p |
349 | 350 |
350 # define XRECORD(x, c_name, structtype) error_check_##c_name (x) | 351 # define XRECORD(x, c_name, structtype) error_check_##c_name (x) |
351 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) | 352 # define XNONRECORD(x, c_name, type_enum, structtype) error_check_##c_name (x) |