/* ********************************************************** * 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_*/ /** @} */