#ifndef TAL_OBJBASE_H
#define TAL_OBJBASE_H

/*
**	LibV internal master header: object manager.
*/ 

#ifdef	V_LIB_H
#error	This file must be #included prior to 'v_lib.h'.
#endif	/* V_LIB_H */

#ifndef	__LIBV__
#define	__LIBV__
#endif

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

/*
**	Macros used by memory management functions.
*/
#define	MEMORY_HASHPROC(ptr) \
		(((u32_t)(ptr) + ((u32_t)(ptr) >> 4) + \
          ((u32_t)(ptr) >> 8)) & MEMORY_HASH_LIMIT)

#define	OBJECT_HASHPROC(ptr) \
		(((u32_t)(ptr) + ((u32_t)(ptr) >> 4) + \
          ((u32_t)(ptr) >> 8)) & OBJECT_HASH_LIMIT)

/*
**	Base object for most LibV objects.
*/
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;
	/*
	 * Destructor must decrement self->ref_count and if it
	 * reaches 0 - perform cleanup.
	 */
	u32_t	(V_CALL *destroy)(void *self);
	/*
	 * That's all; pure abstract, isn't it ? :)
	 */
}	libv_object_t, *libv_object_p;

/*
 * Macro for injecting DWORD object identifiers.
 */
#ifdef	CHECKED_BUILD
#define	MARK_OBJECT(object,magic)	*((u32_t*)(object))=(u32_t)(magic)
#else	/* !CHECKED_BUILD */
#define	MARK_OBJECT(object,magic)
#endif	/* !CHECKED_BUILD */

/*
 * Constructor.
 * Implemenation as macro is much more useful, although less intuitive.
 */
#define	ALLOC_OBJECT(ptr,type,extra_memory,magic) \
		{ \
			u32_t cksize = sizeof(type)+(extra_memory); \
			(ptr)=(type*)memAllocObject(cksize); \
            V_ASSERT(ptr); \
			memZero((ptr),cksize); \
            ((libv_object_t*)(ptr))->ref_count=1; \
			((libv_object_t*)(ptr))->destroy=libv_object_destructor; \
			MARK_OBJECT(ptr,magic); \
        }

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

#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);
	/* -------------------------------------------------------------------
	 *	Function for checking object handles.
	 *
	 *	Returns NULL (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 */
	/*
     * Function for closing object handles.
     * Calls handle->destroy(handle), which, in turn, decreases
     * handle's reference counter, and if it reaches 0 - destroys object.
     * 
     * 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_object_destructor(vhandle_t handle);
	/* Quiet version of libv_object_destructor() */
	u32_t	V_CALL	libv_object_destructor_quiet(vhandle_t handle);
#ifdef	__cplusplus
}
#endif	/* __cplusplus */

#endif	/* TAL_OBJBASE_H */
