Logo ROOT   6.18/05
Reference Guide
RDirectory.hxx
Go to the documentation of this file.
1/// \file ROOT/RDirectory.h
2/// \ingroup Base ROOT7
3/// \author Axel Naumann <axel@cern.ch>
4/// \date 2015-07-31
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RDirectory
17#define ROOT7_RDirectory
18
19#include "ROOT/RLogger.hxx"
21
22#include <iterator>
23#include <memory>
24#include <type_traits>
25#include <unordered_map>
26#include <string>
27#include <ROOT/RStringView.hxx>
28
29namespace ROOT {
30namespace Experimental {
31
32/**
33 Objects of this class are thrown to signal that no key with that name exists.
34 */
35class RDirectoryUnknownKey: public std::exception {
36 std::string fKeyName;
37
38public:
40 const char *what() const noexcept final { return fKeyName.c_str(); }
41};
42
43/**
44 Objects of this class are thrown to signal that the value known under the
45 given name .
46 */
47class RDirectoryTypeMismatch: public std::exception {
48 std::string fKeyName;
49 // FIXME: add expected and actual type names.
50public:
52 const char *what() const noexcept final { return fKeyName.c_str(); }
53};
54
55/**
56 Key/value store of objects.
57
58 Given a name, a `RDirectory` can store and retrieve an object. It will manage
59 shared ownership through a `shared_ptr`.
60
61 Example:
62 RDirectory dirMC;
63 RDirectory dirHiggs;
64
65 dirMC.Add("higgs", histHiggsMC);
66 dirHiggs.Add("mc", histHiggsMC);
67
68 */
69
71 // TODO: ContentMap_t should allow lookup by string_view while still providing
72 // storage of names.
73
74 /// The directory content is a hashed map of name => `Internal::RDirectoryEntry`.
75 using ContentMap_t = std::unordered_map<std::string, Internal::RDirectoryEntry>;
76
77 /// The `RDirectory`'s content.
79
80 template <class T>
83 using type =
84 typename std::enable_if<!std::is_pointer<decaytype>::value && !std::is_member_pointer<decaytype>::value &&
85 !std::is_void<decaytype>::value,
87 };
88 template <class T>
90
91public:
92 /// Create an object of type `T` (passing some arguments to its constructor).
93 /// The `RDirectory` will have shared ownership of the object.
94 ///
95 /// \param name - Key of the object.
96 /// \param args - arguments to be passed to the constructor of `T`
97 template <class T, class... ARGS>
98 std::shared_ptr<ToContentType_t<T>> Create(std::string_view name, ARGS &&... args)
99 {
100 auto ptr = std::make_shared<ToContentType_t<T>>(std::forward<ARGS>(args)...);
101 Add(name, ptr);
102 return ptr;
103 }
104
105 /// Find the RDirectoryEntry associated to the name. Returns empty RDirectoryEntry if
106 /// nothing is found.
108 {
109 auto idx = fContent.find(std::string(name));
110 if (idx == fContent.end())
111 return nullptr;
112 return idx->second;
113 }
114
115 /**
116 Status of the call to Find<T>(name).
117 */
118 enum class EFindStatus {
119 kValidValue, ///< Value known for this key name and type
120 kValidValueBase, ///< Value known for this key name and base type
121 kKeyNameNotFound, ///< No key is known for this name
122 kTypeMismatch ///< The provided type does not match the value's type.
123 };
124
125 /// Find the RDirectoryEntry associated with the name.
126 /// \returns empty RDirectoryEntry in `first` if nothing is found, or if the type does not
127 /// match the expected type. `second` contains the reason.
128 /// \note if `second` is kValidValue, then static_pointer_cast<`T`>(`first`.GetPointer())
129 /// is shared_ptr<`T`> to initially stored object
130 /// \note if `second` is kValidValueBase, then `first`.CastPointer<`T`>()
131 /// is a valid cast to base class `T` of the stored object
132 template <class T>
133 std::pair<Internal::RDirectoryEntry, EFindStatus> Find(std::string_view name) const
134 {
135 auto idx = fContent.find(std::string(name));
136 if (idx == fContent.end())
137 return {nullptr, EFindStatus::kKeyNameNotFound};
138 if (idx->second.GetTypeInfo() == typeid(ToContentType_t<T>))
139 return {idx->second, EFindStatus::kValidValue};
140 if (idx->second.CastPointer<ToContentType_t<T>>())
141 return {idx->second, EFindStatus::kValidValueBase};
142 return {nullptr, EFindStatus::kTypeMismatch};
143 }
144
145 /// Get the object for a key. `T` can be the object's type or a base class.
146 /// The `RDirectory` will return the same object for subsequent calls to
147 /// `Get().`
148 /// \returns a `shared_ptr` to the object or its base.
149 /// \throws RDirectoryUnknownKey if no object is stored under this name.
150 /// \throws RDirectoryTypeMismatch if the object stored under this name is of
151 /// a type that is not a derived type of `T`.
152 template <class T>
153 std::shared_ptr<ToContentType_t<T>> Get(std::string_view name)
154 {
155 const auto &pair = Find<T>(name);
156 const Internal::RDirectoryEntry &entry = pair.first;
157 EFindStatus status = pair.second;
158 switch (status) {
159 case EFindStatus::kValidValue: return std::static_pointer_cast<ToContentType_t<T>>(entry.GetPointer());
162 // FIXME: add expected versus actual type name as c'tor args
165 }
166 return nullptr; // never happens
167 }
168
169 /// Add an existing object (rather a `shared_ptr` to it) to the RDirectory.
170 /// The RDirectory will have shared ownership.
171 template <class T>
172 void Add(std::string_view name, const std::shared_ptr<T> &ptr)
173 {
174 Internal::RDirectoryEntry entry(ptr);
175 // FIXME: CXX17: insert_or_assign
176 std::string sName(name);
177 auto idx = fContent.find(sName);
178 if (idx != fContent.end()) {
179 R__LOG_HERE(ELogLevel::kWarning, "CORE") << "Replacing object with name \"" << name << "\"" << std::endl;
180 idx->second.swap(entry);
181 } else {
182 fContent[sName].swap(entry);
183 }
184 }
185
186 /// Dedicated, process-wide RDirectory.
187 ///
188 /// \note This is *not* thread-safe. You will need to syncronize yourself. In
189 /// general it's a bad idea to use a global collection in a multi-threaded
190 /// environment; ROOT itself does not make use of it. It is merely offered for
191 /// historical, process-wide object registration by name. Instead, pass a
192 /// pointer to the object where you need to access it - this is also much
193 /// faster than a lookup by name.
194 static RDirectory &Heap();
195};
196
197} // namespace Experimental
198} // namespace ROOT
199
200#endif
#define R__LOG_HERE(LEVEL, GROUP)
Definition: RLogger.hxx:179
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
std::shared_ptr< void > & GetPointer()
Retrieve the shared_ptr of the referenced object.
Objects of this class are thrown to signal that the value known under the given name .
Definition: RDirectory.hxx:47
const char * what() const noexcept final
Definition: RDirectory.hxx:52
RDirectoryTypeMismatch(std::string_view keyName)
Definition: RDirectory.hxx:51
Objects of this class are thrown to signal that no key with that name exists.
Definition: RDirectory.hxx:35
const char * what() const noexcept final
Definition: RDirectory.hxx:40
RDirectoryUnknownKey(std::string_view keyName)
Definition: RDirectory.hxx:39
Key/value store of objects.
Definition: RDirectory.hxx:70
typename ToContentType< T >::type ToContentType_t
Definition: RDirectory.hxx:89
static RDirectory & Heap()
Dedicated, process-wide RDirectory.
Definition: RFile.cxx:23
Internal::RDirectoryEntry Find(std::string_view name) const
Find the RDirectoryEntry associated to the name.
Definition: RDirectory.hxx:107
std::shared_ptr< ToContentType_t< T > > Get(std::string_view name)
Get the object for a key.
Definition: RDirectory.hxx:153
void Add(std::string_view name, const std::shared_ptr< T > &ptr)
Add an existing object (rather a shared_ptr to it) to the RDirectory.
Definition: RDirectory.hxx:172
std::unordered_map< std::string, Internal::RDirectoryEntry > ContentMap_t
The directory content is a hashed map of name => Internal::RDirectoryEntry.
Definition: RDirectory.hxx:75
EFindStatus
Status of the call to Find<T>(name).
Definition: RDirectory.hxx:118
@ kValidValue
Value known for this key name and type.
@ kValidValueBase
Value known for this key name and base type.
@ kTypeMismatch
The provided type does not match the value's type.
@ kKeyNameNotFound
No key is known for this name.
ContentMap_t fContent
The RDirectory's content.
Definition: RDirectory.hxx:78
std::pair< Internal::RDirectoryEntry, EFindStatus > Find(std::string_view name) const
Find the RDirectoryEntry associated with the name.
Definition: RDirectory.hxx:133
std::shared_ptr< ToContentType_t< T > > Create(std::string_view name, ARGS &&... args)
Create an object of type T (passing some arguments to its constructor).
Definition: RDirectory.hxx:98
basic_string_view< char > string_view
@ kWarning
Warnings about likely unexpected behavior.
double T(double x)
Definition: ChebyshevPol.h:34
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
typename std::decay< T >::type decaytype
Definition: RDirectory.hxx:82
typename std::enable_if<!std::is_pointer< decaytype >::value &&!std::is_member_pointer< decaytype >::value &&!std::is_void< decaytype >::value, decaytype >::type type
Definition: RDirectory.hxx:86
#define ARGS(alist)
Definition: gifencode.c:10