/* * $HEADER$ */ #ifndef LAM_OBJECT_H #define LAM_OBJECT_H #include #include "lam/types.h" #include "lam/atomic.h" /* * * Base data structures * */ struct lam_object; typedef void (*class_init_t)(struct lam_object *); typedef void (*class_destroy_t)(struct lam_object *); typedef struct lam_class_info { const char *cls_name; struct lam_class_info *cls_parent; class_init_t cls_init; class_destroy_t cls_destroy; } lam_class_info_t; #define OBJECT(obj) ((lam_object_t *)(obj)) #define CREATE_OBJECT(obj, lam_obj_type, cls_ptr) \ do { \ obj = (lam_obj_type *)malloc(sizeof(lam_obj_type)); \ if ( obj ) \ { \ OBJECT(obj)->obj_class = cls_ptr; \ OBJECT(obj)->obj_class->cls_init(OBJECT(obj)); \ } \ } while (0) /* * * Available Classes * */ extern lam_class_info_t lam_object_cls; /* * * Helpful macros * */ #define SUPER(obj) (&((obj)->super)) /* Use STATIC_INIT to initialize objects that are not dynamically allocated. */ #define STATIC_INIT(obj, cls_ptr) \ do { \ OBJECT(&(obj))->obj_class = cls_ptr; \ OBJECT(&(obj))->obj_class->cls_init(OBJECT(&(obj))); \ } while (0) /* super_cls should be the pointer to the obj's parent class info struct. */ #define SUPER_INIT(obj, super_cls) \ do { \ (super_cls)->cls_init(OBJECT(obj)); \ } while (0) #define SUPER_DESTROY(obj, super_cls) (super_cls)->cls_destroy(OBJECT(obj)) #define OBJ_RETAIN(obj) if ( obj ) lam_obj_retain(OBJECT(obj)) #define OBJ_RELEASE(obj) if ( obj ) lam_obj_release(OBJECT(obj)) typedef struct lam_object { lam_class_info_t *obj_class; int obj_refcnt; } lam_object_t; void lam_obj_init(lam_object_t *obj); void lam_obj_destroy(lam_object_t *obj); /* * This function is used by inline functions later in this file, and * it must be defined by other header files later (eg., one of the * atomic.h's). */ static inline int fetchNadd(volatile int *addr, int inc); /* returns 1 if object's class is derived from cls, otherwise 0. */ int lam_obj_is_kind_of(lam_object_t *obj, lam_class_info_t *cls); static inline int lam_obj_get_ref_count(lam_object_t *obj) { return obj->obj_refcnt; } static inline void lam_obj_retain(lam_object_t *obj) { fetchNadd(&obj->obj_refcnt, 1); } static inline void lam_obj_release(lam_object_t *obj) { if ( fetchNadd(&obj->obj_refcnt, -1) == 1 ) { obj->obj_class->cls_destroy(obj); } } #endif /* LAM_OBJECT_H */