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 <unordered_map>
27 #include <vector>
28 #include <mutex>
29 #include <stdexcept>
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& get(const KeyType& key)
85  {
86  std::lock_guard<std::recursive_mutex> guard {registeredElementsMutex()};
87  if (!has(key))
88  {
89  throw std::invalid_argument {"No factory for this key! "};
90  }
91  return registeredElements().at(key);
92  }
93 
94  static bool has(const KeyType& key)
95  {
96  std::lock_guard<std::recursive_mutex> guard {registeredElementsMutex()};
97  return registeredElements().end() != registeredElements().find(key);
98  }
99 
100  /**
101  * @brief Registers an element.
102  * @param key The element's key.
103  * @param element The element.
104  */
105  static void registerElement(const KeyType& key, RegisteredType element)
106  {
107  std::lock_guard<std::recursive_mutex> guard {registeredElementsMutex()};
108  registeredElements()[key] = std::move(element);
109  }
110 
111  /**
112  * @brief Retrieves the list of all registered elements.
113  * @return The list of all registered elements.
114  */
115  static std::vector<KeyType> getKeys()
116  {
117  std::lock_guard<std::recursive_mutex> guard {registeredElementsMutex()};
118  std::vector<KeyType> result;
119  result.reserve(registeredElements().size());
120  for (const auto& elem : registeredElements())
121  {
122  result.emplace_back(elem.first);
123  }
124  return result;
125  }
126  private:
127  /**
128  * @brief Holds the map of registered elements.
129  * @return The map of registered elements.
130  */
131  static ContainerType& registeredElements()
132  {
133  static ContainerType elementContainer;
134  return elementContainer;
135  }
136  static std::recursive_mutex& registeredElementsMutex()
137  {
138  static std::recursive_mutex elementContainerMutex;
139  return elementContainerMutex;
140  }
141  };
142 }
armarx::Registrar::get
static const RegisteredType & get(const KeyType &key)
Returns the registered object for the given key.
Definition: Registrar.h:84
armarx::Registrar::has
static bool has(const KeyType &key)
Definition: Registrar.h:94
armarx::Registrar::registerElement
static void registerElement(const KeyType &key, RegisteredType element)
Registers an element.
Definition: Registrar.h:105
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:115
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:28