Yet More on MI
Hans-Dieter.Dreier@materna.de
Hans-Dieter.Dreier@materna.de
Wed, 17 Mar 1999 18:04:47 +0100
--niWO8o7uApPVPHJTV8IQB7FnAL8o8Vmq
Content-type: text/plain; charset="ISO-8859-1"
Content-transfer-encoding: quoted-printable
Yet More on MI
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
After contemplating the MI problem a little more a came upon the approach I=
want to sketch below.
Please have a look at it and tell me about any flaws you can find in it.
First, the goals I want to achieve:
1. Provide true MI functionality to the user (How it works internally is an=
other issue).
2. No bidirectional class dependency: Make sure no base class needs recompi=
lation when a derived class changes.
I'm not addressing the issue of "virtual/static" here, assuming that either=
the user specifies what he wants or everything is virtual.
3. Be reasonably efficient.
Internally, this approach would use cMI since IMO the above conditions rule=
out instance merging.
So one of the base classes will be "more equal" than the others.
I'll call that class the "MI class". The others will be called "mixed-n" cl=
asses here to distinguish them.
The proposed instance layout would be:
this -> - Reference to MI class if used as mixed-class, pointer to this oth=
erwise (Note a)
- Reference to vtable (Note b)
- Reference to ttable (Note c)
- (Instance items if any)
Note a:
If a reference to this is used in the program itself, a reference to the MI=
object is wanted rather than a reference to the mixin object.
That's what this instance item is good for.
Note b:
This will be the vtable as commonly used.
Each virtual item that has been declared here or in one of the base classes=
has a slot assigned by the compiler in which its address is stored.
Vtable layout of base classes is preserved; entries for virtual items in th=
e current class are appended.
The vtable may be shared among all instances of that class that are used in=
the same mixin declaration (or as a standalone class).
This is because the compiler may need to change entries' values if the MI c=
lass (or one of the other mixins) overrides virtual items of this (mixin) c=
lass.
Example: Let there be instances of class A as a standalone class as well as=
(implicit) instances that are used as mixins.
Then there will be two versions of the vtable, one for each usage.
Note c:
For each vtable entry this table will contain the this pointer that needs t=
o be used with that entry
(ie he reference to the instance that actually contains the item).
If the item is taken from the MI class, it will be a pointer to the MI clas=
s's instance;
if it was taken from a mixin (of the MI class) it will be one to that mixin=
's instance.
Because it contains this's, I'll call it the "ttable".
The value will be used as a this pointer for actual item access (for virtua=
l calls; simple data accesses may not need it).
This makes sure that a method will always be called with the proper this va=
lue (ie consistent with instance layout)
which for mixins is different from the MI object's this value.
Since the ttable contains references to instances, each instance needs its =
own table.
Therefore the ttable may be contained inside the instance rather than being=
referenced by a pointer.
If it is kept as a separate entity (I won't call it an object), the referen=
ce may be NULL if the instance was not used as a mixin,
thus saving space (and one indirection) at the expense of having to check f=
or a NULL on every virtual call.
If it is NULL, "this" will be used.
Here's an example.
class A {int a; virtual va1; virtual va2;} // not "pure virtual" but overri=
deable is meant
class B {int b; virtual vb1; virtual vb2;
virtual va1 =3D 0;} // va1 is pure virtual (i=
e used here, defined elsewhere)
class C {int c; mixin A ca; mixin B cb; // contains 2 mixins
int va2; int vb2; // va2 and vb2 are overridd=
en
virtual va1 =3D 0;} // va1 is pure virtual (i=
e used here, defined elsewhere)
A AnA; // A used standalone
C aC; // A used as a mixin (together with B)
The memory layout looks like this:
AnA: =
AnA // MI class instance: If you check "this =3D=3D aC" insi=
de A standalone you get false because this is AnA
vtable of A standalone
ttable of AnA // might be NULL, see Note c
a
vtable of A standalone:
va1 of A
va2 of A
ttable of AnA: // might be missing, see Note c
AnA
AnA
(This was easy.)
aC:
aC // MI class instance
vtable of C
ttable of aC
c
ca
cb
vtable of C:
va1 of A
ttable of aC:
ca // va1 always operates on an A if taken from A
ca:
aC // MI class: If you check "this =3D=3D aC" inside mixin =
A ca you get true
vtable of mixin A ca
ttable of ca
a
vtable of mixin A ca:
va1 of A
va2 of C // overridden by C
ttable of ca:
ca
aC
cb:
aC
vtable of mixin B cb
ttable of cb
b
vtable of mixin B cb:
vb1 of B
vb2 of C // overridden by C
va1 of A // found in A
ttable of cb:
cb
aC
ca
=
--
Regards,
Hans-Dieter Dreier
(Hans-Dieter.Dreier@materna.de)=
--niWO8o7uApPVPHJTV8IQB7FnAL8o8Vmq
Content-type: text/plain; charset="ISO-8859-1"
Content-transfer-encoding: quoted-printable
IDENTIFIKATIONSANGABEN:
a22317a.txt IA5 DX-MAIL X.400 User Agent=
--niWO8o7uApPVPHJTV8IQB7FnAL8o8Vmq--