src/method-{proto,impl}.lisp: Abstract out the receiver type.
[sod] / lib / sod-structs.3
index 6cfbb75..161fc4e 100644 (file)
@@ -72,6 +72,7 @@ struct SodObject__vt_obj {
 \h'2n'struct SodObject__vtmsgs_obj {
 \h'4n'void (*init)(SodObject *\fIme\fB, ...);
 \h'4n'void (*init__v)(SodObject *\fIme\fB, va_list);
 \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;
 };
 
 \h'2n'} obj;
 };
 
@@ -92,10 +93,11 @@ struct SodClass__vt_obj {
 \h'2n'struct SodClass__vtmsgs_obj {
 \h'4n'void (*init)(SodClass *\fIme\fB, ...);
 \h'4n'void (*init__v)(SodClass *\fIme\fB, va_list);
 \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;
 };
 
 \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;
@@ -103,6 +105,7 @@ 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'size_t n_supers;
 \h'8n'const SodClass *const *supers;
 \h'8n'void *(*imprint)(void *\fIp\fB);
 \h'8n'size_t n_supers;
 \h'8n'const SodClass *const *supers;
@@ -254,19 +257,21 @@ if some method calls on its
 function more than once.
 .PP
 This default behaviour is to initialize the instance's slots
 function more than once.
 .PP
 This default behaviour is to initialize the instance's slots
-using the defined slot initializers:
-each slot is initialized
+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
 using the most specific applicable initializer,
 if any.
 Slots without an initializer
 are left uninitialized.
 .PP
-Slots are initialized in reverse-precedence order
-of their defining classes;
-i.e., slots defined by a less specific superclass are initialized
-earlier than slots defined by a more specific superclass.
-Slots defined by the same class are initialized in the order in which
-they appear in the class definition.
+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
 .PP
 There are no standard keyword arguments;
 methods on subclasses are free to
@@ -277,6 +282,38 @@ It is usual to provide complex initialization behaviour as
 methods.
 This ensures that slots have been initialized as necessary
 before the method executes.
 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
@@ -298,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
@@ -502,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
@@ -586,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
@@ -624,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
@@ -648,7 +692,7 @@ will have
 .I different
 structures.
 .PP
 .I different
 structures.
 .PP
-The instance layout split neatly into disjoint chains.
+The instance layout splits neatly into disjoint chains.
 This is necessary because
 each
 .B ichain
 This is necessary because
 each
 .B ichain
@@ -661,7 +705,7 @@ it doesn't matter that there are
 multiple method entry pointers
 for the same effective method
 as long as they all work correctly.
 multiple method entry pointers
 for the same effective method
 as long as they all work correctly.
-Indeed, it's essential that they do,
+Indeed, it's essential that there are multiple entry pointers,
 because each chain's method entry function
 will need to apply a different offset to the receiver pointer
 before invoking the effective method.
 because each chain's method entry function
 will need to apply a different offset to the receiver pointer
 before invoking the effective method.
@@ -695,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
@@ -819,8 +869,9 @@ be the most specific superclass of
 .I M
 in the same chain as
 .IR J .
 .I M
 in the same chain as
 .IR J .
-Then, if there is currently no class pointer of type
-.IR Q ,
+If there is currently no class pointer
+for the chain headed by
+.IR J ,
 then add a member
 .RS
 .IP
 then add a member
 .RS
 .IP
@@ -833,7 +884,13 @@ pointing to the appropriate
 .B islots
 structure within
 .IR M 's
 .B islots
 structure within
 .IR M 's
-class object.
+class object,
+where
+.I Q
+is the most specific superclass of
+.I M
+in the same chain as
+.IR J .
 .RE
 .hP \*o
 Examine the superclass chains of
 .RE
 .hP \*o
 Examine the superclass chains of
@@ -1057,6 +1114,12 @@ Finally, the class object is defined as
 .B #define
 .IB C __class
 .BI (& C __classobj. j . r )
 .B #define
 .IB C __class
 .BI (& C __classobj. j . r )
+.br
+.B #define
+.IB C __cls_ k
+.BI (& C __classobj. k . n )
+.br
+\&...
 .PP
 The exported symbol
 .IB C __classobj
 .PP
 The exported symbol
 .IB C __classobj
@@ -1075,7 +1138,32 @@ is the root metaclass of
 i.e., the metaclass of the least specific superclass of
 .IR C ;
 usually this is
 i.e., the metaclass of the least specific superclass of
 .IR C ;
 usually this is
-.BR "const SodClass *" .
+.BR "const SodClass\ *" .
+For each chain of
+.IR C 's
+metaclass, a macro
+.IB C __cls_ k
+is defined, usable as a pointer of type
+.B const
+.IR N \ \c
+.BR * ,
+where
+.I K
+and
+.I N
+are the chain's head and tail classes
+(i.e., the least- and most-specific classes in the chain)
+respectively;
+this macro is
+.I omitted
+if
+.IR N "\ =\ " R ,
+i.e., in the common case where
+.IR C 's
+metaclass is precisely the root metaclass,
+since the existing
+.IB C __class
+macro is already sufficient.
 .
 .\"--------------------------------------------------------------------------
 .SH SEE ALSO
 .
 .\"--------------------------------------------------------------------------
 .SH SEE ALSO