diff options
| author | Nick Barnes | 2001-10-31 14:40:56 +0000 |
|---|---|---|
| committer | Nick Barnes | 2001-10-31 14:40:56 +0000 |
| commit | 7acfca905d76140f4cc0b09c9a12de237de364cd (patch) | |
| tree | 3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/message.c | |
| parent | b7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff) | |
| download | emacs-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.c | 396 |
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 | |||
| 19 | SRCID(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 */ | ||
| 28 | static Bool MessageTypeEnabled(Arena arena, MessageType type); | ||
| 29 | static 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 | |||
| 37 | static Bool MessageOnQueue(Message message) | ||
| 38 | { | ||
| 39 | AVERT(Message, message); | ||
| 40 | |||
| 41 | return !RingIsSingle(&message->queueRing); | ||
| 42 | } | ||
| 43 | |||
| 44 | |||
| 45 | /* Checking Functions */ | ||
| 46 | |||
| 47 | |||
| 48 | Bool MessageTypeCheck(MessageType type) | ||
| 49 | { | ||
| 50 | CHECKL(type < MessageTypeLIMIT); | ||
| 51 | UNUSED(type); /* impl.c.mpm.check.unused */ | ||
| 52 | |||
| 53 | return TRUE; | ||
| 54 | } | ||
| 55 | |||
| 56 | |||
| 57 | Bool 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 | |||
| 69 | Bool 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 */ | ||
| 85 | Arena MessageArena(Message message) | ||
| 86 | { | ||
| 87 | AVERT(Message, message); | ||
| 88 | |||
| 89 | return message->arena; | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | /* return the class of a message */ | ||
| 94 | MessageClass MessageGetClass(Message message) | ||
| 95 | { | ||
| 96 | AVERT(Message, message); | ||
| 97 | |||
| 98 | return message->class; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | /* Initialises a message */ | ||
| 103 | void 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 */ | ||
| 122 | void 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 */ | ||
| 133 | void 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 */ | ||
| 151 | static 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 */ | ||
| 161 | MessageType 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 */ | ||
| 176 | Bool 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 */ | ||
| 189 | Bool 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) */ | ||
| 210 | void 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. */ | ||
| 223 | static 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 */ | ||
| 237 | void MessageEmpty(Arena arena) | ||
| 238 | { | ||
| 239 | AVERT(Arena, arena); | ||
| 240 | |||
| 241 | while(!RingIsSingle(&arena->messageRing)) { | ||
| 242 | MessageDeleteHead(arena); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | Bool 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 | |||
| 266 | static 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 | |||
| 275 | void MessageTypeEnable(Arena arena, MessageType type) | ||
| 276 | { | ||
| 277 | AVERT(Arena, arena); | ||
| 278 | AVER(MessageTypeCheck(type)); | ||
| 279 | |||
| 280 | BTSet(arena->enabledMessageTypes, type); | ||
| 281 | } | ||
| 282 | |||
| 283 | |||
| 284 | void 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 */ | ||
| 305 | static void MessageDelete(Message message) | ||
| 306 | { | ||
| 307 | AVERT(Message, message); | ||
| 308 | |||
| 309 | (*message->class->delete)(message); | ||
| 310 | } | ||
| 311 | |||
| 312 | |||
| 313 | /* type specific dispatch methods */ | ||
| 314 | |||
| 315 | void 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 | |||
| 330 | Size MessageGCLiveSize(Message message) | ||
| 331 | { | ||
| 332 | AVERT(Message, message); | ||
| 333 | AVER(message->type == MessageTypeGC); | ||
| 334 | |||
| 335 | return (*message->class->gcLiveSize)(message); | ||
| 336 | } | ||
| 337 | |||
| 338 | Size MessageGCCondemnedSize(Message message) | ||
| 339 | { | ||
| 340 | AVERT(Message, message); | ||
| 341 | AVER(message->type == MessageTypeGC); | ||
| 342 | |||
| 343 | return (*message->class->gcCondemnedSize)(message); | ||
| 344 | } | ||
| 345 | |||
| 346 | Size 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 | |||
| 358 | void 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 | |||
| 368 | Size MessageNoGCLiveSize(Message message) | ||
| 369 | { | ||
| 370 | AVERT(Message, message); | ||
| 371 | UNUSED(message); | ||
| 372 | |||
| 373 | NOTREACHED; | ||
| 374 | |||
| 375 | return (Size)0; | ||
| 376 | } | ||
| 377 | |||
| 378 | Size MessageNoGCCondemnedSize(Message message) | ||
| 379 | { | ||
| 380 | AVERT(Message, message); | ||
| 381 | UNUSED(message); | ||
| 382 | |||
| 383 | NOTREACHED; | ||
| 384 | |||
| 385 | return (Size)0; | ||
| 386 | } | ||
| 387 | |||
| 388 | Size MessageNoGCNotCondemnedSize(Message message) | ||
| 389 | { | ||
| 390 | AVERT(Message, message); | ||
| 391 | UNUSED(message); | ||
| 392 | |||
| 393 | NOTREACHED; | ||
| 394 | |||
| 395 | return (Size)0; | ||
| 396 | } | ||