#ifndef TAL_OBJBASE_H
#define TAL_OBJBASE_H

/*
 * LibV internal master header: object manager.
 *
 * Status: acceptable (05.07.05)
 */ 

#ifdef	V_LIB_H
#error	"Either v_lib.h or this file can be #included."
#endif	/* V_LIB_H */

#ifndef	__LIBV__
#define	__LIBV__
#endif

#include <v_lib.h>
#include <../source/PAL/dataman.h>

#define	archMemAlloc(cksize)		malloc(cksize)
#define	archMemFree(ptr)			free(ptr)
#define	archMemRealloc(ptr,newsize)	realloc(ptr,newsize)

/*
 * Base class.
 */
typedef struct libv_object_s
{
#ifdef	CHECKED_BUILD
	/*
	 * Run-time type information
	 */
	u32_t	magic;
#endif	/* CHECKED_BUILD */
	/*
	 * If ref_count == 1, then object will be destroyed at next
	 * call of destructor.
	 */
	u32_t	ref_count;
	/*
	 * If inherited_destroy == NULL, than destructor must decrement
	 * self->ref_count and perform cleanup when it reaches zero.
	 */
	u32_t	(V_CALL *destroy)(vhandle_t self);
	/*
	 * Inherited destructor from base class (can be NULL).
	 */
	u32_t	(V_CALL *inherited_destroy)(vhandle_t self);
}	libv_object_t, *libv_object_p;

/*
 * ANSI C RTTI :)
 */

#ifdef	CHECKED_BUILD

#define	GET_MAGIC_PTR(object)		((u32_t*)object)
#define	CHECK_MAGIC(object,magic)	(*GET_MAGIC_PTR(object) != (magic))
#define	MARK_OBJECT(object,magic)	(*GET_MAGIC_PTR(object) = (magic))

#else	/* !CHECKED_BUILD */

#define	CHECK_MAGIC(object,magic)	(object != LIBV_INVALID_HANDLE)
#define	MARK_OBJECT(object,magic)

#endif	/* !CHECKED_BUILD */

/*
 * The constructor.
 * Implemenation as a macro _is_ useful, although may not be intuitive.
 */
#define	ALLOC_OBJECT(ptr,type,extra_memory,magic) \
	{ \
		u32_t cksize = sizeof(type) + (extra_memory); \
		(ptr) = (type*)memAllocObject(cksize); \
		if(ptr == LIBV_INVALID_HANDLE) \
			return LIBV_INVALID_HANDLE; \
		memZero((ptr),cksize); \
		((libv_object_t*)(ptr))->ref_count = 1; \
		((libv_object_t*)(ptr))->destroy = libv_destruct_and_complain; \
		((libv_object_t*)(ptr))->inherited_destroy = NULL; \
		MARK_OBJECT(ptr,magic); \
	}

/*
 * Macro for obtaining objects derived from base class.
 */
#define	CHECK_AND_GET_OBJECT(type,handle,caller,object,magic) \
		((type*)libvIsHandle(handle,caller,object,magic))

/*
 * Helper macro to use in destructor: returns decremented
 * reference counter, if later was greater than 1.
 */
#define	UNREF_EXIT(descendant_ptr) \
	if(--(descendant_ptr)->base.ref_count) \
		return (descendant_ptr)->base.ref_count

#ifdef	__cplusplus
extern "C" {
#endif	/* __cplusplus */
	/*
	 * Object-specific memory management.
	 */
	vhandle_t	V_CALL		memAllocObject(size_t size);
	void		V_GLOBAL	memFreeObject(vhandle_t ptr);
	/*
	 * Returns 'true' if 'ptr' was allocated via call to
	 * memAllocObject().
	 */
	vboolean		V_CALL	memIsObject(vhandle_t ptr);
	/*
	 *	libvIsHandle(): check if given handle is valid.
	 *
	 *	Returns LIBV_INVALID_HANDLE (and complains an error) if:
	 *		a)	agrument was not created via memAllocObject();
	 *		b)	(when CHECKED_BUILD) first DWORD of memory pointed
	 *			by 'handle' != magic.
	 *	Otherwise returns 'handle' back.
	 *	Implemented in TAL/objbase.c.
	 */
#ifdef	CHECKED_BUILD
	void_p	V_CALL	libvIsHandle(vhandle_t handle,
		char *caller,	/* Name of function handle passed to */
		char *object,	/* Sence of handle: file, ipc, etc... */
		u32_t magic);	/* Magic: must be in FIRST DWORD of object */
#else	/* !CHECKED_BUILD */
#define	libvIsHandle(handle,caller,object,magic)	(handle)
#endif	/* CHECKED_BUILD */
	/*
	 * libvCloseHandle() close the handle of object.
	 * Calls handle->destroy(handle), which, in turn, decreases
	 * handle's reference counter. When it reaches 0 the object have to be
	 * destroyed (by its own destructor, _not_ this routine).
	 * 
	 * Returns new (decreased) reference counter:
	 *  0 - object destroyed;
	 *	> 0 - there are still references to object.
	 */
#ifdef	CHECKED_BUILD
	u32_t V_CALL	libvCloseHandle(vhandle_t handle,
		char *caller,	/* Name of function handle passed to */
		char *object,	/* Sence of handle: file, ipc, etc... */
		u32_t magic);	/* Magic: must be in FIRST DWORD of object */
#else	/* !CHECKED_BUILD */
#define	libvCloseHandle(handle,caller,object,magic)	\
		__libvCloseHandle(handle)
#endif	/* CHECKED_BUILD */
	/* Quiet version of libvCloseHandle() */
	u32_t	V_CALL	__libvCloseHandle(vhandle_t handle);
	/* Default object's destructor (prints warning message) */
	u32_t	V_CALL	libv_destruct_and_complain(vhandle_t handle);
	/* Quiet version of libv_destruct_and_complain() */
	u32_t	V_CALL	libv_default_destructor(vhandle_t handle);
#ifdef	__cplusplus
}
#endif	/* __cplusplus */

#endif	/* TAL_OBJBASE_H */
