[svn-r27945] Purpose: Fix HDFFV-9529

Description:
    Merged from hdf5_CppAPI_Constants

    r27942:
    ------
    Description:
    - Added H5dont_atexit() to getPredType and all the getConstant's to prevent
    the C library from terminating before the C++ library cleanup.
    - More cleanup and added more comments

    r27923:
    ------
    - Updated more comments and moved some things around for consistency
    - Removed check for "new" failure, exceptions would be thrown

    r27922:
    ------
    Description:
        Added function headers and more comments for clarity.

    r27917:
    ------
    Description:
        The C++ library has several types of global constants from different
        classes, such as PropList, PredType, DataSpace, etc...  Previously,
        these global constants were declared statically and the C++ library used
        a constant, called PredType::AtExit, to detect when all the global
        contants are destroyed then close the C library (H5close).  This method
        relied on the order of the constants being created and destroyed and
        that PredType constants be the last to be destroyed.  In September 2015,
        it was recognized that the order in which the global constants were
        created and destroyed was actually undefined, thus can be different
        between different compilers.  This resulted in failure when compilers
        destroy PredType constants before others because when PredType::AtExit
        was destroyed, the C library was closed, so when the constants of other
        classes such as PropList or DataSpace were being deleted, the C library
        would not be available.

    Solution:
        The static approach is changed to dynamic.  In order to avoid an impact
        on existing applications, the static global constants are changed to
        constant references to the dynamically allocated objects.
        A detailed explanation of the new method and a description of the
        changes are in a Design Notes at the end of the file H5PredType.cpp.

        New functions added to support the new methods are listed below.

        class H5Library:
                // Returns a singleton H5Library to initialize the global
                // constants, invoked in IdComponent default constructor
                static H5Library* getInstance(); // public

                // Registers cleanup and terminating functions with atexit(),
                // called in IdComponent default constructor
                static void initH5cpp(void); // public

                // Calls H5close to terminate the library, registered with
                // atexit(), as the last thing to be done.
                static void termH5cpp(void); // public

        class PredType:
                // Creates the constants
                static void makePredTypes(); // private

                // Calls makePredTypes to create the constants and returns
                // the dummy constant PREDTYPE_CONST;
                static PredType* getPredTypes(); // private

        class DataSpace:
                // Creates the constant
                static DataSpace* getConstant(); // private

        class PropList:
                // Creates the constant
                static PropList* getConstant(); // private

        class DSetCreatPropList:
                // Creates the constant
                static DSetCreatPropList* getConstant(); // private

        class DSetMemXferPropList:
                // Creates the constant
                static DSetMemXferPropList* getConstant(); // private

        class FileCreatPropList:
                // Creates the constant
                static FileCreatPropList* getConstant(); // private

        class FileAccPropList:
                // Creates the constant
                static FileAccPropList* getConstant(); // private

        This function is added to PredType, DataSpace, PropList, and the four
        subclasses of PropList:
                // Deletes the constant
                static void deleteConstants(); // public

Platforms tested:
    Linux/32 2.6 (jam)
    Linux/64 (platypus)
    Darwin (osx1010test)
This commit is contained in:
Binh-Minh Ribler
2015-10-04 00:05:51 -05:00
parent 0ef29b550b
commit 888a002cdd
22 changed files with 1940 additions and 474 deletions

View File

@@ -14,10 +14,22 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <string>
#include <cstdlib>
#include "H5CppDoc.h" // included only for Doxygen to generate part of RM
#include "H5CppDoc.h" // included only for Doxygen to generate part of RM
#include "H5Include.h"
#include "H5Exception.h"
#include "H5IdComponent.h"
#include "H5PropList.h"
#include "H5FaccProp.h"
#include "H5FcreatProp.h"
#include "H5DxferProp.h"
#include "H5Object.h"
#include "H5DataType.h"
#include "H5DcreatProp.h"
#include "H5AtomType.h"
#include "H5PredType.h"
#include "H5DataSpace.h"
#include "H5Library.h"
#ifndef H5_NO_NAMESPACE
@@ -25,8 +37,7 @@ namespace H5 {
#endif
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// This static variable will be set to true when dontAtExit is called
bool H5Library::need_cleanup = false;
H5Library* H5Library::instance = 0;
#endif // DOXYGEN_SHOULD_SKIP_THIS
//--------------------------------------------------------------------------
@@ -63,18 +74,17 @@ void H5Library::close()
//--------------------------------------------------------------------------
// Function: H5Library::dontAtExit
///\brief Instructs library not to install \c atexit cleanup routine
///\brief Instructs library not to install the C \c atexit cleanup routine
///
///\exception H5::LibraryIException
// Programmer Binh-Minh Ribler - 2000
// Modification
// Removed the check for failure returned from H5dont_atexit.
// will be fixed to not fail (HDFFV-9540)
//--------------------------------------------------------------------------
void H5Library::dontAtExit()
{
herr_t ret_value = H5dont_atexit();
if( ret_value < 0 )
{
throw LibraryIException("H5Library::dontAtExit", "H5dont_atexit failed");
}
}
//--------------------------------------------------------------------------
@@ -147,6 +157,91 @@ void H5Library::garbageCollect()
}
}
//--------------------------------------------------------------------------
// Function: H5Library::initH5cpp
///\brief Initializes C++ library and registers terminating functions at
/// exit. Only for the library functions, not for user-defined
/// functions.
// Description
// initH5cpp registers the following functions with std::atexit():
// termH5cpp() - calls H5close() after all cleanup in
// the C++ library is done
// <classname>::deleteConstants - deletes all references for
// <classname> global constants
///\exception H5::LibraryIException
//
// Programmer Binh-Minh Ribler - September, 2015
//--------------------------------------------------------------------------
void H5Library::initH5cpp()
{
// Register terminating functions with atexit(); they will be invoked in the
// reversed order
int ret_value = 0;
ret_value = std::atexit(termH5cpp);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of termH5cpp failed");
ret_value = std::atexit(PredType::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of PredType::deleteConstants failed");
ret_value = std::atexit(PropList::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of PropList::deleteConstants failed");
ret_value = std::atexit(FileAccPropList::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of FileAccPropList::deleteConstants failed");
ret_value = std::atexit(FileCreatPropList::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of FileCreatPropList::deleteConstants failed");
ret_value = std::atexit(DSetMemXferPropList::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of DSetMemXferPropList::deleteConstants failed");
ret_value = std::atexit(DSetCreatPropList::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of DSetCreatPropList::deleteConstants failed");
ret_value = std::atexit(DataSpace::deleteConstants);
if (ret_value != 0)
throw LibraryIException("H5Library::initH5cpp", "Registration of DataSpace::deleteConstants failed");
}
//--------------------------------------------------------------------------
// Function: H5Library::termH5cpp
///\brief Sends request for the C layer to terminate.
///\par Description
/// If the C library fails to terminate, exit with a failure.
// Programmer Binh-Minh Ribler - September, 2015
//--------------------------------------------------------------------------
void H5Library::termH5cpp()
{
// Close the C library
herr_t ret_value = H5close();
if (ret_value == -1)
exit(-1);
}
//--------------------------------------------------------------------------
// Function: H5Library::getInstance
///\brief Provides a way to instantiate the class.
///\par Description
/// getInstance ensures that only one instance of the H5Library
/// is created.
// Programmer Binh-Minh Ribler - September, 2015
//--------------------------------------------------------------------------
H5Library* H5Library::getInstance()
{
if (H5Library::instance == 0)
{
instance = new H5Library();
}
return(instance);
}
//--------------------------------------------------------------------------
// Function: H5Library::setFreeListLimits
///\brief Sets limits on the different kinds of free lists.
@@ -174,6 +269,13 @@ void H5Library::setFreeListLimits(int reg_global_lim, int reg_list_lim,
throw LibraryIException("H5Library::setFreeListLimits", "H5set_free_list_limits failed");
}
}
// Default constructor - no instance ever created by outsiders
H5Library::H5Library(){};
// Destructor
H5Library::~H5Library(){};
#ifndef H5_NO_NAMESPACE
} // end namespace
#endif