Registrar.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu)
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <mutex>
27 #include <stdexcept>
28 #include <unordered_map>
29 #include <vector>
30 
31 namespace armarx
32 {
33  /**
34  * @brief Stores key object pairs.
35  * The third template parameter offers the option to tag this registrar with a class.
36  *
37  * If polymorphic objects are required use a base class and unique pointers.
38  * E.g.:
39  * \code{.cpp}
40  * class Base{};
41  * class DerivedA{};
42  * class DerivedB{};
43  * Registrar<std::unique_ptr<Base>>::registerElement("A", DerivedA{});
44  * Registrar<std::unique_ptr<Base>>::registerElement("B", DerivedB{});
45  * \endcode
46  *
47  * If functions are stored use std::function (or function pointers).
48  *
49  * To register elements on file inclusion use this code in the header (note the missing static).
50  * \code{.cpp}
51  * Registrar<Type>::RegisterElement register("A", object);
52  * \endcode
53  * Example for strings
54  * \code{.cpp}
55  * Registrar<std::string>::RegisterElement register1("key 1", "value 1");
56  * Registrar<std::string>::RegisterElement register2("key 2", "value 2");
57  * \endcode
58  *
59  * \ingroup core-utility
60  */
61  template <class RegisteredType, class KeyType = std::string, class = void>
62  class Registrar
63  {
64  public:
65  using ContainerType = std::unordered_map<KeyType, RegisteredType>;
66 
67  /**
68  * @brief Registers the object passed to the constructor.
69  * This can be used in combination with global variables to register types when a header is included.
70  */
72  {
73  RegisterElement(const KeyType& key, RegisteredType element)
74  {
75  registerElement(key, std::move(element));
76  }
77  };
78 
79  /**
80  * @brief Returns the registered object for the given key.
81  * @param key The object's key.
82  * @return The registered object for the given key.
83  */
84  static const RegisteredType&
85  get(const KeyType& key)
86  {
87  std::lock_guard<std::recursive_mutex> guard{registeredElementsMutex()};
88  if (!has(key))
89  {
90  throw std::invalid_argument{"No factory for this key! "};
91  }
92  return registeredElements().at(key);
93  }
94 
95  static bool
96  has(const KeyType& key)
97  {
98  std::lock_guard<std::recursive_mutex> guard{registeredElementsMutex()};
99  return registeredElements().end() != registeredElements().find(key);
100  }
101 
102  /**
103  * @brief Registers an element.
104  * @param key The element's key.
105  * @param element The element.
106  */
107  static void
108  registerElement(const KeyType& key, RegisteredType element)
109  {
110  std::lock_guard<std::recursive_mutex> guard{registeredElementsMutex()};
111  registeredElements()[key] = std::move(element);
112  }
113 
114  /**
115  * @brief Retrieves the list of all registered elements.
116  * @return The list of all registered elements.
117  */
118  static std::vector<KeyType>
120  {
121  std::lock_guard<std::recursive_mutex> guard{registeredElementsMutex()};
122  std::vector<KeyType> result;
123  result.reserve(registeredElements().size());
124  for (const auto& elem : registeredElements())
125  {
126  result.emplace_back(elem.first);
127  }
128  return result;
129  }
130 
131  private:
132  /**
133  * @brief Holds the map of registered elements.
134  * @return The map of registered elements.
135  */
136  static ContainerType&
137  registeredElements()
138  {
139  static ContainerType elementContainer;
140  return elementContainer;
141  }
142 
143  static std::recursive_mutex&
144  registeredElementsMutex()
145  {
146  static std::recursive_mutex elementContainerMutex;
147  return elementContainerMutex;
148  }
149  };
150 } // namespace armarx
armarx::Registrar::get
static const RegisteredType & get(const KeyType &key)
Returns the registered object for the given key.
Definition: Registrar.h:85
armarx::Registrar::has
static bool has(const KeyType &key)
Definition: Registrar.h:96
armarx::Registrar::registerElement
static void registerElement(const KeyType &key, RegisteredType element)
Registers an element.
Definition: Registrar.h:108
armarx::Registrar::ContainerType
std::unordered_map< KeyType, RegisteredType > ContainerType
Definition: Registrar.h:65
armarx::Registrar::RegisterElement::RegisterElement
RegisterElement(const KeyType &key, RegisteredType element)
Definition: Registrar.h:73
armarx::Registrar::getKeys
static std::vector< KeyType > getKeys()
Retrieves the list of all registered elements.
Definition: Registrar.h:119
armarx::Registrar::RegisterElement
Registers the object passed to the constructor.
Definition: Registrar.h:71
armarx::Registrar
Stores key object pairs.
Definition: Registrar.h:62
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27