votca 2025.1-dev
Loading...
Searching...
No Matches
checkpoint_utils.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 *
15 */
16
17#pragma once
18#ifndef VOTCA_XTP_CHECKPOINT_UTILS_H
19#define VOTCA_XTP_CHECKPOINT_UTILS_H
20
21// Standard includes
22#include <cstddef>
23#include <cstring>
24#include <mutex>
25#include <string>
26
27// Third party includes
28#include <H5Cpp.h>
29
30// VOTCA includes
31#include <votca/tools/types.h>
32
33namespace votca {
34namespace xtp {
35
36using CptLoc = H5::Group;
37
39
40inline H5::DataSpace StrScalar() { return H5::DataSpace(H5S_SCALAR); }
41
42/*
43 * ======================= HDF5 THREAD-SAFETY NOTE =======================
44 *
45 * IMPORTANT:
46 * ----------
47 * The HDF5 C++ API (H5::*) as provided by Homebrew and most system builds
48 * is NOT thread-safe, even when different threads operate on different
49 * files. In particular:
50 *
51 * - HDF5 maintains global internal state
52 * - H5::Attribute, H5::DataSet, H5::Group, and H5::H5File call HDF5
53 * close functions (H5Aclose, H5Dclose, H5Gclose, H5Fclose) in their
54 * destructors
55 * - These destructors may run after leaving local scopes and MUST NOT
56 * execute concurrently with other HDF5 calls
57 *
58 * Failure to serialize *all* HDF5 activity (including destruction) leads
59 * to hard-to-debug runtime errors such as:
60 *
61 * - "Attribute::~Attribute - H5Aclose failed"
62 * - sporadic std::runtime_error from HDF5
63 * - segmentation faults under multithreading
64 *
65 * DESIGN DECISION:
66 * ----------------
67 * We enforce process-wide serialization of all HDF5 access using a single
68 * global recursive mutex (Hdf5Mutex).
69 *
70 * - The mutex is recursive because HDF5 calls are layered:
71 * CheckpointWriter -> CptTable -> HDF5
72 * - All HDF5-related code must lock this mutex
73 * - High-level operations (e.g. JobTopology::WriteToHdf5 / ReadFromHdf5)
74 * MUST hold the lock for their entire duration so that all HDF5 object
75 * destructors run while the mutex is held
76 *
77 * RULES FOR DEVELOPERS:
78 * --------------------
79 * 1) Any code that creates, reads, writes, or closes HDF5 objects MUST
80 * hold Hdf5Mutex().
81 *
82 * 2) If a function creates HDF5 objects whose destructors run at function
83 * exit, the lock MUST span the entire function scope.
84 *
85 * 3) Never call HDF5 (directly or indirectly) without holding this lock,
86 * even if the file names differ.
87 *
88 * 4) Do NOT remove or replace this mutex unless the entire HDF5 stack
89 * is redesigned (e.g. single-writer thread or MPI HDF5).
90 *
91 * This policy is REQUIRED for correct behavior under multithreading.
92 * ========================================================================
93 */
94inline std::recursive_mutex& Hdf5Mutex() {
95 static std::recursive_mutex m;
96 return m;
97}
98
99// Declare some HDF5 data type inference stuff:
100// Adapted from
101// https://github.com/garrison/eigen3-hdf5/blob/2c782414251e75a2de9b0441c349f5f18fe929a2/eigen3-hdf5.hpp#L18
102
103template <typename T>
105
106template <>
107struct InferDataType<float> {
108 static const H5::DataType* get(void) { return &H5::PredType::NATIVE_FLOAT; }
109};
110
111template <>
112struct InferDataType<double> {
113 static const H5::DataType* get(void) { return &H5::PredType::NATIVE_DOUBLE; }
114};
115
116template <>
117struct InferDataType<int> {
118 static const H5::DataType* get(void) { return &H5::PredType::NATIVE_INT; }
119};
120
121template <>
122struct InferDataType<long int> {
123 static const H5::DataType* get(void) { return &H5::PredType::NATIVE_LONG; }
124};
125
126template <>
127struct InferDataType<unsigned> {
128 static const H5::DataType* get(void) { return &H5::PredType::NATIVE_UINT; }
129};
130
131template <>
132struct InferDataType<std::string> {
133 static const H5::DataType* get(void) {
134
135#if (defined(__GNUC__) && defined(__clang__))
136#pragma clang diagnostic push
137#pragma clang diagnostic ignored "-Wconversion"
138#elif (defined(__GNUC__) && !defined(__INTEL_COMPILER))
139#pragma GCC diagnostic push
140#pragma GCC diagnostic ignored "-Wconversion"
141#elif (defined(__INTEL_COMPILER))
142#pragma warning push
143#pragma warning(disable : 1682) // implicit conversion of a 64-bit integral
144 // type to a smaller integral type
145#endif
146 static const H5::StrType strtype(H5T_C_S1, H5T_VARIABLE);
147#if (defined(__GNUC__) && defined(__clang__))
148#pragma clang diagnostic pop
149#elif (defined(__GNUC__) && !defined(__INTEL_COMPILER))
150#pragma GCC diagnostic pop
151#elif (defined(__INTEL_COMPILER))
152#pragma warning pop
153#endif
154
155 return &strtype;
156 }
157};
158
159} // namespace checkpoint_utils
160} // namespace xtp
161} // namespace votca
162#endif // VOTCA_XTP_CHECKPOINT_UTILS_H
STL namespace.
std::recursive_mutex & Hdf5Mutex()
H5::Group CptLoc
Provides a means for comparing floating point numbers.
Definition basebead.h:33