File:  [DragonFly] / src / sys / sys / kobj.h
Revision 1.7: download - view: text, annotated - select for diffs
Wed Apr 14 18:28:29 2004 UTC (10 years, 4 months ago) by joerg
Branches: MAIN
CVS tags: HEAD, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
KObj extension stage IIIa/III

Merge inheritance support from FreeBSD:
  * Add multiple inheritance to kobj. Each class can have zero or more base
    classes and if a method is not found in a given class, its base classes
    are searched (in the order they were declared). This search is recursive,
    i.e. a method may be define in a base class of a base class.

    1: /*-
    2:  * Copyright (c) 2000 Doug Rabson
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24:  * SUCH DAMAGE.
   25:  *
   26:  * $FreeBSD: src/sys/sys/kobj.h,v 1.8 2003/09/22 21:32:49 peter Exp $
   27:  * $DragonFly: src/sys/sys/kobj.h,v 1.7 2004/04/14 18:28:29 joerg Exp $
   28:  */
   29: 
   30: #ifndef _SYS_KOBJ_H_
   31: #define _SYS_KOBJ_H_
   32: 
   33: /*
   34:  * Forward declarations
   35:  */
   36: typedef struct kobj		*kobj_t;
   37: typedef struct kobj_class	*kobj_class_t;
   38: typedef struct kobj_method	kobj_method_t;
   39: typedef int			(*kobjop_t)(void);
   40: typedef struct kobj_ops		*kobj_ops_t;
   41: typedef struct kobjop_desc	*kobjop_desc_t;
   42: struct malloc_type;
   43: 
   44: struct kobj_method {
   45: 	kobjop_desc_t	desc;
   46: 	kobjop_t	func;
   47: };
   48: 
   49: /*
   50:  * A class is simply a method table and a sizeof value. When the first
   51:  * instance of the class is created, the method table will be compiled
   52:  * into a form more suited to efficient method dispatch. This compiled
   53:  * method table is always the first field of the object.
   54:  */
   55: #define KOBJ_CLASS_FIELDS						\
   56: 	const char	*name;		/* class name */		\
   57: 	kobj_method_t	*methods;	/* method table */		\
   58: 	size_t		size;		/* object size */		\
   59: 	kobj_class_t	*baseclasses;	/* base classes */		\
   60: 	u_int		refs;		/* reference count */		\
   61: 	kobj_ops_t	ops		/* compiled method table */
   62: 
   63: struct kobj_class {
   64: 	KOBJ_CLASS_FIELDS;
   65: };
   66: 
   67: /*
   68:  * Implementation of kobj.
   69:  */
   70: #define KOBJ_FIELDS				\
   71: 	kobj_ops_t	ops
   72: 
   73: struct kobj {
   74: 	KOBJ_FIELDS;
   75: };
   76: 
   77: /*
   78:  * The ops table is used as a cache of results from kobj_lookup_method().
   79:  */
   80: 
   81: #define KOBJ_CACHE_SIZE	256
   82: 
   83: struct kobj_ops {
   84: 	kobj_method_t	*cache[KOBJ_CACHE_SIZE];
   85: 	kobj_class_t	cls;
   86: };
   87: 
   88: struct kobjop_desc {
   89: 	unsigned int	id;	/* unique ID */
   90: 	kobj_method_t	*deflt;	/* default implementation */
   91: };
   92: 
   93: /*
   94:  * Shorthand for constructing method tables.
   95:  */
   96: #define KOBJMETHOD(NAME, FUNC) { &NAME##_desc, (kobjop_t) FUNC }
   97: 
   98: /*
   99:  * Declare a class (which should be defined in another file.
  100:  */
  101: #define DECLARE_CLASS(name) extern struct kobj_class name
  102: 
  103: /*
  104:  * Define a class with no base classes (api backward-compatible. with
  105:  * FreeBSD-5.1 and earlier).
  106:  */
  107: #define DEFINE_CLASS(name, methods, size)     		\
  108: DEFINE_CLASS_0(name, name ## _class, methods, size)
  109: 
  110: /*
  111:  * Define a class with no base classes. Use like this:
  112:  *
  113:  * DEFINE_CLASS_0(foo, foo_class, foo_methods, sizeof(foo_softc));
  114:  */
  115: #define DEFINE_CLASS_0(name, classvar, methods, size)	\
  116: 							\
  117: struct kobj_class classvar = {				\
  118: 	#name, methods, size, 0				\
  119: }
  120: 
  121: /*
  122:  * Define a class inheriting a single base class. Use like this:
  123:  *
  124:  * DEFINE_CLASS1(foo, foo_class, foo_methods, sizeof(foo_softc),
  125:  *			  bar);
  126:  */
  127: #define DEFINE_CLASS_1(name, classvar, methods, size,	\
  128: 		       base1)				\
  129: 							\
  130: static kobj_class_t name ## _baseclasses[] = {		\
  131: 	&base1, 0					\
  132: };							\
  133: struct kobj_class classvar = {				\
  134: 	#name, methods, size, name ## _baseclasses	\
  135: }
  136: 
  137: /*
  138:  * Define a class inheriting two base classes. Use like this:
  139:  *
  140:  * DEFINE_CLASS2(foo, foo_class, foo_methods, sizeof(foo_softc),
  141:  *			  bar, baz);
  142:  */
  143: #define DEFINE_CLASS_2(name, methods, size,		\
  144: 	               base1, base2)			\
  145: 							\
  146: static kobj_class_t name ## _baseclasses[] = {		\
  147: 	&base1,						\
  148: 	&base2, 0					\
  149: };							\
  150: struct kobj_class name ## _class = {			\
  151: 	#name, methods, size, name ## _baseclasses	\
  152: }
  153:  
  154: /*
  155:  * Define a class inheriting three base classes. Use like this:
  156:  *
  157:  * DEFINE_CLASS3(foo, foo_class, foo_methods, sizeof(foo_softc),
  158:  *			  bar, baz, foobar);
  159:  */
  160: #define DEFINE_CLASS_3(name, methods, size,		\
  161: 		       base1, base2, base3)		\
  162: 							\
  163: static kobj_class_t name ## _baseclasses[] = {		\
  164: 	&base1,						\
  165: 	&base2,						\
  166: 	&base3, 0					\
  167: };							\
  168: struct kobj_class name ## _class = {			\
  169: 	#name, methods, size, name ## _baseclasses	\
  170: }
  171: 
  172: /*
  173:  * Compile class for the first instance and add a reference.
  174:  */
  175: void		kobj_class_instantiate(kobj_class_t cls);
  176: 
  177: /*
  178:  * Remove a reference and free method table with the last instance.
  179:  */
  180: void		kobj_class_uninstantiate(kobj_class_t cls);
  181: 
  182: /*
  183:  * Allocate memory for and initialise a new object.
  184:  */
  185: kobj_t		kobj_create(kobj_class_t cls,
  186: 			    struct malloc_type *mtype,
  187: 			    int mflags);
  188: 
  189: /*
  190:  * Initialise a pre-allocated object.
  191:  */
  192: void		kobj_init(kobj_t obj, kobj_class_t cls);
  193: 
  194: /*
  195:  * Delete an object. If mtype is non-zero, free the memory.
  196:  */
  197: void		kobj_delete(kobj_t obj, struct malloc_type *mtype);
  198: 
  199: /*
  200:  * Maintain stats on hits/misses in lookup caches.
  201:  */
  202: #ifdef KOBJ_STATS
  203: extern u_int kobj_lookup_hits;
  204: extern u_int kobj_lookup_misses;
  205: #endif
  206: 
  207: /*
  208:  * Lookup the method in the cache and if it isn't there look it up the
  209:  * slow way.
  210:  */
  211: #ifdef KOBJ_STATS
  212: #define KOBJOPLOOKUP(OPS,OP) do {					\
  213: 	kobjop_desc_t _desc = &OP##_##desc;				\
  214: 	kobj_method_t **_cep =						\
  215: 	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];		\
  216: 	kobj_method_t *_ce = *_cep;					\
  217: 	kobj_lookup_hits++; /* assume hit */				\
  218: 	if (_ce->desc != _desc)						\
  219: 		_ce = kobj_lookup_method(OPS->cls,			\
  220: 					 _cep, _desc);			\
  221: 	_m = _ce->func;							\
  222: } while(0)
  223: #else
  224: #define KOBJOPLOOKUP(OPS,OP) do {					\
  225: 	kobjop_desc_t _desc = &OP##_##desc;				\
  226: 	kobj_method_t **_cep =						\
  227: 	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];		\
  228: 	kobj_method_t *_ce = *_cep;					\
  229: 	if (_ce->desc != _desc)						\
  230: 		_ce = kobj_lookup_method(OPS->cls,			\
  231: 					 _cep, _desc);			\
  232: 	_m = _ce->func;							\
  233: } while(0)
  234: #endif
  235: 
  236: kobj_method_t *kobj_lookup_method(kobj_class_t cls,
  237: 				  kobj_method_t **cep,
  238: 				  kobjop_desc_t desc);
  239: 
  240: /*
  241:  * Default method implementation. Returns ENXIO.
  242:  */
  243: int kobj_error_method(void);
  244: 
  245: #endif /* !_SYS_KOBJ_H_ */