File indexing completed on 2025-01-18 10:06:09
0001
0002 #ifndef PODIO_GENERICPARAMETERS_H
0003 #define PODIO_GENERICPARAMETERS_H 1
0004
0005 #include "podio/utilities/TypeHelpers.h"
0006
0007 #include <algorithm>
0008 #include <iostream>
0009 #include <iterator>
0010 #include <map>
0011 #include <memory>
0012 #include <mutex>
0013 #include <optional>
0014 #include <string>
0015 #include <vector>
0016
0017 #if PODIO_ENABLE_SIO
0018 namespace sio {
0019 class read_device;
0020 class write_device;
0021 using version_type = uint32_t;
0022 }
0023 #endif
0024
0025 #if PODIO_ENABLE_RNTUPLE
0026 namespace podio {
0027 class RNTupleReader;
0028 class RNTupleWriter;
0029 }
0030 #endif
0031
0032 namespace podio {
0033
0034 #if !defined(__CLING__)
0035
0036
0037 class ROOTReader;
0038 #endif
0039
0040
0041 using SupportedGenericDataTypes = std::tuple<int, float, std::string, double>;
0042
0043
0044 template <typename T>
0045 static constexpr bool isSupportedGenericDataType = detail::isAnyOrVectorOf<T, SupportedGenericDataTypes>;
0046
0047
0048
0049 template <typename T>
0050 using EnableIfValidGenericDataType = typename std::enable_if_t<isSupportedGenericDataType<T>>;
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 class GenericParameters {
0061 public:
0062 template <typename T>
0063 using MapType = std::map<std::string, std::vector<T>>;
0064
0065 private:
0066
0067 using MutexPtr = std::unique_ptr<std::mutex>;
0068
0069 public:
0070 GenericParameters();
0071
0072
0073
0074
0075 GenericParameters(const GenericParameters&);
0076 GenericParameters& operator=(const GenericParameters&) = delete;
0077
0078
0079 GenericParameters(GenericParameters&&) = default;
0080 GenericParameters& operator=(GenericParameters&&) = default;
0081
0082 ~GenericParameters() = default;
0083
0084 template <typename T>
0085 std::optional<T> get(const std::string& key) const;
0086
0087
0088 template <typename T>
0089 void set(const std::string& key, T value);
0090
0091
0092 void set(const std::string& key, const char* value) {
0093 set<std::string>(key, std::string(value));
0094 }
0095
0096
0097 void set(const std::string& key, std::vector<std::string> values) {
0098 set<std::vector<std::string>>(key, std::move(values));
0099 }
0100
0101
0102 template <typename T, typename = std::enable_if_t<detail::isInTuple<T, SupportedGenericDataTypes>>>
0103 void set(const std::string& key, std::initializer_list<T>&& values) {
0104 set<std::vector<T>>(key, std::move(values));
0105 }
0106
0107
0108 template <typename T, template <typename...> typename VecLike>
0109 void loadFrom(VecLike<std::string> keys, VecLike<std::vector<T>> values);
0110
0111
0112 template <typename T, typename = EnableIfValidGenericDataType<T>>
0113 size_t getN(const std::string& key) const;
0114
0115
0116 template <typename T>
0117 std::vector<std::string> getKeys() const;
0118
0119
0120 template <typename T>
0121 std::tuple<std::vector<std::string>, std::vector<std::vector<T>>> getKeysAndValues() const;
0122
0123
0124 void clear() {
0125 _intMap.clear();
0126 _floatMap.clear();
0127 _stringMap.clear();
0128 }
0129
0130 void print(std::ostream& os = std::cout, bool flush = true) const;
0131
0132
0133 bool empty() const {
0134 return _intMap.empty() && _floatMap.empty() && _stringMap.empty();
0135 }
0136
0137 #if PODIO_ENABLE_SIO
0138 friend void writeGenericParameters(sio::write_device& device, const GenericParameters& parameters);
0139 friend void readGenericParameters(sio::read_device& device, GenericParameters& parameters, sio::version_type version);
0140 #endif
0141
0142 #if PODIO_ENABLE_RNTUPLE
0143 friend RNTupleReader;
0144 friend RNTupleWriter;
0145 #endif
0146
0147 #if !defined(__CLING__)
0148 friend ROOTReader;
0149 #endif
0150
0151
0152 template <typename T>
0153 const MapType<detail::GetVectorType<T>>& getMap() const {
0154 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0155 return _intMap;
0156 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0157 return _floatMap;
0158 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0159 return _doubleMap;
0160 } else {
0161 return _stringMap;
0162 }
0163 }
0164
0165 private:
0166
0167 template <typename T>
0168 MapType<detail::GetVectorType<T>>& getMap() {
0169 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0170 return _intMap;
0171 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0172 return _floatMap;
0173 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0174 return _doubleMap;
0175 } else {
0176 return _stringMap;
0177 }
0178 }
0179
0180
0181 template <typename T>
0182 std::mutex& getMutex() const {
0183 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0184 return *(m_intMtx.get());
0185 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0186 return *(m_floatMtx.get());
0187 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0188 return *(m_doubleMtx.get());
0189 } else {
0190 return *(m_stringMtx.get());
0191 }
0192 }
0193
0194 private:
0195 MapType<int> _intMap{};
0196 mutable MutexPtr m_intMtx{nullptr};
0197 MapType<float> _floatMap{};
0198 mutable MutexPtr m_floatMtx{nullptr};
0199 MapType<std::string> _stringMap{};
0200 mutable MutexPtr m_stringMtx{nullptr};
0201 MapType<double> _doubleMap{};
0202 mutable MutexPtr m_doubleMtx{nullptr};
0203 };
0204
0205 template <typename T>
0206 std::optional<T> GenericParameters::get(const std::string& key) const {
0207 static_assert(podio::isSupportedGenericDataType<T>, "Unsupported parameter type");
0208 const auto& map = getMap<T>();
0209 auto& mtx = getMutex<T>();
0210 std::lock_guard lock{mtx};
0211 const auto it = map.find(key);
0212 if (it == map.end()) {
0213 return std::nullopt;
0214 }
0215
0216
0217 if constexpr (detail::isVector<T>) {
0218 return it->second;
0219 } else {
0220 const auto& iv = it->second;
0221 return iv[0];
0222 }
0223 }
0224
0225 template <typename T>
0226 void GenericParameters::set(const std::string& key, T value) {
0227 static_assert(podio::isSupportedGenericDataType<T>, "Unsupported parameter type");
0228 auto& map = getMap<T>();
0229 auto& mtx = getMutex<T>();
0230
0231 if constexpr (detail::isVector<T>) {
0232 std::lock_guard lock{mtx};
0233 map.insert_or_assign(key, std::move(value));
0234 } else {
0235
0236 std::vector<T> v = {std::move(value)};
0237 std::lock_guard lock{mtx};
0238 map.insert_or_assign(key, std::move(v));
0239 }
0240 }
0241
0242 template <typename T, typename>
0243 size_t GenericParameters::getN(const std::string& key) const {
0244 const auto& map = getMap<T>();
0245 auto& mtx = getMutex<T>();
0246 std::lock_guard lock{mtx};
0247 if (const auto it = map.find(key); it != map.end()) {
0248 return it->second.size();
0249 }
0250 return 0;
0251 }
0252
0253 template <typename T>
0254 std::vector<std::string> GenericParameters::getKeys() const {
0255 static_assert(podio::isSupportedGenericDataType<T>, "Unsupported parameter type");
0256 std::vector<std::string> keys;
0257 const auto& map = getMap<T>();
0258 keys.reserve(map.size());
0259 {
0260 auto& mtx = getMutex<T>();
0261 std::lock_guard lock{mtx};
0262 std::transform(map.begin(), map.end(), std::back_inserter(keys), [](const auto& pair) { return pair.first; });
0263 }
0264
0265 return keys;
0266 }
0267
0268 template <typename T>
0269 std::tuple<std::vector<std::string>, std::vector<std::vector<T>>> GenericParameters::getKeysAndValues() const {
0270 static_assert(podio::isSupportedGenericDataType<T>, "Unsupported parameter type");
0271 std::vector<std::vector<T>> values;
0272 std::vector<std::string> keys;
0273 auto& mtx = getMutex<T>();
0274 const auto& map = getMap<T>();
0275 {
0276
0277
0278 std::lock_guard lock{mtx};
0279 values.reserve(map.size());
0280 keys.reserve(map.size());
0281
0282 for (const auto& [k, v] : map) {
0283 keys.emplace_back(k);
0284 values.emplace_back(v);
0285 }
0286 }
0287 return {keys, values};
0288 }
0289
0290 template <typename T, template <typename...> typename VecLike>
0291 void GenericParameters::loadFrom(VecLike<std::string> keys, VecLike<std::vector<T>> values) {
0292 auto& map = getMap<T>();
0293 auto& mtx = getMutex<T>();
0294
0295 std::lock_guard lock{mtx};
0296 for (size_t i = 0; i < keys.size(); ++i) {
0297 map.emplace(std::move(keys[i]), std::move(values[i]));
0298 }
0299 }
0300
0301 }
0302 #endif