aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code/message.c
diff options
context:
space:
mode:
authorNick Barnes2001-10-31 14:40:56 +0000
committerNick Barnes2001-10-31 14:40:56 +0000
commit7acfca905d76140f4cc0b09c9a12de237de364cd (patch)
tree3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/message.c
parentb7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff)
downloademacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz
emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip
Branch imports for masters.
Copied from Perforce Change: 23678 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/message.c')
-rw-r--r--mps/code/message.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/mps/code/message.c b/mps/code/message.c
new file mode 100644
index 00000000000..f29af31d258
--- /dev/null
+++ b/mps/code/message.c
@@ -0,0 +1,396 @@
1/* impl.c.message: MPS/CLIENT MESSAGES
2 *
3 * $HopeName: MMsrc!message.c(trunk.10) $
4 * Copyright (C) 1998 Harlequin Limited. All rights reserved.
5 *
6 * DESIGN
7 *
8 * .design: See design.mps.message (it really exists).
9 *
10 * PURPOSE
11 *
12 * .purpose: Provide the generic part of the MPS / Client message
13 * interface. Messages are instances of Message Classes; much of the
14 * "real work" goes on in the modules that provide the actual messages.
15 */
16
17#include "mpm.h"
18
19SRCID(message, "$HopeName: MMsrc!message.c(trunk.10) $");
20
21
22/* Maps from a Ring pointer to the message */
23#define MessageNodeMessage(node) \
24 PARENT(MessageStruct, queueRing, node)
25
26
27/* forward declarations */
28static Bool MessageTypeEnabled(Arena arena, MessageType type);
29static void MessageDelete(Message message);
30
31
32/* MessageOnQueue -- is the message on the queue?
33 *
34 * Message is on queue if and only if its ring is not a singleton.
35 */
36
37static Bool MessageOnQueue(Message message)
38{
39 AVERT(Message, message);
40
41 return !RingIsSingle(&message->queueRing);
42}
43
44
45/* Checking Functions */
46
47
48Bool MessageTypeCheck(MessageType type)
49{
50 CHECKL(type < MessageTypeLIMIT);
51 UNUSED(type); /* impl.c.mpm.check.unused */
52
53 return TRUE;
54}
55
56
57Bool MessageCheck(Message message)
58{
59 CHECKS(Message, message);
60 CHECKU(Arena, message->arena);
61 CHECKL(MessageTypeCheck(message->type));
62 CHECKU(MessageClass, message->class);
63 CHECKL(RingCheck(&message->queueRing));
64
65 return TRUE;
66}
67
68
69Bool MessageClassCheck(MessageClass class)
70{
71 CHECKS(MessageClass, class);
72 CHECKL(class->name != NULL);
73 CHECKL(FUNCHECK(class->delete));
74 CHECKL(FUNCHECK(class->finalizationRef));
75 CHECKL(class->endSig == MessageClassSig);
76
77 return TRUE;
78}
79
80
81/* Internal Functions */
82
83
84/* returns the arena associated with a message */
85Arena MessageArena(Message message)
86{
87 AVERT(Message, message);
88
89 return message->arena;
90}
91
92
93/* return the class of a message */
94MessageClass MessageGetClass(Message message)
95{
96 AVERT(Message, message);
97
98 return message->class;
99}
100
101
102/* Initialises a message */
103void MessageInit(Arena arena, Message message, MessageClass class,
104 MessageType type)
105{
106 AVERT(Arena, arena);
107 AVER(message != NULL);
108 AVERT(MessageClass, class);
109 AVERT(MessageType, type);
110
111 message->arena = arena;
112 message->class = class;
113 RingInit(&message->queueRing);
114 message->type = type;
115 message->sig = MessageSig;
116
117 AVERT(Message, message);
118}
119
120
121/* Finishes a message */
122void MessageFinish(Message message)
123{
124 AVERT(Message, message);
125 AVER(RingIsSingle(&message->queueRing));
126
127 message->sig = SigInvalid;
128 RingFinish(&message->queueRing);
129}
130
131
132/* Posts a message to the arena's queue of pending messages */
133void MessagePost(Arena arena, Message message)
134{
135 AVERT(Arena, arena);
136 AVERT(Message, message);
137
138 /* queueRing field must be a singleton, see */
139 /* design.mps.message.fun.post.singleton */
140 AVER(!MessageOnQueue(message));
141 if(MessageTypeEnabled(arena, message->type)) {
142 RingAppend(&arena->messageRing, &message->queueRing);
143 } else {
144 /* discard message immediately if client hasn't enabled that type */
145 MessageDiscard(arena, message);
146 }
147}
148
149
150/* returns the Message at the head of the queue */
151static Message MessageHead(Arena arena)
152{
153 AVERT(Arena, arena);
154 AVER(!RingIsSingle(&arena->messageRing));
155
156 return MessageNodeMessage(RingNext(&arena->messageRing));
157}
158
159
160/* returns the type of a message */
161MessageType MessageGetType(Message message)
162{
163 AVERT(Message, message);
164
165 return message->type;
166}
167
168
169/* External Functions
170 *
171 * These are actually the internal implementations of functions
172 * exposed through the external interface */
173
174
175/* Determines whether the queue has any messages on it */
176Bool MessagePoll(Arena arena)
177{
178 AVERT(Arena, arena);
179
180 if(RingIsSingle(&arena->messageRing)) {
181 return FALSE;
182 } else {
183 return TRUE;
184 }
185}
186
187
188/* Determines the type of a message at the head of the queue */
189Bool MessageQueueType(MessageType *typeReturn, Arena arena)
190{
191 Message message;
192 MessageType type;
193
194 AVER(typeReturn != NULL);
195 AVERT(Arena, arena);
196
197 if(!MessagePoll(arena)) {
198 return FALSE;
199 }
200 message = MessageHead(arena);
201 type = MessageGetType(message);
202 *typeReturn = type;
203
204 return TRUE;
205}
206
207
208/* Discards a message
209 * (called from external interface) */
210void MessageDiscard(Arena arena, Message message)
211{
212 AVERT(Arena, arena);
213 AVERT(Message, message);
214
215 AVER(!MessageOnQueue(message));
216
217 MessageDelete(message);
218}
219
220
221/* Deletes the message at the head of the queue.
222 * Internal function. */
223static void MessageDeleteHead(Arena arena)
224{
225 Message message;
226
227 AVERT(Arena, arena);
228 AVER(!RingIsSingle(&arena->messageRing));
229
230 message = MessageHead(arena);
231 AVERT(Message, message);
232 RingRemove(&message->queueRing);
233 MessageDelete(message);
234}
235
236/* Empties the queue by discarding all messages */
237void MessageEmpty(Arena arena)
238{
239 AVERT(Arena, arena);
240
241 while(!RingIsSingle(&arena->messageRing)) {
242 MessageDeleteHead(arena);
243 }
244}
245
246Bool MessageGet(Message *messageReturn, Arena arena, MessageType type)
247{
248 Ring node, next;
249
250 AVER(messageReturn != NULL);
251 AVERT(Arena, arena);
252 AVER(MessageTypeCheck(type));
253
254 RING_FOR(node, &arena->messageRing, next) {
255 Message message = RING_ELT(Message, queueRing, node);
256 if(MessageGetType(message) == type) {
257 RingRemove(&message->queueRing);
258 *messageReturn = message;
259 return TRUE;
260 }
261 }
262 return FALSE;
263}
264
265
266static Bool MessageTypeEnabled(Arena arena, MessageType type)
267{
268 AVERT(Arena, arena);
269 AVER(MessageTypeCheck(type));
270
271 return BTGet(arena->enabledMessageTypes, type);
272}
273
274
275void MessageTypeEnable(Arena arena, MessageType type)
276{
277 AVERT(Arena, arena);
278 AVER(MessageTypeCheck(type));
279
280 BTSet(arena->enabledMessageTypes, type);
281}
282
283
284void MessageTypeDisable(Arena arena, MessageType type)
285{
286 Message message;
287
288 AVERT(Arena, arena);
289 AVER(MessageTypeCheck(type));
290
291 /* Flush existing messages of this type */
292 while(MessageGet(&message, arena, type)) {
293 MessageDelete(message);
294 }
295
296 BTRes(arena->enabledMessageTypes, type);
297}
298
299
300
301/* Dispatch Methods */
302
303
304/* generic message delete dispatch */
305static void MessageDelete(Message message)
306{
307 AVERT(Message, message);
308
309 (*message->class->delete)(message);
310}
311
312
313/* type specific dispatch methods */
314
315void MessageFinalizationRef(Ref *refReturn, Arena arena,
316 Message message)
317{
318 AVER(refReturn != NULL);
319 AVERT(Arena, arena);
320 AVERT(Message, message);
321
322 AVER(message->type == MessageTypeFINALIZATION);
323
324 (*message->class->finalizationRef)(refReturn, arena, message);
325
326 return;
327}
328
329
330Size MessageGCLiveSize(Message message)
331{
332 AVERT(Message, message);
333 AVER(message->type == MessageTypeGC);
334
335 return (*message->class->gcLiveSize)(message);
336}
337
338Size MessageGCCondemnedSize(Message message)
339{
340 AVERT(Message, message);
341 AVER(message->type == MessageTypeGC);
342
343 return (*message->class->gcCondemnedSize)(message);
344}
345
346Size MessageGCNotCondemnedSize(Message message)
347{
348 AVERT(Message, message);
349 AVER(message->type == MessageTypeGC);
350
351 return (*message->class->gcNotCondemnedSize)(message);
352}
353
354
355/* type-specific stub methods */
356
357
358void MessageNoFinalizationRef(Ref *refReturn, Arena arena,
359 Message message)
360{
361 AVER(refReturn != NULL);
362 AVERT(Arena, arena);
363 AVERT(Message, message);
364
365 NOTREACHED;
366}
367
368Size MessageNoGCLiveSize(Message message)
369{
370 AVERT(Message, message);
371 UNUSED(message);
372
373 NOTREACHED;
374
375 return (Size)0;
376}
377
378Size MessageNoGCCondemnedSize(Message message)
379{
380 AVERT(Message, message);
381 UNUSED(message);
382
383 NOTREACHED;
384
385 return (Size)0;
386}
387
388Size MessageNoGCNotCondemnedSize(Message message)
389{
390 AVERT(Message, message);
391 UNUSED(message);
392
393 NOTREACHED;
394
395 return (Size)0;
396}