chiark / gitweb /
doc/structures.tex, lib/sod-structs.3: Fix in-chain ichain exemplar.
[sod] / lib / sod-structs.3
index da12cc56926a745f4bd3ddb1e63a00b380224948..672fe596debee5c41230b80733af0e853d0622a1 100644 (file)
 .\" This file is part of the Sensible Object Design, an object system for C.
 .\"
 .\" SOD is free software; you can redistribute it and/or modify
 .\" This file is part of the Sensible Object Design, an object system for C.
 .\"
 .\" SOD is free software; you can redistribute it and/or modify
-.\" it under the terms of the GNU General Public License as published by
-.\" the Free Software Foundation; either version 2 of the License, or
-.\" (at your option) any later version.
+.\" it under the terms of the GNU Library General Public License as
+.\" published by the Free Software Foundation; either version 2 of the
+.\" License, or (at your option) any later version.
 .\"
 .\" SOD is distributed in the hope that it will be useful,
 .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
 .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 .\"
 .\" SOD is distributed in the hope that it will be useful,
 .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
 .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-.\" GNU General Public License for more details.
+.\" GNU Library General Public License for more details.
 .\"
 .\"
-.\" You should have received a copy of the GNU General Public License
-.\" along with SOD; if not, write to the Free Software Foundation,
-.\" Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+.\" You should have received a copy of the GNU Library General Public
+.\" License along with SOD; if not, write to the Free
+.\" Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+.\" MA 02111-1307, USA.
 .
 .\" Highlight using terminal escapes, rather than overstriking.
 .\"\X'tty: sgr 1'
 .
 .\" Highlight using terminal escapes, rather than overstriking.
 .\"\X'tty: sgr 1'
@@ -68,6 +69,11 @@ struct sod_vtable {
 struct SodObject__vt_obj {
 \h'2n'const SodClass *_class;
 \h'2n'size_t _base;
 struct SodObject__vt_obj {
 \h'2n'const SodClass *_class;
 \h'2n'size_t _base;
+\h'2n'struct SodObject__vtmsgs_obj {
+\h'4n'void (*init)(SodObject *\fIme\fB, ...);
+\h'4n'void (*init__v)(SodObject *\fIme\fB, va_list);
+\h'4n'int (*teardown)(SodObject *\fIme\fB);
+\h'2n'} obj;
 };
 
 struct SodObject__ilayout {
 };
 
 struct SodObject__ilayout {
@@ -84,9 +90,14 @@ extern const struct SodClass__ilayout SodObject__classobj;
 struct SodClass__vt_obj {
 \h'2n'const SodClass *_class;
 \h'2n'size_t _base;
 struct SodClass__vt_obj {
 \h'2n'const SodClass *_class;
 \h'2n'size_t _base;
+\h'2n'struct SodClass__vtmsgs_obj {
+\h'4n'void (*init)(SodClass *\fIme\fB, ...);
+\h'4n'void (*init__v)(SodClass *\fIme\fB, va_list);
+\h'4n'int (*teardown)(SodClass *\fIme\fB);
+\h'2n'} obj;
 };
 
 };
 
-struct SodObject__ilayout {
+struct SodClass__ilayout {
 \h'2n'union {
 \h'4n'struct SodClass__ichain_obj {
 \h'6n'const struct SodClass__vt_obj *_vt;
 \h'2n'union {
 \h'4n'struct SodClass__ichain_obj {
 \h'6n'const struct SodClass__vt_obj *_vt;
@@ -94,8 +105,8 @@ struct SodObject__ilayout {
 \h'8n'const char *name;
 \h'8n'const char *nick;
 \h'8n'size_t initsz;
 \h'8n'const char *name;
 \h'8n'const char *nick;
 \h'8n'size_t initsz;
+\h'8n'size_t align;
 \h'8n'void *(*imprint)(void *\fIp\fB);
 \h'8n'void *(*imprint)(void *\fIp\fB);
-\h'8n'void *(*init)(void *\fIp\fB);
 \h'8n'size_t n_supers;
 \h'8n'const SodClass *const *supers;
 \h'8n'size_t n_cpl;
 \h'8n'size_t n_supers;
 \h'8n'const SodClass *const *supers;
 \h'8n'size_t n_cpl;
@@ -211,7 +222,7 @@ and not really to be recommended.
 .SS The SodObject class
 The
 .B SodObject
 .SS The SodObject class
 The
 .B SodObject
-class defines no slots or messages.
+class defines no slots.
 Because
 .B SodObject
 has no direct superclasses,
 Because
 .B SodObject
 has no direct superclasses,
@@ -219,8 +230,7 @@ there is only one chain,
 and no inherited slots or messages,
 so the single chain contains only a vtable pointer.
 .PP
 and no inherited slots or messages,
 so the single chain contains only a vtable pointer.
 .PP
-Since there are no messages,
-and
+Since
 .B SodClass
 also has only one chain,
 the vtable contains only the standard class pointer and offset-to-base
 .B SodClass
 also has only one chain,
 the vtable contains only the standard class pointer and offset-to-base
@@ -231,6 +241,79 @@ In an actual instance of
 the class pointer contains the address of
 .B SodObject__class
 and the offset is zero.
 the class pointer contains the address of
 .B SodObject__class
 and the offset is zero.
+.PP
+The
+.B init
+message is used to initialize a newly allocated instance.
+.PP
+This message uses a custom method combination
+which works like the standard method combination
+except that default behaviour
+specific to the receiver's direct class
+is invoked if no primary or around method overrides.
+This default behaviour may be invoked multiple times
+if some method calls on its
+.B next_method
+function more than once.
+.PP
+This default behaviour is to initialize the instance's slots
+using the defined slot initializers,
+and execute the initialization fragments.
+Each slot is initialized
+using the most specific applicable initializer,
+if any.
+Slots without an initializer
+are left uninitialized.
+.PP
+Slots are initialized and initialization fragments executed together,
+a superclass at a time:
+first, the superclass's slots are initialized (if any);
+then the superclass's initialization fragments (if any) are executed,
+starting with the least specific superclass first.
+Slots and initialization fragments defined by the same class
+are processed in the order in which they appear in the class definition.
+.PP
+There are no standard keyword arguments;
+methods on subclasses are free to
+introduce their own in the usual way.
+.PP
+It is usual to provide complex initialization behaviour as
+.B after
+methods.
+This ensures that slots have been initialized as necessary
+before the method executes.
+.PP
+The
+.B teardown
+message is used to tear down an instance which is no longer required.
+.PP
+The message returns an integer flag.
+A zero value means that the instance is safe to deallocate.
+A nonzero value means that the instance should not be deallocated,
+and that it is safe for the caller to simply forget about it.
+This simple protocol may be used, for example,
+to implement a reference-counting system.
+.PP
+This message uses a custom method combination
+which works like the standard method combination
+except that default behaviour is invoked if
+no primary or around method overrides.
+This default behaviour is to execute
+each superclass's teardown fragments,
+most specific first,
+and then return zero to indicate
+that the object is ready for deallocation.
+Teardown fragments defined by the same class
+are processed in the order in which they appear
+in the class definition.
+.PP
+It is usual to provide complex teardown behaviour as
+.B before
+methods.
+Logic to decide whether to allow deallocation
+is usually implemented as
+.B around
+methods.
 .
 .SS The SodClass class
 The
 .
 .SS The SodClass class
 The
@@ -252,6 +335,9 @@ A pointer to the class's nickname.
 .B size_t initsz;
 The size in bytes required to store an instance of the class.
 .TP
 .B size_t initsz;
 The size in bytes required to store an instance of the class.
 .TP
+.B size_t align;
+A sufficient alignment for the class's instance storage.
+.TP
 .BI "void *(*imprint)(void *" p );
 A pointer to a function:
 given a pointer
 .BI "void *(*imprint)(void *" p );
 A pointer to a function:
 given a pointer
@@ -266,20 +352,6 @@ but the slots are left untouched.
 The function returns its argument
 .IR p .
 .TP
 The function returns its argument
 .IR p .
 .TP
-.BI "void *(*init)(void *" p );
-A pointer to a function:
-given a pointer
-.I p
-to at least
-.I initsz
-bytes of appropriately aligned memory,
-initialize an instance of the class in it:
-all of the vtable and class pointers are initialized,
-as are slots for which initializers are defined.
-Other slots are left untouched.
-The function returns its argument
-.IR p .
-.TP
 .B size_t n_supers;
 The number of direct superclasses.
 (This is zero exactly in the case of
 .B size_t n_supers;
 The number of direct superclasses.
 (This is zero exactly in the case of
@@ -470,7 +542,7 @@ struct \fIC\fB__ilayout {
 \h'6n'} \fIc\fB;
 \h'4n'} \fIc\fB;
 \h'4n'\fR...\fB
 \h'6n'} \fIc\fB;
 \h'4n'} \fIc\fB;
 \h'4n'\fR...\fB
-\h'4n'struct \fIH\fB__ichain_\fIh\fB \fIh\fB;
+\h'4n'struct \fIA\fB__ichain_\fIh\fB \fIa\fB;
 \h'2n'} \fIh\fB;
 \h'2n'union \fIB\fB__ichainu_\fIi\fB \fIi\fB;
 \h'2n'\fR...\fB
 \h'2n'} \fIh\fB;
 \h'2n'union \fIB\fB__ichainu_\fIi\fB \fIi\fB;
 \h'2n'\fR...\fB
@@ -554,13 +626,9 @@ for each of
 superclasses
 .IR A
 in the same chain in some (unimportant) order.
 superclasses
 .IR A
 in the same chain in some (unimportant) order.
-A `pointer to
-.IR C '
-is always assumed
-(and, indeed, defined in C's type system)
-to be a pointer to the
-.B struct
-.IB C __ichain_ h \fR.
+The (somewhat obtuse) purpose of this union is to
+engage the `common initial sequence' rule of
+C99 (clause 6.5.2.3).
 .PP
 The
 .B ichain
 .PP
 The
 .B ichain
@@ -592,6 +660,14 @@ then the last member is
 .IB C __islots 
 .IB c ;
 .PP
 .IB C __islots 
 .IB c ;
 .PP
+A `pointer to
+.IR C '
+is always assumed
+(and, indeed, defined in C's type system)
+to be a pointer to the
+.B struct
+.IB C __ichain_ h \fR.
+.PP
 Finally, the
 .B islots
 structure simply contains one member for each slot defined by
 Finally, the
 .B islots
 structure simply contains one member for each slot defined by
@@ -663,6 +739,12 @@ extern const union \fIC\fB__vtu_\fIh\fB \fIC\fB__vtable_\fIh\fB;
 .ft P
 .fi
 .PP
 .ft P
 .fi
 .PP
+In the following,
+let
+.I M
+be the metaclass of
+.IR C .
+.PP
 The outer layer is a
 .B union
 .IB C __vtu_ h
 The outer layer is a
 .B union
 .IB C __vtu_ h
@@ -892,6 +974,27 @@ defined as
 .IB an , 
 .B ...);
 .PP
 .IB an , 
 .B ...);
 .PP
+or a standard message which takes keyword arguments,
+defined as
+.IP
+.I tr
+.IB m ( \c
+.I t1
+.IB a1 ,
+.RB ... ,
+.I tn
+.IB an ?\&
+.IR tn +1
+.IR kn +1
+.RB [ =
+.IR dn +1] \c
+.B ,
+.I tm
+.I km
+.RB [ =
+.IR dm ] \c
+);
+.PP
 two entry points are defined:
 the usual `main' entry point
 which accepts a variable number of
 two entry points are defined:
 the usual `main' entry point
 which accepts a variable number of
@@ -899,7 +1002,8 @@ arguments,
 and a `valist' entry point
 which accepts an argument of type
 .B va_list
 and a `valist' entry point
 which accepts an argument of type
 .B va_list
-in place of the variable portion of the argument list.
+in place of the variable portion of the argument list
+or keywords.
 .IP
 .I tr
 .BI (* m )( \c
 .IP
 .I tr
 .BI (* m )( \c
@@ -949,6 +1053,7 @@ somewhat less ugly.
 If
 .I m
 takes a variable number of arguments,
 If
 .I m
 takes a variable number of arguments,
+or keyword arguments,
 the macro is more complicated
 and is only available in compilers advertising C99 support,
 but the effect is the same.
 the macro is more complicated
 and is only available in compilers advertising C99 support,
 but the effect is the same.