/* **********************************************************
* Copyright 2007 VMware, Inc. All rights reserved. -- VMware Confidential
* **********************************************************/
/**
* @file VMCFClass.h
*
* This file contains macros that facilitate the creation of VMCF classes
* without the need for error-prone typing and copy/paste. For these to
* work, define these three macros:
*
* -# VMCF_SUPERCLASS : name of the superclass
* -# VMCF_THISMODULE : name of the module for the class being implemented.
* -# VMCF_THISCLASS : name of the class being implemented.
*
* @addtogroup VMCFCore
* @{
*/
/**
* @def VMCF_EXTERN
* @brief Tags a function for export in a shared library.
*
* Add this tag to any functions that need to be exported. In the .c file
* implementing the functions, define the "VMCF_IMPL" pre-processor variable
* before including this header file, and undef it after the inclusion.
*
* @internal These lines need to be kept outside the include guard.
*/
#undef VMCF_EXTERN
#if defined(VMCF_IMPL)
# if defined(_WIN32)
# define VMCF_EXTERN __declspec(dllexport)
# elif defined(GCC_EXPLICIT_EXPORT)
# define VMCF_EXTERN __attribute__((visibility("default")))
# else
# define VMCF_EXTERN
# endif
#else
# define VMCF_EXTERN extern
#endif
#ifndef _VMCF_CLASS_H_
#define _VMCF_CLASS_H_
/**
* @cond INTERNAL
* @{
*/
/*
* The following macros (inside the INTERNAL section) are intended for internal
* use only. They mostly handle the needed macro redirection to resolve all
* the names passed as macro arguments.
*/
#define __VMCF_PROTO_ALLOC(klass) \
void \
klass ## Impl_alloc(klass self, \
size_t extraInstanceDataSize, \
CORBA_string name, \
void *server, \
VMCFCore_CFObject parent, \
CORBA_Environment *env)
#define _VMCF_PROTO_ALLOC(klass) __VMCF_PROTO_ALLOC(klass)
/**
* @brief Instance allocation function prototype.
*
* This function is automatically generated by the VMCF_DECLARE_CLASS macro.
* It chains the call to the super-class's allocation function, making sure
* that enough data is allocated for this interface's private data.
*
* The data allocated by the top-level CFObject class is always zeroed. If an
* interface doesn't inherit from CFObject (or one of its subclasses), then
* that may not apply.
*
* @param[in] self Object being initialized.
* @param[in] extraInstanceDataSize Extra memory to be allocated for the
* object's private data.
* @param[in] name This object's name.
* @param[in] parent This object's parent object.
* @param[out] env
*
* @throw InvalidArguments If self is NULL or instance has already been
* initialized.
*/
#define VMCF_PROTO_ALLOC(klass) _VMCF_PROTO_ALLOC(klass)
/* Finalizer helper macros. */
#define __VMCF_PROTO_FINI(klass) \
void \
klass ## Impl_finalize(void *instData)
#define _VMCF_PROTO_FINI(klass) __VMCF_PROTO_FINI(klass)
/**
* @brief Creates a CFObject finalizer function prototype.
*
* This function may be called from:
* -# the ORB runtime, when an object is destroyed.
* -# from subinterfaces' @c _finalize functions (up-chaining);
* @c _finalize implementations must call the 'super'_finalize
* as the last step, after performing their own clean-up.
*
* To ease the implementation of finalizers, it's recommended that the
* @def VMCF_DEFINE_FINI_BEGIN and @def VMCF_DEFINE_FINI_END macros
* are used, like the following:
*
* @param[in] instData Private instace data; the pointer will be freed.
*/
#define VMCF_PROTO_FINI(klass) _VMCF_PROTO_FINI(klass)
/* getSubinstanceData helper macros. */
#define __VMCF_PROTO_SUBINST(klass) \
void * \
klass ## Impl_getSubinstanceData(void *instData)
#define _VMCF_PROTO_SUBINST(klass) __VMCF_PROTO_SUBINST(klass)
/**
* This function returns a pointer to the subinterface instance data.
* Any subinterface implementation must return the pointer returned by
* the call to its 'super'_getSubinstanceData', to which it adds
* the size of its own instance data.
*
* This function is normally used in conjunction with
* [fully_qualified_interface_name]__GetUserData, which takes a
* @c self argument and returns a pointer to the instance data which may
* be passed to this function.
*
* @return Pointer to subinterface instance data, or (void *)0 on error.
*/
#define VMCF_PROTO_SUBINST(klass) _VMCF_PROTO_SUBINST(klass)
/* Constructor helper macros. */
#define __VMCF_PROTO_CTOR(klass) \
klass \
klass ## Impl_create(CORBA_string name, \
void *server, \
CORBA_boolean bind, \
VMCFCore_CFObject parent, \
CORBA_Environment *env)
#define _VMCF_PROTO_CTOR(klass) __VMCF_PROTO_CTOR(klass)
/**
* @brief Creates a CFObject 'constructor' function prototype.
*
* Called to instantiate an object of this type.
* Generated @a _create functions perform the following tasks:
* -# Call the (generated) initialization function of the module
* in which the interface is defined.
* -# Call the (generated) interface finalization setter function,
* to set the _finalize function on the interface.
* -# Call the (generated) CreateTrue function and specify the
* VMCF server as the second argument.
*
* @param[in] name This object's name (passed to _alloc).
* @param[in] server The server where this object is created.
* @param[in] bind Whether the object's name will be registered with the server,
* making it available for lookups with corbaloc URLs.
* @param[in] parent This object's parent object (passed to _alloc).
* @param[out] env
*
* @return Newly created and initialized object, or NULL on error.
*/
#define VMCF_PROTO_CTOR(klass) _VMCF_PROTO_CTOR(klass)
/* Initializer helper macros. */
#define __VMCF_PROTO_INIT(klass, args) void klass ## Impl_init args
#define _VMCF_PROTO_INIT(klass, args) __VMCF_PROTO_INIT(klass, args)
#include
#include
#define _ILU_CORBA_OBJECT "ilu--corba-native-object:"
/* Instance type helper macros. */
#define __VMCF_INSTANCE_TYPE(klass) klass ## Instance
#define _VMCF_INSTANCE_TYPE(klass) __VMCF_INSTANCE_TYPE(klass)
/* Helper macros for chaining calls. */
#define __VMCF_CHAIN_TO_SUPER(prefix, super, function, args) \
prefix ## super ## function args
#define _VMCF_CHAIN_TO_SUPER(prefix, super, function, args) \
__VMCF_CHAIN_TO_SUPER(prefix, super, function, args)
#define VMCF_CHAIN_TO_SUPER(prefix, function, args) \
_VMCF_CHAIN_TO_SUPER(prefix, VMCF_SUPERCLASS, function, args)
/* Chaining macros for the base CFObject interface methods. */
#define __VMCF_DEFINE_CHAINED_GET_NAME(klass) \
CORBA_string \
server_ ## klass ## __get_name(klass self, \
CORBA_Environment *env) \
{ \
return VMCF_CHAIN_TO_SUPER_SERVER(_get_name, (self, env)); \
}
#define _VMCF_DEFINE_CHAINED_GET_NAME(klass) \
__VMCF_DEFINE_CHAINED_GET_NAME(klass)
#define __VMCF_DEFINE_CHAINED_PROBE(klass) \
void \
server_ ## klass ## _probe(klass self, \
CORBA_Environment *env) \
{ \
VMCF_CHAIN_TO_SUPER_SERVER(probe, (self, env)); \
}
#define _VMCF_DEFINE_CHAINED_PROBE(klass) \
__VMCF_DEFINE_CHAINED_PROBE(klass)
/* Definition of auto-generated functions (create/alloc/subinstance). */
#define __VMCF_DEFINE_CTOR_BODY(module, klass) \
{ \
CORBA_string corbalocName = NULL; \
klass self; \
\
VMCF_ASSERT_ARG(server, env, return NULL); \
\
module ## __InitializeServer(); \
klass ## __SetDefaultClassFinalization(klass ## Impl_finalize); \
\
if (bind) { \
size_t len; \
VMCF_ASSERT_ARG(name != NULL, env, return NULL); \
len = strlen(_ILU_CORBA_OBJECT) + strlen(name) + 1; \
corbalocName = CORBA_string_alloc((CORBA_unsigned_long)len); \
VMCF_ASSERT_ALLOC(corbalocName, env, return NULL); \
snprintf(corbalocName, len, _ILU_CORBA_OBJECT "%s", name); \
} \
\
self = klass ## __CreateTrue(corbalocName, \
(ILU_C_Server)server, \
NULL); \
CORBA_free(corbalocName); \
VMCF_ASSERT_ALLOC(self, env, return NULL); \
klass ## Impl_alloc(self, 0, (name), (server), (parent), env); \
return self; \
}
#define _VMCF_DEFINE_CTOR_BODY(module, klass) \
__VMCF_DEFINE_CTOR_BODY(module, klass)
/** Macro to generate the implementation of a class' constructor ("create"). */
#define VMCF_DEFINE_CTOR \
VMCF_PROTO_CTOR(VMCF_THISCLASS) \
_VMCF_DEFINE_CTOR_BODY(VMCF_THISMODULE, VMCF_THISCLASS)
#define __VMCF_DEFINE_ALLOC_BODY(instType) \
{ \
instType *inst; \
VMCF_CHAIN_TO_SUPER_IMPL(alloc, \
(self, (extraInstanceDataSize + sizeof *inst), \
name, server, parent, env)); \
if (VMCF_EXCEPTION_RAISED(env)) { \
return; \
} \
}
#define _VMCF_DEFINE_ALLOC_BODY(instType) \
__VMCF_DEFINE_ALLOC_BODY(instType)
/** Macro to generate the implementation of a class' instance "alloc". */
#define VMCF_DEFINE_ALLOC \
VMCF_PROTO_ALLOC(VMCF_THISCLASS) \
_VMCF_DEFINE_ALLOC_BODY(VMCF_INSTANCE_TYPE)
#define __VMCF_DEFINE_SUBINST_BODY(instType) \
{ \
char *myData; \
myData = (char *)VMCF_CHAIN_TO_SUPER_IMPL(getSubinstanceData, (instData)); \
return myData + sizeof (instType); \
}
#define _VMCF_DEFINE_SUBINST_BODY(instType) \
__VMCF_DEFINE_SUBINST_BODY(instType)
/** Macro to generate the implementation of a class' "getSubinstanceData". */
#define VMCF_DEFINE_SUBINST \
VMCF_PROTO_SUBINST(VMCF_THISCLASS) \
_VMCF_DEFINE_SUBINST_BODY(VMCF_INSTANCE_TYPE)
/**
* @}
* @endcond
*/
/**
* Declares the prototypes of functions in a VMCF class. Used in header files.
*
* @param[in] klass Name of the class being created.
* @param[in] initArgs Argument list for the @a init() function.
*/
#define VMCF_DECLARE_CLASS(klass, initArgs) \
VMCF_EXTERN VMCF_PROTO_ALLOC(klass); \
\
VMCF_EXTERN VMCF_PROTO_FINI(klass); \
\
VMCF_EXTERN VMCF_PROTO_SUBINST(klass); \
\
VMCF_EXTERN VMCF_PROTO_CTOR(klass); \
\
VMCF_EXTERN _VMCF_PROTO_INIT(klass, initArgs);
/**
* Defines the start of the finalizer function for a class. A finalizer
* should be implemented in the following way:
*
* @code
*
* VMCF_DEFINE_FINI_BEGIN {
* // Finalizer implementation. "inst" is a variable pointing
* // to the instance's private data. It's guaranteed to be
* // not NULL, and shouldn't be freed here.
* } VMCF_DEFINE_FINI_END;
*
* @endcode
*
* @see VMCF_DEFINE_FINI_END
*/
#define VMCF_DEFINE_FINI_BEGIN \
VMCF_PROTO_FINI(VMCF_THISCLASS) \
{ \
VMCF_INSTANCE_TYPE *inst = VMCF_GET_SUBINSTANCE_DATA((instData)); \
if (!inst) { \
return; \
}
/**
* Defines the end of a finalizer function for a class. Takes care of chaining
* the finalization up the inheritance chain.
*
* @see VMCF_PROTO_FINI
*/
#define VMCF_DEFINE_FINI_END \
VMCF_CHAIN_TO_SUPER_IMPL(finalize, (instData)); \
}
/**
* @brief Defines the prototype of the 'initializer' function.
*
* This function is called to perform custom initialization of CFObject
* instances, after they've been allocated by calling 'create'.
*
* This function can have a custom signature depending on the object, but
* as a convention the first parameter should always be the instance pointer,
* and the last parameter a pointer to a CORBA_Environment.
*
* Implementations are responsible for chaining the call to the super class's
* initializer function. The code calling @ _init() shouldn't try to use the
* object if an exception is raised, since it might have been freed by the
* runtime.
*
* @param[in] args The function signature.
*/
#define VMCF_PROTO_INIT(args) _VMCF_PROTO_INIT(VMCF_THISCLASS, args)
/**
* @brief Epilogue for initialization functions.
*
* Checks whether an exception was raised and releases the object if so. This
* should be called from the class's @a _init() function, after it has checked
* for the super class's successful initialization.
* Note that the second argument ('activate') in the 'super' call should be
* FALSE to ensure object activation happens only on complete initialization.
* For example:
*
* @code
*
* VMCF_CHAIN_TO_SUPER_IMPL(init, (self, CORBA_FALSE, env));
*
* if (!VMCF_EXCEPTION_RAISED(env)) {
* // Perform class initialization.
* VMCF_INIT_EPILOGUE(self, activate, env);
* }
*
* @endcode
*/
#define VMCF_INIT_EPILOGUE(self, activate, env) { \
if (self) { \
if (VMCF_EXCEPTION_RAISED((env))) { \
CORBA_Environment _lenv = { CORBA_NO_EXCEPTION }; \
CORBA_Object_release((self), &_lenv); \
CORBA_exception_free(&_lenv); \
} else if (activate) { \
ilu_ActivateObject(self->iluco_ko); \
} \
} \
}
/**
* Macro to generate an instance type name, based on the implemented class.
* Implementations should use this to define the data type for their
* private data:
*
* typedef [private data type] VMCF_INSTANCE_TYPE;
*/
#define VMCF_INSTANCE_TYPE _VMCF_INSTANCE_TYPE(VMCF_THISCLASS)
/**
* Macro to call a "server" function in the super class.
*
* @param[in] function Name of the function (without the "server_" and class
* name prefixes).
* @param[in] args The arguments to pass to the call (enclosed in parentheses).
*/
#define VMCF_CHAIN_TO_SUPER_SERVER(function, args) \
VMCF_CHAIN_TO_SUPER(server_, _ ## function, args)
/**
* Macro to call an implementation function in the super class.
*
* @param[in] function Name of the function (without the class name prefix).
* @param[in] args The arguments to pass to the call (enclosed in parentheses).
*/
#define VMCF_CHAIN_TO_SUPER_IMPL(function, args) \
VMCF_CHAIN_TO_SUPER(, Impl_ ## function, args)
/**
* Macro used to get a pointer to the entire (root) instance data. This returns
* a pointer to the private data of the base class in the inheritance chain,
* not to the private data of the current instance.
*/
#define VMCF_USER_DATA(self) (((ILU_C_Object *)(self))->instanceData)
/**
* A shorthand macro to get a subinstance's private data, given the root
* pointer for the instance's private data.
*
* @param[in] data Pointer to the class's private data.
*/
#define VMCF_GET_SUBINSTANCE_DATA(data) \
VMCF_CHAIN_TO_SUPER_IMPL(getSubinstanceData, (data))
/**
* A shorthand macro to get an instance's private data, given a pointer
* to the instance object.
*
* @param[in] self Pointer to the class's instance.
*/
#define VMCF_GET_SELF_DATA(self) \
VMCF_GET_SUBINSTANCE_DATA(VMCF_USER_DATA(self))
/**
* Create the server function to chain a call to the super class's
* "_get_name()" attribute getter (method).
*
* @param[in] klass Name of the class.
*/
#define VMCF_DEFINE_CHAINED_GET_NAME \
_VMCF_DEFINE_CHAINED_GET_NAME(VMCF_THISCLASS)
/**
* Create the server function to chain a call to the super class's
* "probe()" method.
*
* @param[in] klass Name of the class.
*/
#define VMCF_DEFINE_CHAINED_PROBE \
_VMCF_DEFINE_CHAINED_PROBE(VMCF_THISCLASS)
/**
* Macro to define the implementations of a class' "create", "alloc" and
* "getSubinstanceData".
*/
#define VMCF_DEFINE_CLASS \
VMCF_DEFINE_CTOR \
VMCF_DEFINE_ALLOC \
VMCF_DEFINE_SUBINST
#endif /* _VMCF_CLASS_H_*/
/** @} */