X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/sod/blobdiff_plain/54fa3df9560fe739b5fe20ca561749092cef0fd5..756e9293611d2b1dc34fba6cca89fd70098f5546:/lib/sod-structs.3 diff --git a/lib/sod-structs.3 b/lib/sod-structs.3 index 2d4ecd1..a515c8e 100644 --- a/lib/sod-structs.3 +++ b/lib/sod-structs.3 @@ -69,6 +69,11 @@ struct sod_vtable { 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 { @@ -85,9 +90,14 @@ extern const struct SodClass__ilayout SodObject__classobj; 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; @@ -95,8 +105,8 @@ 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'void *(*init)(void *\fIp\fB); \h'8n'size_t n_supers; \h'8n'const SodClass *const *supers; \h'8n'size_t n_cpl; @@ -212,7 +222,7 @@ and not really to be recommended. .SS The SodObject class The .B SodObject -class defines no slots or messages. +class defines no slots. Because .B SodObject has no direct superclasses, @@ -220,8 +230,7 @@ there is only one chain, 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 @@ -232,6 +241,79 @@ In an actual instance of 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 @@ -253,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 @@ -267,16 +352,6 @@ but the slots are left untouched. The function returns its argument .IR p . .TP -.BI "void *(*init)(void *" p ); -A pointer to a function: -given a pointer -.I p -to an imprinted instance, -initialize all of its 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 @@ -467,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 @@ -551,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 @@ -589,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 @@ -613,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 @@ -660,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