1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-13 06:50:39 -08:00
emacs/mps/manual/html/design/protocol.html
Gareth Rees c5f77afc19 Bring html up to date for the mps manual.
Copied from Perforce
 Change: 181433
 ServerID: perforce.ravenbrook.com
2013-04-24 12:21:37 +01:00

587 lines
No EOL
50 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>16. Protocol inheritance &mdash; Memory Pool System 1.111.0 documentation</title>
<link rel="stylesheet" href="../_static/mps.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.111.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
<link rel="up" title="Design" href="index.html" />
<link rel="next" title="17. General MPS types" href="type.html" />
<link rel="prev" title="15. Debugging features for client objects" href="object-debug.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="type.html" title="17. General MPS types"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="object-debug.html" title="15. Debugging features for client objects"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" accesskey="U">Design</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="protocol-inheritance">
<span id="design.mps.protocol"></span><h1>16. Protocol inheritance<a class="headerlink" href="#protocol-inheritance" title="Permalink to this headline"></a></h1>
<div class="section" id="introduction">
<h2>16.1. Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.intro"></span><a class="mpstag reference internal" href="#design.mps.protocol.intro">.intro:</a> This document explains the design of the support for
class inheritance in MPS. It is not yet complete. It describes support
for single inheritance of classes. Future extensions will describe
multiple inheritance and the relationship between instances and
classes.</p>
<p><span class="target" id="design.mps.protocol.readership"></span><a class="mpstag reference internal" href="#design.mps.protocol.readership">.readership:</a> This document is intended for any MPS developer.</p>
</div>
<div class="section" id="history">
<h2>16.2. History<a class="headerlink" href="#history" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.hist.0"></span><a class="mpstag reference internal" href="#design.mps.protocol.hist.0">.hist.0:</a> Written by Tony 1998-10-12</p>
</div>
<div class="section" id="purpose">
<h2>16.3. Purpose<a class="headerlink" href="#purpose" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.purpose.code-maintain"></span><a class="mpstag reference internal" href="#design.mps.protocol.purpose.code-maintain">.purpose.code-maintain:</a> The purpose of the protocol
inheritance design is to ensure that the MPS code base can make use of
the benefits of object-oriented class inheritance to maximize code
reuse, minimize code maintenance and minimize the use of boilerplate
code.</p>
<p><span class="target" id="design.mps.protocol.purpose.related"></span><a class="mpstag reference internal" href="#design.mps.protocol.purpose.related">.purpose.related:</a> For related discussion, see
mail.tony.1998-08-28.16-26(0), mail.tony.1998-09-01.11-38(0),
mail.tony.1998-10-06.11-03(0) and other messages in the same threads.</p>
</div>
<div class="section" id="requirements">
<h2>16.4. Requirements<a class="headerlink" href="#requirements" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.req.implicit"></span><a class="mpstag reference internal" href="#design.mps.protocol.req.implicit">.req.implicit:</a> The object system should provide a means for
classes to inherit the methods of their direct superclasses implicitly
for all functions in the protocol without having to write any explicit
code for each inherited function.</p>
<p><span class="target" id="design.mps.protocol.req.override"></span><a class="mpstag reference internal" href="#design.mps.protocol.req.override">.req.override:</a> There must additionally be a way for classes
to override the methods of their superclasses.</p>
<p><span class="target" id="design.mps.protocol.req.next-method"></span><a class="mpstag reference internal" href="#design.mps.protocol.req.next-method">.req.next-method:</a> As a result of <a class="reference internal" href="#design.mps.protocol.req.implicit">.req.implicit</a>,
classes cannot make static assumptions about methods used by direct
superclasses. The object system must provide a means for classes to
extend (not just replace) the behaviour of protocol functions, such as
a mechanism for invoking the &#8220;next-method&#8221;.</p>
<p><span class="target" id="design.mps.protocol.req.ideal.extend"></span><a class="mpstag reference internal" href="#design.mps.protocol.req.ideal.extend">.req.ideal.extend:</a> The object system must provide a standard
way for classes to implement the protocol supported by they superclass
and additionally add new methods of their own which can be specialized
by subclasses.</p>
<p><span class="target" id="design.mps.protocol.req.ideal.multiple-inheritance"></span><a class="mpstag reference internal" href="#design.mps.protocol.req.ideal.multiple-inheritance">.req.ideal.multiple-inheritance:</a> The object system should
support multiple inheritance such that sub-protocols can be &#8220;mixed in&#8221;
with several classes which do not themselves support identical
protocols.</p>
</div>
<div class="section" id="overview">
<h2>16.5. Overview<a class="headerlink" href="#overview" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.overview.root"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.root">.overview.root:</a> We start with the root of all conformant
class hierarchies, which is called <tt class="xref c c-type docutils literal"><span class="pre">ProtocolClass</span></tt>. This is an
&#8220;abstract&#8221; class (that is, it has no direct instances, but it is
intended to have subclasses). To use Dylan terminology, instances of
its subclasses are &#8220;general&#8221; instances of ProtocolClass. They look
like this:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="n">Instance</span> <span class="n">Object</span> <span class="n">Class</span> <span class="n">Object</span>
<span class="o">--------------------</span> <span class="o">--------------------</span>
<span class="o">|</span> <span class="n">sig</span> <span class="o">|</span> <span class="o">|--------&gt;|</span> <span class="n">sig</span> <span class="o">|</span>
<span class="o">--------------------</span> <span class="o">|</span> <span class="o">--------------------</span>
<span class="o">|</span> <span class="n">class</span> <span class="o">|----|</span> <span class="o">|</span> <span class="n">superclass</span> <span class="o">|</span>
<span class="o">--------------------</span> <span class="o">--------------------</span>
<span class="o">|</span> <span class="p">...</span> <span class="o">|</span> <span class="o">|</span> <span class="n">coerceInst</span> <span class="o">|</span>
<span class="o">--------------------</span> <span class="o">--------------------</span>
<span class="o">|</span> <span class="p">...</span> <span class="o">|</span> <span class="o">|</span> <span class="n">coerceClass</span> <span class="o">|</span>
<span class="o">--------------------</span> <span class="o">--------------------</span>
<span class="o">|</span> <span class="o">|</span> <span class="o">|</span> <span class="p">...</span> <span class="o">|</span>
</pre></div>
</div>
<p><span class="target" id="design.mps.protocol.overview.inherit"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.inherit">.overview.inherit:</a> Classes inherit the protocols supported by
their superclasses. By default they have the same methods as the
class(es) from which they inherit.</p>
<p><span class="target" id="design.mps.protocol.overview.inherit.specialize"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.inherit.specialize">.overview.inherit.specialize:</a> Classes may specialize the
behaviour of their superclass. They do this by by overriding methods
or other fields in the class object.</p>
<p><span class="target" id="design.mps.protocol.overview.extend"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.extend">.overview.extend:</a> Classes may extend the protocols supported
by their superclasses by adding new fields for methods or other data.</p>
<p><span class="target" id="design.mps.protocol.overview.sig.inherit"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.sig.inherit">.overview.sig.inherit:</a> Classes will contain (possibly
several) signatures. Classes must not specialize (override) the
signatures they inherit from their superclasses.</p>
<p><span class="target" id="design.mps.protocol.overview.sig.extend"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.sig.extend">.overview.sig.extend:</a> If a class definition extends a
protocol, it is normal policy for the class definition to include a
new signature as the last field in the class object.</p>
<p><span class="target" id="design.mps.protocol.overview.coerce-class"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.coerce-class">.overview.coerce-class:</a> Each class contains a <tt class="docutils literal"><span class="pre">coerceClass</span></tt>
field. This contains a method which can find the part of the class
object which implements the protocols of a supplied superclass
argument (if, indeed, the argument <em>is</em> a superclass). This function
may be used for testing subclass/superclass relationships, and it also
provides support for multiple inheritance.</p>
<p><span class="target" id="design.mps.protocol.overview.coerce-inst"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.coerce-inst">.overview.coerce-inst:</a> Each class contains a <tt class="docutils literal"><span class="pre">coerceInst</span></tt>
field. This contains a method which can find the part of an instance
object which contains the instance slots of a supplied superclass
argument (if, indeed, the argument <em>is</em> a superclass). This function
may be used for testing whether an object is an instance of a given
class, and it also provides support for multiple inheritance.</p>
<p><span class="target" id="design.mps.protocol.overview.superclass"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.superclass">.overview.superclass:</a> Each class contains a <tt class="docutils literal"><span class="pre">superclass</span></tt>
field. This enables classes to call &#8220;next-method&#8221;, as well as enabling
the coercion functions.</p>
<p><span class="target" id="design.mps.protocol.overview.next-method"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.next-method">.overview.next-method:</a> A specialized method in a class can
make use of an overridden method from a superclass by accessing the
method from the appropriate field in the superclass object and calling
it. The superclass may be accessed indirectly from the class&#8217;s
&#8220;Ensure&#8221; function when it is statically known (see
<a class="reference internal" href="#design.mps.protocol.overview.access">.overview.access</a>). This permits &#8220;next-method&#8221; calls, and
is fully scalable in that it allows arbitrary length method chains.
The <tt class="xref c c-func docutils literal"><span class="pre">SUPERCLASS()</span></tt> macro helps with this (see
<a class="reference internal" href="#design.mps.protocol.int.static-superclass">.int.static-superclass</a>).</p>
<p><span class="target" id="design.mps.protocol.overview.next-method.naive"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.next-method.naive">.overview.next-method.naive:</a> In some cases it is necessary to
write a method which is designed to specialize an inherited method,
needs to call the next-method, and yet the implementation doesn&#8217;t have
static knowledge of the superclass. This might happen because the
specialized method is designed to be reusable by many class
definitions. The specialized method can usually locate the class
object from one of the parameters passed to the method. It can then
access the superclass through the <tt class="docutils literal"><span class="pre">superclass</span></tt> field of the class,
and hence call the next method. This technique has some limitations
and doesn&#8217;t support longer method chains. It is also dependent on none
of the class definitions which use the method having any subclasses.</p>
<p><span class="target" id="design.mps.protocol.overview.access"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.access">.overview.access:</a> Classes must be initialized by calls to
functions, since it is these function calls which copy properties from
superclasses. Each class must provide an &#8220;Ensure&#8221; function, which
returns the canonical copy of the class. The canonical copy may reside
in static storage, but no MPS code may refer to that static storage by
name.</p>
<p><span class="target" id="design.mps.protocol.overview.naming"></span><a class="mpstag reference internal" href="#design.mps.protocol.overview.naming">.overview.naming:</a> There are some strict naming conventions
which must be followed when defining and using classes. The use is
obligatory because it is assumed by the macros which support the
definition and inheritance mechanism. For every class <tt class="docutils literal"><span class="pre">SomeClass</span></tt>,
we insist upon the following naming conventions:-</p>
<p><tt class="docutils literal"><span class="pre">SomeClassStruct</span></tt></p>
<blockquote>
<div>names the type of the structure for the protocol class. This might
be a <tt class="docutils literal"><span class="pre">typedef</span></tt> which aliases the type to the type of the
superclass, but if the class has extended the protocols of the
superclass the it will be a type which contains the new class
fields.</div></blockquote>
<p><tt class="docutils literal"><span class="pre">SomeClass</span></tt></p>
<blockquote>
<div>names the type <tt class="docutils literal"><span class="pre">*SomeClassStruct</span></tt>. This might be a <tt class="docutils literal"><span class="pre">typedef</span></tt>
which aliases the type to the type of the superclass, but if the
class has extended the protocols of the superclass then it will be
a type which contains the new class fields.</div></blockquote>
<p><tt class="docutils literal"><span class="pre">EnsureSomeClass()</span></tt></p>
<blockquote>
<div>names the function that returns the initialized class object.</div></blockquote>
</div>
<div class="section" id="interface">
<h2>16.6. Interface<a class="headerlink" href="#interface" title="Permalink to this headline"></a></h2>
<div class="section" id="class-definition">
<h3>16.6.1. Class definition<a class="headerlink" href="#class-definition" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.int.define-class"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.define-class">.int.define-class:</a> Class definition is performed by the macro
<tt class="docutils literal"><span class="pre">DEFINE_CLASS(className,</span> <span class="pre">var)</span></tt>. A call to the macro must be followed
by a body of initialization code in braces <tt class="docutils literal"><span class="pre">{}</span></tt>. The parameter
<tt class="docutils literal"><span class="pre">className</span></tt> is used to name the class being defined. The parameter
<tt class="docutils literal"><span class="pre">var</span></tt> is used to name a local variable of type <tt class="docutils literal"><span class="pre">className</span></tt>, which
is defined by the macro; it refers to the canonical storage for the
class being defined. This variable may be used in the initialization
code. (The macro doesn&#8217;t just pick a name implicitly because of the
danger of a name clash with other names used by the programmer). A
call to <tt class="docutils literal"><span class="pre">DEFINE_CLASS(SomeClass,</span> <span class="pre">var)</span></tt> defines the
<tt class="docutils literal"><span class="pre">EnsureSomeClass()</span></tt> function, defines some static storage for the
canonical class object, and defines some other things to ensure the
class gets initialized exactly once.</p>
<p><span class="target" id="design.mps.protocol.int.define-alias-class"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.define-alias-class">.int.define-alias-class:</a> A convenience macro
<tt class="xref c c-func docutils literal"><span class="pre">DEFINE_ALIAS_CLASS()</span></tt> is provided which both performs the class
definition and defines the types <tt class="docutils literal"><span class="pre">SomeClass</span></tt> and <tt class="docutils literal"><span class="pre">SomeClass</span>
<span class="pre">struct</span></tt> as aliases for some other class types. This is particularly
useful for classes which simply inherit, and don&#8217;t extend protocols.
The macro call <tt class="docutils literal"><span class="pre">DEFINE_ALIAS_CLASS(className,</span> <span class="pre">superName,</span> <span class="pre">var)</span></tt> is
exactly equivalent to the following:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="n">superName</span> <span class="n">className</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">superNameStruct</span> <span class="n">classNameStruct</span><span class="p">;</span>
<span class="n">DEFINE_CLASS</span><span class="p">(</span><span class="n">className</span><span class="p">,</span> <span class="n">var</span><span class="p">)</span>
</pre></div>
</div>
<p><span class="target" id="design.mps.protocol.int.define-special"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.define-special">.int.define-special:</a> If classes are particularly likely to be
subclassed without extension, the class implementor may choose to
provide a convenience macro which expands into
<tt class="xref c c-func docutils literal"><span class="pre">DEFINE_ALIAS_CLASS()</span></tt> with an appropriate name for the
superclass. For example, there might be a macro for defining pool
classes such that the macro call <tt class="docutils literal"><span class="pre">DEFINE_POOL_CLASS(className,</span> <span class="pre">var)</span></tt>
is exactly equivalent to the macro call
<tt class="docutils literal"><span class="pre">DEFINE_ALIAS_CLASS(className,</span> <span class="pre">PoolClass,</span> <span class="pre">var)</span></tt>. It may also be
convenient to define a static superclass accessor macro at the same
time (see <a class="reference internal" href="#design.mps.protocol.int.static-superclass.special">.int.static-superclass.special</a>).</p>
</div>
<div class="section" id="single-inheritance">
<h3>16.6.2. Single inheritance<a class="headerlink" href="#single-inheritance" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.int.inheritance"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.inheritance">.int.inheritance:</a> Class inheritance details must be provided
in the class initialization code (see <a class="reference internal" href="#design.mps.protocol.int.define-class">.int.define-class</a>).
Inheritance is performed by the macro
<tt class="docutils literal"><span class="pre">INHERIT_CLASS(thisClassCoerced,</span> <span class="pre">parentClassName)</span></tt>. A call to this
macro will make the class being defined a direct subclass of
<tt class="docutils literal"><span class="pre">parentClassName</span></tt> by ensuring that all the fields of the parent
class are copied into <tt class="docutils literal"><span class="pre">thisClass</span></tt>, and setting the superclass field
of <tt class="docutils literal"><span class="pre">thisClass</span></tt> to be the parent class object. The parameter
<tt class="docutils literal"><span class="pre">thisClassCoerced</span></tt> must be of type <tt class="docutils literal"><span class="pre">parentClassName</span></tt>. If the class
definition defines an alias class (see
<a class="reference internal" href="#design.mps.protocol.int.define-alias-class">.int.define-alias-class</a>), then the variable named as the
second parameter to <tt class="xref c c-func docutils literal"><span class="pre">DEFINE_CLASS()</span></tt> will be appropriate to pass
to <tt class="xref c c-func docutils literal"><span class="pre">INHERIT_CLASS()</span></tt>.</p>
</div>
<div class="section" id="specialization">
<h3>16.6.3. Specialization<a class="headerlink" href="#specialization" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.int.specialize"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.specialize">.int.specialize:</a> Class specialization details must be given
explicitly in the class initialization code (see
<a class="reference internal" href="#design.mps.protocol.int.define-class">.int.define-class</a>). This must happen <em>after</em> the
inheritance details are given (see <a class="reference internal" href="#design.mps.protocol.int.inheritance">.int.inheritance</a>).</p>
</div>
<div class="section" id="extension">
<h3>16.6.4. Extension<a class="headerlink" href="#extension" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.int.extend"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.extend">.int.extend:</a> To extend the protocol when defining a new
class, a new type must be defined for the class structure. This must
embed the structure for the primarily inherited class as the first
field of the structure. Class extension details must be given
explicitly in the class initialization code (see
<a class="reference internal" href="#design.mps.protocol.int.define-class">.int.define-class</a>). This must happen <em>after</em> the
inheritance details are given (see <a class="reference internal" href="#design.mps.protocol.int.inheritance">.int.inheritance</a>).</p>
</div>
<div class="section" id="introspection">
<h3>16.6.5. Introspection<a class="headerlink" href="#introspection" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.introspect.c-lang"></span><a class="mpstag reference internal" href="#design.mps.protocol.introspect.c-lang">.introspect.c-lang:</a> The design includes a number of
introspection functions for dynamically examining class relationships.
These functions are polymorphic and accept arbitrary subclasses of
<tt class="xref c c-type docutils literal"><span class="pre">ProtocolClass</span></tt>. C doesn&#8217;t support such polymorphism. So
although these have the semantics of functions (and could be
implemented as functions in another language with compatible calling
conventions) they are actually implemented as macros. The macros are
named as method-style macros despite the fact that this arguably
contravenes guide.impl.c.macro.method. The justification
for this is that this design is intended to promote the use of
polymorphism, and it breaks the abstraction for the users to need to
be aware of what can and can&#8217;t be expressed directly in C function
syntax. These functions all have names ending in <tt class="docutils literal"><span class="pre">Poly</span></tt> to identify
them as polymorphic functions.</p>
<p><span class="target" id="design.mps.protocol.int.superclass"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.superclass">.int.superclass:</a> <tt class="docutils literal"><span class="pre">ProtocolClassSuperclassPoly(class)</span></tt> is an
introspection function which returns the direct superclass of class
object class.</p>
<p><span class="target" id="design.mps.protocol.int.static-superclass"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.static-superclass">.int.static-superclass:</a> <tt class="docutils literal"><span class="pre">SUPERCLASS(className)</span></tt> is an
introspection macro which returns the direct superclass given a class
name, which must (obviously) be statically known. The macro expands
into a call to the ensure function for the class name, so this must be
in scope (which may require a forward declaration). The macro is
useful for next-method calls (see <a class="reference internal" href="#design.mps.protocol.overview.next-method">.overview.next-method</a>).
The superclass is returned with type <tt class="xref c c-type docutils literal"><span class="pre">ProtocolClass</span></tt> so it may
be necessary to cast it to the type for the appropriate subclass.</p>
<p><span class="target" id="design.mps.protocol.int.static-superclass.special"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.static-superclass.special">.int.static-superclass.special:</a> Implementors of classes which
are designed to be subclassed without extension may choose to provide
a convenience macro which expands into a call to <tt class="xref c c-func docutils literal"><span class="pre">SUPERCLASS()</span></tt>
along with a type cast. For example, there might be a macro for
finding pool superclasses such that the macro call
<tt class="docutils literal"><span class="pre">POOL_SUPERCLASS(className)</span></tt> is exactly equivalent to
<tt class="docutils literal"><span class="pre">(PoolClass)SUPERCLASS(className)</span></tt>. It&#8217;s convenient to define these
macros alongside the convenience class definition macro (see
<a class="reference internal" href="#design.mps.protocol.int.define-special">.int.define-special</a>).</p>
<p><span class="target" id="design.mps.protocol.int.class"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.class">.int.class:</a> <tt class="docutils literal"><span class="pre">ClassOfPoly(inst)</span></tt> is an introspection
function which returns the class of which inst is a direct instance.</p>
<p><span class="target" id="design.mps.protocol.int.subclass"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.subclass">.int.subclass:</a> <tt class="docutils literal"><span class="pre">IsSubclassPoly(sub,</span> <span class="pre">super)</span></tt> is an
introspection function which returns a Boolean indicating whether sub
is a subclass of super. That is, it is a predicate for testing
subclass relationships.</p>
</div>
<div class="section" id="multiple-inheritance">
<h3>16.6.6. Multiple inheritance<a class="headerlink" href="#multiple-inheritance" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.int.mult-inherit"></span><a class="mpstag reference internal" href="#design.mps.protocol.int.mult-inherit">.int.mult-inherit:</a> Multiple inheritance involves an extension
of the protocol (see <a class="reference internal" href="#design.mps.protocol.int.extend">.int.extend</a>) and also multiple uses
of the single inheritance mechanism (see
<a class="reference internal" href="#design.mps.protocol.int.inheritance">.int.inheritance</a>). It also requires specialized methods
for <tt class="xref c c-func docutils literal"><span class="pre">coerceClass()</span></tt> and <tt class="xref c c-func docutils literal"><span class="pre">coerceInst()</span></tt> to be written (see
<a class="reference internal" href="#design.mps.protocol.overview.coerce-class">.overview.coerce-class</a> and
<a class="reference internal" href="#design.mps.protocol.overview.coerce-inst">.overview.coerce-inst</a>). Documentation on support for
multiple inheritance is under construction. This facility is not
currently used. The basic idea is described in
mail.tony.1998-10-06.11-03(0).</p>
</div>
<div class="section" id="protocol-guidelines">
<h3>16.6.7. Protocol guidelines<a class="headerlink" href="#protocol-guidelines" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.guide.fail"></span><a class="mpstag reference internal" href="#design.mps.protocol.guide.fail">.guide.fail:</a> When designing an extensible function which
might fail, the design must permit the correct implementation of the
failure-case code. Typically, a failure might occur in any method in
the chain. Each method is responsible for correctly propagating
failure information supplied by superclass methods and for managing
it&#8217;s own failures.</p>
<p><span class="target" id="design.mps.protocol.guide.fail.before-next"></span><a class="mpstag reference internal" href="#design.mps.protocol.guide.fail.before-next">.guide.fail.before-next:</a> Dealing with a failure which is
detected before any next-method call is made is similar to a fail case
in any non-extensible function. See <a class="reference internal" href="#design.mps.protocol.example.fail">.example.fail</a> below.</p>
<p><span class="target" id="design.mps.protocol.guide.fail.during-next"></span><a class="mpstag reference internal" href="#design.mps.protocol.guide.fail.during-next">.guide.fail.during-next:</a> Dealing with a failure returned from
a next-method call is also similar to a fail case in any
non-extensible function. See <a class="reference internal" href="#design.mps.protocol.example.fail">.example.fail</a> below.</p>
<p><span class="target" id="design.mps.protocol.guide.fail.after-next"></span><a class="mpstag reference internal" href="#design.mps.protocol.guide.fail.after-next">.guide.fail.after-next:</a> Dealing with a failure which is
detected after the next methods have been successfully invoked is more
complex. If this scenario is possible, the design must include an
&#8220;anti-function&#8221;, and each class must ensure that it provides a method
for the anti-method which will clean up any resources which are
claimed after a successful invocation of the main method for that
class. Typically the anti-function would exist anyway for clients of
the protocol (for example, &#8220;finish&#8221; is an anti-function for &#8220;init&#8221;).
The effect of the next-method call can then be cleaned up by calling
the anti-method for the superclass. See <a class="reference internal" href="#design.mps.protocol.example.fail">.example.fail</a>
below.</p>
</div>
<div class="section" id="example">
<h3>16.6.8. Example<a class="headerlink" href="#example" title="Permalink to this headline"></a></h3>
<p><span class="target" id="design.mps.protocol.example.inheritance"></span><a class="mpstag reference internal" href="#design.mps.protocol.example.inheritance">.example.inheritance:</a> The following example class definition
shows both inheritance and specialization. It shows the definition of
the class <tt class="docutils literal"><span class="pre">EPDRPoolClass</span></tt>, which inherits from <tt class="docutils literal"><span class="pre">EPDLPoolClass</span></tt> and
has specialized values of the <tt class="docutils literal"><span class="pre">name</span></tt>, <tt class="docutils literal"><span class="pre">init</span></tt>, and <tt class="docutils literal"><span class="pre">alloc</span></tt>
fields. The type <tt class="docutils literal"><span class="pre">EPDLPoolClass</span></tt> is an alias for
<tt class="xref c c-type docutils literal"><span class="pre">PoolClass</span></tt>.</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="n">EPDLPoolClass</span> <span class="n">EPDRPoolClass</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">EPDLPoolClassStruct</span> <span class="n">EPDRPoolClassStruct</span><span class="p">;</span>
<span class="n">DEFINE_CLASS</span><span class="p">(</span><span class="n">EPDRPoolClass</span><span class="p">,</span> <span class="n">this</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">INHERIT_CLASS</span><span class="p">(</span><span class="n">this</span><span class="p">,</span> <span class="n">EPDLPoolClass</span><span class="p">);</span>
<span class="n">this</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;EPDR&quot;</span><span class="p">;</span>
<span class="n">this</span><span class="o">-&gt;</span><span class="n">init</span> <span class="o">=</span> <span class="n">EPDRInit</span><span class="p">;</span>
<span class="n">this</span><span class="o">-&gt;</span><span class="n">alloc</span> <span class="o">=</span> <span class="n">EPDRAlloc</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p><span class="target" id="design.mps.protocol.example.extension"></span><a class="mpstag reference internal" href="#design.mps.protocol.example.extension">.example.extension:</a> The following (hypothetical) example
class definition shows inheritance, specialization and also extension.
It shows the definition of the class <tt class="docutils literal"><span class="pre">EPDLDebugPoolClass</span></tt>, which
inherits from <tt class="docutils literal"><span class="pre">EPDLPoolClass</span></tt>, but also implements a method for
checking properties of the pool.</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">typedef</span> <span class="k">struct</span> <span class="n">EPDLDebugPoolClassStruct</span> <span class="p">{</span>
<span class="n">EPDLPoolClassStruct</span> <span class="n">epdl</span><span class="p">;</span>
<span class="n">DebugPoolCheckMethod</span> <span class="n">check</span><span class="p">;</span>
<span class="n">Sig</span> <span class="n">sig</span><span class="p">;</span>
<span class="p">}</span> <span class="n">EPDLDebugPoolClassStruct</span><span class="p">;</span>
<span class="k">typedef</span> <span class="n">EPDLDebugPoolClassStruct</span> <span class="o">*</span><span class="n">EPDLDebugPoolClass</span><span class="p">;</span>
<span class="n">DEFINE_CLASS</span><span class="p">(</span><span class="n">EPDLDebugPoolClass</span><span class="p">,</span> <span class="n">this</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">EPDLPoolClass</span> <span class="n">epdl</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">this</span><span class="o">-&gt;</span><span class="n">epdl</span><span class="p">;</span>
<span class="n">INHERIT_CLASS</span><span class="p">(</span><span class="n">epdl</span><span class="p">,</span> <span class="n">EPDLPoolClass</span><span class="p">);</span>
<span class="n">epdl</span><span class="o">-&gt;</span><span class="n">name</span> <span class="o">=</span> <span class="s">&quot;EPDLDBG&quot;</span><span class="p">;</span>
<span class="n">this</span><span class="o">-&gt;</span><span class="n">check</span> <span class="o">=</span> <span class="n">EPDLDebugCheck</span><span class="p">;</span>
<span class="n">this</span><span class="o">-&gt;</span><span class="n">sig</span> <span class="o">=</span> <span class="n">EPDLDebugSig</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p><span class="target" id="design.mps.protocol.example.fail"></span><a class="mpstag reference internal" href="#design.mps.protocol.example.fail">.example.fail:</a> The following example shows the implementation
of failure-case code for an &#8220;init&#8221; method, making use of the &#8220;finish&#8221;
anti-method:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="n">Res</span> <span class="nf">mySegInit</span><span class="p">(</span><span class="n">Seg</span> <span class="n">seg</span><span class="p">,</span> <span class="n">Pool</span> <span class="n">pool</span><span class="p">,</span> <span class="n">Addr</span> <span class="n">base</span><span class="p">,</span> <span class="n">Size</span> <span class="n">size</span><span class="p">,</span>
<span class="n">Bool</span> <span class="n">reservoirPermit</span><span class="p">,</span> <span class="kt">va_list</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">SegClass</span> <span class="n">super</span><span class="p">;</span>
<span class="n">MYSeg</span> <span class="n">myseg</span><span class="p">;</span>
<span class="n">OBJ1</span> <span class="n">obj1</span><span class="p">;</span>
<span class="n">Res</span> <span class="n">res</span><span class="p">;</span>
<span class="n">Arena</span> <span class="n">arena</span><span class="p">;</span>
<span class="n">AVERT</span><span class="p">(</span><span class="n">Seg</span><span class="p">,</span> <span class="n">seg</span><span class="p">);</span>
<span class="n">myseg</span> <span class="o">=</span> <span class="n">SegMYSeg</span><span class="p">(</span><span class="n">seg</span><span class="p">);</span>
<span class="n">AVERT</span><span class="p">(</span><span class="n">Pool</span><span class="p">,</span> <span class="n">pool</span><span class="p">);</span>
<span class="n">arena</span> <span class="o">=</span> <span class="n">PoolArena</span><span class="p">(</span><span class="n">pool</span><span class="p">);</span>
<span class="cm">/* Ensure the pool is ready for the segment */</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">myNoteSeg</span><span class="p">(</span><span class="n">pool</span><span class="p">,</span> <span class="n">seg</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">ResOK</span><span class="p">)</span>
<span class="k">goto</span> <span class="n">failNoteSeg</span><span class="p">;</span>
<span class="cm">/* Initialize the superclass fields first via next-method call */</span>
<span class="n">super</span> <span class="o">=</span> <span class="p">(</span><span class="n">SegClass</span><span class="p">)</span><span class="n">SUPERCLASS</span><span class="p">(</span><span class="n">MYSegClass</span><span class="p">);</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">super</span><span class="o">-&gt;</span><span class="n">init</span><span class="p">(</span><span class="n">seg</span><span class="p">,</span> <span class="n">pool</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">reservoirPermit</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">ResOK</span><span class="p">)</span>
<span class="k">goto</span> <span class="n">failNextMethods</span><span class="p">;</span>
<span class="cm">/* Create an object after the next-method call */</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">ControlAlloc</span><span class="p">(</span><span class="o">&amp;</span><span class="n">obj1</span><span class="p">,</span> <span class="n">arena</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">OBJ1Struct</span><span class="p">),</span> <span class="n">reservoirPermit</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">!=</span> <span class="n">ResOK</span><span class="p">)</span>
<span class="k">goto</span> <span class="n">failObj1</span><span class="p">;</span>
<span class="n">myseg</span><span class="o">-&gt;</span><span class="n">obj1</span> <span class="o">=</span> <span class="n">obj1</span>
<span class="k">return</span> <span class="n">ResOK</span><span class="p">;</span>
<span class="nl">failObj1:</span>
<span class="cm">/* call the anti-method for the superclass */</span>
<span class="n">super</span><span class="o">-&gt;</span><span class="n">finish</span><span class="p">(</span><span class="n">seg</span><span class="p">);</span>
<span class="nl">failNextMethods:</span>
<span class="cm">/* reverse the effect of myNoteSeg */</span>
<span class="n">myUnnoteSeg</span><span class="p">(</span><span class="n">pool</span><span class="p">,</span> <span class="n">seg</span><span class="p">);</span>
<span class="nl">failNoteSeg:</span>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="implementation">
<h2>16.7. Implementation<a class="headerlink" href="#implementation" title="Permalink to this headline"></a></h2>
<p><span class="target" id="design.mps.protocol.impl.derived-names"></span><a class="mpstag reference internal" href="#design.mps.protocol.impl.derived-names">.impl.derived-names:</a> The <tt class="xref c c-func docutils literal"><span class="pre">DEFINE_CLASS()</span></tt> macro derives
some additional names from the class name as part of it&#8217;s
implementation. These should not appear in the source code - but it
may be useful to know about this for debugging purposes. For each
class definition for class <tt class="docutils literal"><span class="pre">SomeClass</span></tt>, the macro defines the
following:</p>
<p><tt class="docutils literal"><span class="pre">extern</span> <span class="pre">SomeClass</span> <span class="pre">EnsureSomeClass(void);</span></tt></p>
<blockquote>
<div>The class accessor function. See <a class="reference internal" href="#design.mps.protocol.overview.naming">.overview.naming</a>.</div></blockquote>
<p><tt class="docutils literal"><span class="pre">static</span> <span class="pre">Bool</span> <span class="pre">protocolSomeClassGuardian;</span></tt></p>
<blockquote>
<div>A Boolean which indicates whether the class has been initialzed yet.</div></blockquote>
<p><tt class="docutils literal"><span class="pre">static</span> <span class="pre">void</span> <span class="pre">protocolEnsureSomeClass(SomeClass);</span></tt></p>
<blockquote>
<div>A function called by <tt class="docutils literal"><span class="pre">EnsureSomeClass</span></tt>. All the class
initialization code is actually in this function.</div></blockquote>
<p><tt class="docutils literal"><span class="pre">static</span> <span class="pre">SomeClassStruct</span> <span class="pre">protocolSomeClassStruct;</span></tt></p>
<blockquote>
<div>Static storage for the canonical class object.</div></blockquote>
<p><span class="target" id="design.mps.protocol.impl.init-once"></span><a class="mpstag reference internal" href="#design.mps.protocol.impl.init-once">.impl.init-once:</a> Class objects only behave according to their
definition after they have been initialized, and class protocols may
not be used before initialization has happened. The only code which is
allowed to see a class object in a partially initialized state is the
initialization code itself &#8211; and this must take care not to pass the
object to any other code which might assume it is initialized. Once a
class has been initialized, the class might have a client. The class
must not be initialized again when this has happened, because the
state is not necessarily consistent in the middle of an initialization
function. The initialization state for each class is stored in a
Boolean &#8220;guardian&#8221; variable whose name is derived from the class name
(see <a class="reference internal" href="#design.mps.protocol.impl.derived-names">.impl.derived-names</a>). This ensures the
initialization happens only once. The path through the
<tt class="docutils literal"><span class="pre">EnsureSomeClass</span></tt> function should be very fast for the common case
when this variable is <tt class="docutils literal"><span class="pre">TRUE</span></tt>, and the class has already been
initialized, as the canonical static storage can simply be returned in
that case. However, when the value of the guardian is <tt class="docutils literal"><span class="pre">FALSE</span></tt>, the
class is not initialized. In this case, a call to <tt class="docutils literal"><span class="pre">EnsureSomeClass</span></tt>
must first execute the initialization code and then set the guardian
to <tt class="docutils literal"><span class="pre">TRUE</span></tt>. However, this must happen atomically (see
<a class="reference internal" href="#design.mps.protocol.impl.init-lock">.impl.init-lock</a>).</p>
<p><span class="target" id="design.mps.protocol.impl.init-lock"></span><a class="mpstag reference internal" href="#design.mps.protocol.impl.init-lock">.impl.init-lock:</a> There would be the possibility of a race
condition if <tt class="docutils literal"><span class="pre">EnsureSomeClass</span></tt> were called concurrently on separate
threads before <tt class="docutils literal"><span class="pre">SomeClass</span></tt> has been initialized. The class must not
be initialized more than once, so the sequence test-guard, init-class,
set-guard must be run as a critical region. It&#8217;s not sufficient to use
the arena lock to protect the critical region, because the class
object might be shared between multiple arenas. The
<tt class="xref c c-func docutils literal"><span class="pre">DEFINE_CLASS()</span></tt> macro uses a global recursive lock instead. The
lock is only claimed after an initial unlocked access of the guard
variable shows that the class is not initialized. This avoids any
locking overhead for the common case where the class is already
initialized. This lock is provided by the lock module &#8211; see
design.mps.lock(0).</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.png" alt="Logo"/>
</a></p>
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">16. Protocol inheritance</a><ul>
<li><a class="reference internal" href="#introduction">16.1. Introduction</a></li>
<li><a class="reference internal" href="#history">16.2. History</a></li>
<li><a class="reference internal" href="#purpose">16.3. Purpose</a></li>
<li><a class="reference internal" href="#requirements">16.4. Requirements</a></li>
<li><a class="reference internal" href="#overview">16.5. Overview</a></li>
<li><a class="reference internal" href="#interface">16.6. Interface</a><ul>
<li><a class="reference internal" href="#class-definition">16.6.1. Class definition</a></li>
<li><a class="reference internal" href="#single-inheritance">16.6.2. Single inheritance</a></li>
<li><a class="reference internal" href="#specialization">16.6.3. Specialization</a></li>
<li><a class="reference internal" href="#extension">16.6.4. Extension</a></li>
<li><a class="reference internal" href="#introspection">16.6.5. Introspection</a></li>
<li><a class="reference internal" href="#multiple-inheritance">16.6.6. Multiple inheritance</a></li>
<li><a class="reference internal" href="#protocol-guidelines">16.6.7. Protocol guidelines</a></li>
<li><a class="reference internal" href="#example">16.6.8. Example</a></li>
</ul>
</li>
<li><a class="reference internal" href="#implementation">16.7. Implementation</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="object-debug.html"
title="previous chapter">15. Debugging features for client objects</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="type.html"
title="next chapter">17. General MPS types</a></p><h4>Downloads</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/release/1.111.0/">MPS Kit release 1.111.0</a><br>
<a href="http://www.ravenbrook.com/project/mps/release/">All MPS Kit releases</a>
</p>
<h4>Issues</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&amp;view=status%3dopen&amp;display=Job:Priority:Title&amp;sort=Priority">Known issues</a><br>
<a href="http://www.ravenbrook.com/project/mps/issue/?action=fixed&release_fixed=1.111.0">Issues fixed in release 1.111.0</a>
</p><h4>Contact us</h4>
<p class="topless"><a href="mailto:mps-questions@ravenbrook.com">mps-questions@ravenbrook.com</a></p>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="type.html" title="17. General MPS types"
>next</a> |</li>
<li class="right" >
<a href="object-debug.html" title="15. Debugging features for client objects"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" >Design</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2013, Ravenbrook Limited.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>