LCOV - code coverage report
Current view: top level - include/utils - GeneralRegistry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 36 36 100.0 %
Date: 2025-07-17 01:28:37 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include <unordered_map>
      13             : #include <mutex>
      14             : #include <deque>
      15             : 
      16             : #include "MooseError.h"
      17             : 
      18             : template <class Key, class Item, class KeyHash = std::hash<Key>>
      19             : class GeneralRegistry
      20             : {
      21             : public:
      22             :   GeneralRegistry(const std::string & name);
      23             : 
      24             :   /**
      25             :    * @returns The number of registered items
      26             :    */
      27             :   std::size_t size() const;
      28             : 
      29             :   /**
      30             :    * @returns The ID assocated with the key \p key
      31             :    */
      32             :   std::size_t id(const Key & key) const;
      33             : 
      34             :   /**
      35             :    * @returns Whether or not the key \p key is registered
      36             :    */
      37             :   bool keyExists(const Key & key) const;
      38             :   /**
      39             :    * @returns Whether or not the id \p id is registered
      40             :    */
      41             :   bool idExists(const std::size_t id) const;
      42             : 
      43             :   /**
      44             :    * @returns The item associated with the key \p key (thread safe)
      45             :    */
      46             :   const Item & item(const std::size_t id) const;
      47             : 
      48             : protected:
      49             :   /**
      50             :    * @returns The item associated with the key \p key (not thread safe)
      51             :    */
      52             :   const Item & itemNonLocking(const std::size_t id) const;
      53             : 
      54             :   /**
      55             :    * Registers an item with key \p key if said key does not exist.
      56             :    *
      57             :    * @param key The key
      58             :    * @param create_item Lambda called to create an item if the key
      59             :    * does not exist. Takes a single argument std::size_t which is the
      60             :    # new ID and should return an Item
      61             :    * @returns The ID of the item
      62             :    */
      63             :   template <typename CreateItem>
      64             :   std::size_t registerItem(const Key & key, CreateItem & create_item);
      65             : 
      66             :   /// The name of this registry; used in error handling
      67             :   const std::string _name;
      68             : 
      69             :   /// Map of keys to IDs
      70             :   std::unordered_map<Key, std::size_t, KeyHash> _key_to_id;
      71             :   /// Vector of IDs to Items
      72             :   std::deque<Item> _id_to_item;
      73             : 
      74             :   /// Mutex for locking access to _key_to_id
      75             :   /// NOTE: These can be changed to shared_mutexes once we get C++17
      76             :   mutable std::mutex _key_to_id_mutex;
      77             :   /// Mutex for locking access to _id_to_item
      78             :   /// NOTE: These can be changed to shared_mutexes once we get C++17
      79             :   mutable std::mutex _id_to_item_mutex;
      80             : };
      81             : 
      82             : template <class Key, class Item, class KeyHash>
      83      102346 : GeneralRegistry<Key, Item, KeyHash>::GeneralRegistry(const std::string & name) : _name(name)
      84             : {
      85      102346 : }
      86             : 
      87             : template <class Key, class Item, class KeyHash>
      88             : std::size_t
      89      103063 : GeneralRegistry<Key, Item, KeyHash>::size() const
      90             : {
      91      103063 :   std::lock_guard<std::mutex> lock(_id_to_item_mutex);
      92      206126 :   return _id_to_item.size();
      93      103063 : }
      94             : 
      95             : template <class Key, class Item, class KeyHash>
      96             : std::size_t
      97    99917297 : GeneralRegistry<Key, Item, KeyHash>::id(const Key & key) const
      98             : {
      99    99917297 :   std::lock_guard<std::mutex> lock(_key_to_id_mutex);
     100    99917297 :   const auto it = _key_to_id.find(key);
     101    99917297 :   if (it == _key_to_id.end())
     102           4 :     mooseError(_name, ": Key '", key, "' is not registered");
     103   199834586 :   return it->second;
     104    99917293 : }
     105             : 
     106             : template <class Key, class Item, class KeyHash>
     107             : bool
     108    91086433 : GeneralRegistry<Key, Item, KeyHash>::keyExists(const Key & key) const
     109             : {
     110    91086433 :   std::lock_guard<std::mutex> lock(_key_to_id_mutex);
     111   182172866 :   return _key_to_id.count(key);
     112    91086433 : }
     113             : 
     114             : template <class Key, class Item, class KeyHash>
     115             : bool
     116             : GeneralRegistry<Key, Item, KeyHash>::idExists(const std::size_t id) const
     117             : {
     118             :   std::lock_guard<std::mutex> lock(_id_to_item_mutex);
     119             :   return id < _id_to_item.size();
     120             : }
     121             : 
     122             : template <class Key, class Item, class KeyHash>
     123             : const Item &
     124     6235193 : GeneralRegistry<Key, Item, KeyHash>::item(const std::size_t id) const
     125             : {
     126     6235193 :   std::lock_guard<std::mutex> lock(_id_to_item_mutex);
     127    12470382 :   return itemNonLocking(id);
     128     6235189 : }
     129             : 
     130             : template <class Key, class Item, class KeyHash>
     131             : const Item &
     132   165033845 : GeneralRegistry<Key, Item, KeyHash>::itemNonLocking(const std::size_t id) const
     133             : {
     134   165033845 :   if (id >= _id_to_item.size())
     135           4 :     mooseError(_name, ": ID '", id, "' is not registered");
     136   165033841 :   return _id_to_item[id];
     137             : }
     138             : 
     139             : template <class Key, class Item, class KeyHash>
     140             : template <typename CreateItem>
     141             : std::size_t
     142     8529780 : GeneralRegistry<Key, Item, KeyHash>::registerItem(const Key & key, CreateItem & create_item)
     143             : {
     144     8529780 :   std::lock_guard<std::mutex> lock_key(_key_to_id_mutex);
     145             : 
     146             :   // Is it already registered?
     147     8529780 :   const auto it = _key_to_id.find(key);
     148     8529780 :   if (it != _key_to_id.end())
     149     1904933 :     return it->second;
     150             : 
     151             :   // It's not registered
     152     6624847 :   std::lock_guard<std::mutex> lock_id(_id_to_item_mutex);
     153     6624847 :   const auto id = _id_to_item.size();
     154     6624847 :   _key_to_id.emplace(key, id);
     155     6624847 :   _id_to_item.emplace_back(std::move(create_item(id)));
     156     6624847 :   return id;
     157     8529780 : }

Generated by: LCOV version 1.14