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