mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-16 08:10:43 -08:00
Mps: design/message: tidy the new guide section; more on lifecycle; unmention evil hack in initial design
Copied from Perforce Change: 161190 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
026eb20c99
commit
789abf317b
1 changed files with 79 additions and 26 deletions
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
<p>This document contains a <a href="#guide">guide</a> to the MPS Client Message Protocol, followed by the <a href="#initial-design">initial design document</a>.</p>
|
||||
<p>This document contains a <a href="#guide">guide</a> to the MPS Client Message Protocol, followed by the historical <a href="#initial-design">initial design</a>. References, History, Copyright and License are <a href="#section-A">at the end</a>.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
|
|
@ -56,9 +56,20 @@
|
|||
<li> calls mps_message_discard() when it has finished using the message.</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<h2> The Message-system </h2>
|
||||
|
||||
<p>The Message-system does these things:</p>
|
||||
<ul>
|
||||
<li>class-based method dispatch on any valid message (methods: Delete, slot accessors);</li>
|
||||
<li>queue for messages that have been Posted but not yet Got;</li>
|
||||
<li>maintains message lifecycle information (a minimal amount, currently).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2> Using the Internal Interface </h2>
|
||||
|
||||
<p>Any part of the MPS can be a message Originator.</p>
|
||||
<p>Any part of the MPS can be a message Originator. The Originator allocates storage for messages it originates.</p>
|
||||
|
||||
<p>Any struct can be a message, as long as it:</p>
|
||||
<ul>
|
||||
|
|
@ -68,7 +79,7 @@
|
|||
<li> has appropriate accessor functions. </li>
|
||||
</ul>
|
||||
|
||||
<p>Here's an example:</p>
|
||||
<p>Here's an example. Notice the embedded MessageStruct:</p>
|
||||
<blockquote><pre><code>typedef struct TraceStartMessageStruct {
|
||||
Sig sig;
|
||||
char why[TRACE_START_MESSAGE_WHY_LEN];
|
||||
|
|
@ -76,23 +87,58 @@
|
|||
} TraceStartMessageStruct;
|
||||
</code></pre></blockquote>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<h3>Lifecycle</h3>
|
||||
|
||||
<p>The lifecycle of a Message is:</p>
|
||||
|
||||
<blockquote><p> (alloc Init) <strong>unsent</strong> (Post) <strong>queued</strong> (Get) <strong>received</strong> (Discard Delete Finish free)</p></blockquote>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
<p>The struct is a <strong>valid</strong> message between Init and Finish.</p>
|
||||
|
||||
<p>The two common allocation strategies for message structs are:</p>
|
||||
<p>MessagePost() simply links the struct into the message queue (using a RingStruct inside the MessageStruct): no copying occurs. The message is now <strong>queued</strong>, 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.</p>
|
||||
|
||||
<p>When/if the client calls mps_message_get(), the Message-system simply unlinks the message from the queue. The message is now <strong>received</strong>, and is in use by the client.</p>
|
||||
|
||||
<p>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 <strong>unsent</strong> by calling Init.</p>
|
||||
|
||||
<p><em class="note">[Note: the Message-system does not distinguish between <strong>unsent</strong> and <strong>received</strong> states, so this recycling is not currently safe. See <a href="#note-reuse-message">note</a> below. RHSK 2006-12-11]</em></p>
|
||||
|
||||
<p>The Originator must not free a <strong>queued</strong> or <strong>received</strong> message; and it should not edit the message, or the Client may see inconsistent data.</p>
|
||||
|
||||
<p>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().</p>
|
||||
|
||||
<p>Here's a selection of lifecycles:</p>
|
||||
|
||||
<blockquote><p> (alloc Init) <strong>unsent</strong> (Post) <strong>queued</strong> (Get) <strong>received</strong> (Discard Delete Finish free) -- typical</p></blockquote>
|
||||
|
||||
<blockquote><p> (alloc <strong>[</strong> Init) <strong>unsent</strong> (Post) <strong>queued</strong> (Get) <strong>received</strong> (Discard Delete <strong>]</strong> -- Originator reuses message struct</p></blockquote>
|
||||
|
||||
<blockquote><p> ... Init) <strong>unsent</strong> (Post Discard Delete) -- client did not enable this message type</p></blockquote>
|
||||
|
||||
<blockquote><p> ... Init) <strong>unsent</strong> (Post) <strong>queued</strong> -- client never gets message</p></blockquote>
|
||||
|
||||
<blockquote><p> ... Init) <strong>unsent</strong> (Post) <strong>queued</strong> (Get) <strong>received</strong> -- client never discards message</p></blockquote>
|
||||
|
||||
<p>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:</p>
|
||||
|
||||
<blockquote><p> ... Init) <strong>unsent</strong> (Post) <strong>queued</strong> (Discard Delete ... -- killing messages</p></blockquote>
|
||||
|
||||
|
||||
<h3>Allocation strategy</h3>
|
||||
|
||||
<p>The Originator allocates the message struct. The two common allocation strategies are:</p>
|
||||
<ul>
|
||||
<li><p> 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).</p></li>
|
||||
<li><p> 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).</p></li>
|
||||
<li><p> Allocate the message struct (from control pool) immediately before posting, and free it in the Delete method. (Used for GC-Complete messages).</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p><em class="note" id="note-reuse-message">[Note: the Message-system does not currently support re-using message structs, because it does not distinguish between <strong>unsent</strong> and <strong>received</strong> 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]</em></p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<h1> <a id="initial-design">Initial Design Document</a> </h1>
|
||||
<h1> <a id="initial-design">Initial Design</a> </h1>
|
||||
|
||||
<pre>
|
||||
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.
|
|||
|
||||
</pre>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
<h2><a id="section-A" name="section-A">A. References</a></h2>
|
||||
|
||||
|
|
@ -490,13 +535,21 @@ del - frees both the link part and the reference part of the guardian.
|
|||
<table>
|
||||
|
||||
<tr valign="top">
|
||||
|
||||
<td>2002-06-07</td>
|
||||
|
||||
<td><a href="mailto:rb@ravenbrook.com">RB</a></td>
|
||||
|
||||
<td>Converted from MMInfo database design document.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td>2006-10-25</td>
|
||||
<td><a href="mailto:rhsk@ravenbrook.com">RHSK</a></td>
|
||||
<td>Created guide.</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<td>2006-12-11</td>
|
||||
<td><a href="mailto:rhsk@ravenbrook.com">RHSK</a></td>
|
||||
<td>More on lifecycle; unmention evil hack in initial design.</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
|
@ -504,7 +557,7 @@ del - frees both the link part and the reference part of the guardian.
|
|||
|
||||
<h2><a id="section-C" name="section-C">C. Copyright and License</a></h2>
|
||||
|
||||
<p> This document is copyright © 1995-2002 <a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. </p>
|
||||
<p> This document is copyright © 1995-2002, 2006 <a href="http://www.ravenbrook.com/">Ravenbrook Limited</a>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. </p>
|
||||
|
||||
<p> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: </p>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue