X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/3dca7758421664a838c54b273bd9221f02072045..a79bc435502289f53de312694ea3f5ca6c3aca58:/lib/sod-structs.3 diff --git a/lib/sod-structs.3 b/lib/sod-structs.3 index 6aefc9d..0eb6324 100644 --- a/lib/sod-structs.3 +++ b/lib/sod-structs.3 @@ -7,23 +7,26 @@ . .\"----- Licensing notice --------------------------------------------------- .\" -.\" This file is part of the Sensble Object Design, an object system for C. +.\" 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 -.\" 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' +. .\" String definitions and font selection. .ie t \{\ . ds o \(bu @@ -66,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 { @@ -82,6 +90,11 @@ 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 { @@ -92,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; @@ -192,11 +205,13 @@ has no direct superclasses, and .B SodClass is its own metaclass. -It is not possible to define root classes because of circularities: +It is not possible to define root classes in module files +because of circularities: .B SodObject has .B SodClass -as its metaclass, and +as its metaclass, +and .B SodClass is a subclass of .BR SodObject . @@ -207,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, @@ -215,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 @@ -227,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 @@ -248,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 @@ -262,20 +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 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 @@ -546,7 +622,8 @@ and this is followed by corresponding members .IB a ; .PP for each of -.IR C 's superclasses +.IR C 's +superclasses .IR A in the same chain in some (unimportant) order. A `pointer to @@ -617,13 +694,17 @@ each .B ichain must have as a prefix the .B ichain -for each superclass in the same chain, and -each slot must be stored in exactly one place. +for each superclass in the same chain, +and each slot must be stored in exactly one place. The layout of vtables doesn't have this second requirement: 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, +because each chain's method entry function +will need to apply a different offset to the receiver pointer +before invoking the effective method. .PP A vtable for a class .I C @@ -654,11 +735,15 @@ 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 -.IP .B union .IB C __vtu_ h -.PP containing a member .IP .B struct @@ -718,7 +803,7 @@ of The metaclass .I R of -.IR O . +.I O is then the .I root metaclass of @@ -781,7 +866,7 @@ be the most specific superclass of in the same chain as .IR J . Then, if there is currently no class pointer of type -.I Q +.IR Q , then add a member .RS .IP @@ -825,7 +910,7 @@ If class .I A defines any messages, and there is currently no member -.I a +.IR a , then add a member .RS .IP @@ -885,6 +970,27 @@ defined as .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 @@ -892,7 +998,8 @@ arguments, 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 @@ -942,6 +1049,7 @@ somewhat less ugly. 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.