diff --git a/mps/design/message/index.html b/mps/design/message/index.html index 510e8635a76..5ba0e60f5e2 100644 --- a/mps/design/message/index.html +++ b/mps/design/message/index.html @@ -28,7 +28,7 @@ -
This document contains a guide to the MPS Client Message Protocol, followed by the initial design document.
+This document contains a guide to the MPS Client Message Protocol, followed by the historical initial design. References, History, Copyright and License are at the end.
The Message-system does these things:
+Any part of the MPS can be a message Originator.
+Any part of the MPS can be a message Originator. The Originator allocates storage for messages it originates.
Any struct can be a message, as long as it:
Here's an example:
+Here's an example. Notice the embedded MessageStruct:
-typedef struct TraceStartMessageStruct { Sig sig; char why[TRACE_START_MESSAGE_WHY_LEN]; @@ -76,23 +87,58 @@ } TraceStartMessageStruct;
There is no 'copy' method: MessagePost() links this struct into the message queue, and mps_message_get() unlinks it from the queue. The lifecycle is:
+ +The lifecycle of a Message is:
- -(alloc Init) unsent (Post) queued (Get) received (Discard Delete Finish free)
The struct is a message between Init and Finish. The message system does not distinguish between "unsent" and "received" states, but the Originator may do.
-The message remains "in use" by the client until its Delete() method is called. The Originator cannot free the struct; and if it re-uses the struct it may overwrite fields of a message the Client is looking at.
+The struct is a valid message between Init and Finish.
-The two common allocation strategies for message structs are:
+MessagePost() simply links the struct into the message queue (using a RingStruct inside the MessageStruct): no copying occurs. The message is now queued, and MessageOnQueue() returns true. The Originator must not free a queued message, or the Message-system will get upset. Outside this time, the Message-system doesn't care if the message vanishes.
+ +When/if the client calls mps_message_get(), the Message-system simply unlinks the message from the queue. The message is now received, and is in use by the client.
+ +When/if the Client calls mps_message_discard(), the Message-system simply calls through to the Originator-supplied Delete method. The Originator may call Finish and free. Or it may recycle the message to unsent by calling Init.
+ +[Note: the Message-system does not distinguish between unsent and received states, so this recycling is not currently safe. See note below. RHSK 2006-12-11]
+ +The Originator must not free a queued or received message; and it should not edit the message, or the Client may see inconsistent data.
+ +If the Client has not enabled messages of this type (with mps_message_type_enable), Posting the message immediately Discards it, which calls the Delete method. The Originator's Delete method must be safe to call from wherever the Originator calls MessagePost().
+ +Here's a selection of lifecycles:
+ ++ +(alloc Init) unsent (Post) queued (Get) received (Discard Delete Finish free) -- typical
+ +(alloc [ Init) unsent (Post) queued (Get) received (Discard Delete ] -- Originator reuses message struct
+ +... Init) unsent (Post Discard Delete) -- client did not enable this message type
+ +... Init) unsent (Post) queued -- client never gets message
+ +... Init) unsent (Post) queued (Get) received -- client never discards message
Messages can also be dropped from the queue if the client calls mps_message_type_disable() when there are already some messages of that type queued, or if MessageEmpty() is called:
+ ++ + +... Init) unsent (Post) queued (Discard Delete ... -- killing messages
The Originator allocates the message struct. The two common allocation strategies are:
Pre-allocate the message struct when allocating the subject it will refer to. Note that this means you can only have one message in use per subject. (Used for finalization messages).
Pre-allocate the message struct when allocating the subject it will refer to. Note that this means you can only have one message in use per subject. (Used for finalization messages and trace start messages).
Allocate the message struct (from control pool) immediately before posting, and free it in the Delete method. (Used for GC-Complete messages).
[Note: the Message-system does not currently support re-using message structs, because it does not distinguish between unsent and received states. If Originators would like to safely re-use a message once the client has finished with it (TraceStart messages are the current example), the lifecycle state variable, and check code to do this safely, should be added to the Message-system. RHSK 2006-12-11]
+ +
MPS TO CLIENT MESSAGE PROTOCOL
@@ -436,23 +482,20 @@ This subsection is a sketch of how PoolMRG will use Messages for finalization
PoolMRG has guardians (see design.mps.poolmrg.guardian), guardians are used to
manage final references and detect when an object is finalizable.
-The link part of a guardian will be expanded to include a MessageStruct; in
-fact the link part of a guardian will be expanded so that it is exactly a
-MessageStruct (or rather a structure with a single member that has the type
-MessageStruct).
+The link part of a guardian will include a MessageStruct.
The MessageStruct is allocated when the final reference is created (which is
when the referred to object is registered for finalization). This avoids
allocating at the time when the message gets posted (which might be a tricky,
undesirable, or impossible, time to allocate).
-The two queues of PoolMRG (the entry queue, and the exit queue) will use the
-MessageStruct ring node. Before the object (referred to by the guardian) is
-finalizable the MessageStruct is not needed by the Message system (there is no
-message to send yet!), so it is okay to use the Message's ring node to attach
-the guardian to the entry queue (see
-design.mps.poolmrg.guardian.two-part.justify). The exit queue of MRG will
-simply be the external message queue.
+PoolMRG has two queues: the entry queue, and the exit queue. The entry
+queue will use a ring; the exit queue of MRG will simply be the
+external message queue.
+
+[The evil hack of 'borrowing' MessageStruct's ring node for the entry
+queue was removed from the code ages ago, so I've removed the account
+of it from this text too. RHSK 2006-12-11]
MRG Message class
@@ -460,6 +503,8 @@ del - frees both the link part and the reference part of the guardian.
+| 2002-06-07 | -RB | -Converted from MMInfo database design document. | +
| 2006-10-25 | +RHSK | +Created guide. | +
| 2006-12-11 | +RHSK | +More on lifecycle; unmention evil hack in initial design. |
This document is copyright © 1995-2002 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.
+This document is copyright © 1995-2002, 2006 Ravenbrook Limited. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: