File indexing completed on 2025-12-16 09:27:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <edm4hep/EventHeaderCollection.h>
0012 #include <edm4hep/EDM4hepVersion.h>
0013 #include <algorithms/logger.h>
0014 #include <algorithms/service.h>
0015 #include <bitset>
0016 #include <map>
0017 #include <memory>
0018 #include <string>
0019 #include <unordered_map>
0020
0021 namespace algorithms {
0022
0023 class UniqueIDGenSvc : public LoggedService<UniqueIDGenSvc> {
0024 public:
0025 using event_num_t = decltype(std::declval<edm4hep::EventHeader>().getEventNumber());
0026 using run_num_t = decltype(std::declval<edm4hep::EventHeader>().getRunNumber());
0027
0028 using seed_t = uint64_t;
0029
0030 private:
0031 static constexpr size_t event_num_digits = std::numeric_limits<event_num_t>::digits;
0032 static constexpr size_t run_num_digits = std::numeric_limits<run_num_t>::digits;
0033 static constexpr size_t seed_digits = std::numeric_limits<seed_t>::digits;
0034 static constexpr size_t name_digits = std::numeric_limits<size_t>::digits;
0035
0036 public:
0037 virtual void init() {}
0038
0039
0040 size_t getUniqueID(const edm4hep::EventHeader& evt_header, const std::string_view& name) const {
0041 return getUniqueID(evt_header.getEventNumber(), evt_header.getRunNumber(), name);
0042 }
0043
0044 size_t getUniqueID(const edm4hep::EventHeaderCollection& evt_headers,
0045 const std::string_view& name) const {
0046 return getUniqueID(evt_headers.at(0), name);
0047 }
0048
0049 size_t getUniqueID(const event_num_t evt_num, const run_num_t run_num,
0050 const std::string_view& name) const {
0051 std::bitset<seed_digits> seed_bits = m_seed.value();
0052 std::bitset<event_num_digits> event_num_bits = evt_num;
0053 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 2)
0054 std::bitset<run_num_digits> run_num_bits = run_num;
0055 #else
0056
0057 std::bitset<run_num_digits> run_num_bits = static_cast<std::uint32_t>(run_num);
0058 #endif
0059 std::bitset<name_digits> name_bits = std::hash<std::string_view>{}(name);
0060
0061 std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits> combined_bits;
0062
0063 for (size_t i = 0; i < name_digits; i++) {
0064 combined_bits[i] = name_bits[i];
0065 }
0066 for (size_t i = 0; i < run_num_digits; i++) {
0067 combined_bits[i + name_digits] = run_num_bits[i];
0068 }
0069 for (size_t i = 0; i < event_num_digits; i++) {
0070 combined_bits[i + run_num_digits + name_digits] = event_num_bits[i];
0071 }
0072 for (size_t i = 0; i < seed_digits; i++) {
0073 combined_bits[i + event_num_digits + run_num_digits + name_digits] = seed_bits[i];
0074 }
0075
0076 auto hash =
0077 std::hash<std::bitset<seed_digits + event_num_digits + run_num_digits + name_digits>>{}(
0078 combined_bits);
0079
0080 if (m_checkDuplicates) {
0081 auto [it, inserted] = [=, this, &name]() {
0082 std::lock_guard<std::mutex> lock(m_mutex);
0083 return m_uniqueIDs.insert({hash, {evt_num, run_num, std::string{name}}});
0084 }();
0085 if (!inserted) {
0086 const auto& [id_evt, id_run, id_name] = it->second;
0087
0088 throw std::runtime_error(fmt::format(
0089 "Duplicate ID for event number, run number and algorithm name: {}, {}, \"{}\". "
0090 "ID already assigned to: {}, {}, \"{}\"",
0091 evt_num, run_num, name, id_evt, id_run, id_name));
0092 }
0093 }
0094
0095 return hash;
0096 };
0097
0098 protected:
0099 ALGORITHMS_DEFINE_LOGGED_SERVICE(UniqueIDGenSvc)
0100
0101 private:
0102 Property<size_t> m_seed{this, "seed", 1, "Random seed for the internal random engine"};
0103 Property<bool> m_checkDuplicates{
0104 this, "checkDuplicates", false,
0105 "Caches obtained ID and throws an exception if a duplicate would be returned"};
0106
0107 mutable std::unordered_map<size_t, std::tuple<event_num_t, run_num_t, std::string>, std::identity>
0108 m_uniqueIDs;
0109 mutable std::mutex m_mutex;
0110 };
0111
0112 }