X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/a142609c5dc2a7c3df02497235881beaf47088bf..d5fdd49e70b734b791eb907706f92da5775e2a8b:/lib/sod-structs.3 diff --git a/lib/sod-structs.3 b/lib/sod-structs.3 index 6cfbb75..161fc4e 100644 --- a/lib/sod-structs.3 +++ b/lib/sod-structs.3 @@ -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'4n'int (*teardown)(SodObject *\fIme\fB); \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'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; @@ -103,6 +105,7 @@ struct SodObject__ilayout { \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; @@ -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 -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 -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 @@ -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. +.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 @@ -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 align; +A sufficient alignment for the class's instance storage. +.TP .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'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 @@ -586,13 +626,9 @@ for each of 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 @@ -624,6 +660,14 @@ then the last member is .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 @@ -648,7 +692,7 @@ will have .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 @@ -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. -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. @@ -695,6 +739,12 @@ extern const union \fIC\fB__vtu_\fIh\fB \fIC\fB__vtable_\fIh\fB; .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 @@ -819,8 +869,9 @@ be the most specific superclass of .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 @@ -833,7 +884,13 @@ pointing to the appropriate .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 @@ -1057,6 +1114,12 @@ Finally, the class object is defined as .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 @@ -1075,7 +1138,32 @@ is the root metaclass of 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