Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RDirectory.hxx
Go to the documentation of this file.
1/// \file ROOT/RDirectory.hxx
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
20#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/// Logging for generic IO functionality.
34
35/**
36 Objects of this class are thrown to signal that no key with that name exists.
37 */
38class RDirectoryUnknownKey: public std::exception {
39 std::string fKeyName;
40
41public:
42 RDirectoryUnknownKey(std::string_view keyName): fKeyName(keyName) {}
43 const char *what() const noexcept final { return fKeyName.c_str(); }
44};
45
46/**
47 Objects of this class are thrown to signal that the value known under the
48 given name .
49 */
50class RDirectoryTypeMismatch: public std::exception {
51 std::string fKeyName;
52 // FIXME: add expected and actual type names.
53public:
54 RDirectoryTypeMismatch(std::string_view keyName): fKeyName(keyName) {}
55 const char *what() const noexcept final { return fKeyName.c_str(); }
56};
57
58/**
59 Key/value store of objects.
60
61 Given a name, a `RDirectory` can store and retrieve an object. It will manage
62 shared ownership through a `shared_ptr`.
63
64 Example:
65 RDirectory dirMC;
66 RDirectory dirHiggs;
67
68 dirMC.Add("higgs", histHiggsMC);
69 dirHiggs.Add("mc", histHiggsMC);
70
71 */
72
74 // TODO: ContentMap_t should allow lookup by string_view while still providing
75 // storage of names.
76
77 /// The directory content is a hashed map of name => `Internal::RDirectoryEntry`.
78 using ContentMap_t = std::unordered_map<std::string, Internal::RDirectoryEntry>;
79
80 /// The `RDirectory`'s content.
82
83 template <class T>
85 using decaytype = typename std::decay<T>::type;
86 using type =
87 typename std::enable_if<!std::is_pointer<decaytype>::value && !std::is_member_pointer<decaytype>::value &&
88 !std::is_void<decaytype>::value,
90 };
91 template <class T>
93
94public:
95 /// Create an object of type `T` (passing some arguments to its constructor).
96 /// The `RDirectory` will have shared ownership of the object.
97 ///
98 /// \param name - Key of the object.
99 /// \param args - arguments to be passed to the constructor of `T`
100 template <class T, class... ARGS>
101 std::shared_ptr<ToContentType_t<T>> Create(std::string_view name, ARGS &&... args)
102 {
103 auto ptr = std::make_shared<ToContentType_t<T>>(std::forward<ARGS>(args)...);
104 Add(name, ptr);
105 return ptr;
106 }
107
108 /// Find the RDirectoryEntry associated to the name. Returns empty RDirectoryEntry if
109 /// nothing is found.
110 Internal::RDirectoryEntry Find(std::string_view name) const
111 {
112 auto idx = fContent.find(std::string(name));
113 if (idx == fContent.end())
114 return nullptr;
115 return idx->second;
116 }
117
118 /**
119 Status of the call to Find<T>(name).
120 */
121 enum class EFindStatus {
122 kValidValue, ///< Value known for this key name and type
123 kValidValueBase, ///< Value known for this key name and base type
124 kKeyNameNotFound, ///< No key is known for this name
125 kTypeMismatch ///< The provided type does not match the value's type.
126 };
127
128 /// Find the RDirectoryEntry associated with the name.
129 /// \returns empty RDirectoryEntry in `first` if nothing is found, or if the type does not
130 /// match the expected type. `second` contains the reason.
131 /// \note if `second` is kValidValue, then static_pointer_cast<`T`>(`first`.GetPointer())
132 /// is shared_ptr<`T`> to initially stored object
133 /// \note if `second` is kValidValueBase, then `first`.CastPointer<`T`>()
134 /// is a valid cast to base class `T` of the stored object
135 template <class T>
136 std::pair<Internal::RDirectoryEntry, EFindStatus> Find(std::string_view name) const
137 {
138 auto idx = fContent.find(std::string(name));
139 if (idx == fContent.end())
140 return {nullptr, EFindStatus::kKeyNameNotFound};
141 if (idx->second.GetTypeInfo() == typeid(ToContentType_t<T>))
142 return {idx->second, EFindStatus::kValidValue};
143 if (idx->second.CastPointer<ToContentType_t<T>>())
144 return {idx->second, EFindStatus::kValidValueBase};
145 return {nullptr, EFindStatus::kTypeMismatch};
146 }
147
148 /// Get the object for a key. `T` can be the object's type or a base class.
149 /// The `RDirectory` will return the same object for subsequent calls to
150 /// `Get().`
151 /// \returns a `shared_ptr` to the object or its base.
152 /// \throws RDirectoryUnknownKey if no object is stored under this name.
153 /// \throws RDirectoryTypeMismatch if the object stored under this name is of
154 /// a type that is not a derived type of `T`.
155 template <class T>
156 std::shared_ptr<ToContentType_t<T>> Get(std::string_view name)
157 {
158 const auto &pair = Find<T>(name);
159 const Internal::RDirectoryEntry &entry = pair.first;
160 EFindStatus status = pair.second;
161 switch (status) {
162 case EFindStatus::kValidValue: return std::static_pointer_cast<ToContentType_t<T>>(entry.GetPointer());
165 // FIXME: add expected versus actual type name as c'tor args
168 }
169 return nullptr; // never happens
170 }
171
172 /// Add an existing object (rather a `shared_ptr` to it) to the RDirectory.
173 /// The RDirectory will have shared ownership.
174 template <class T>
175 void Add(std::string_view name, const std::shared_ptr<T> &ptr)
176 {
177 Internal::RDirectoryEntry entry(ptr);
178 // FIXME: CXX17: insert_or_assign
179 std::string sName(name);
180 auto idx = fContent.find(sName);
181 if (idx != fContent.end()) {
182 R__LOG_WARNING(IOLog()) << "Replacing object with name \"" << name << "\"" << std::endl;
183 idx->second.swap(entry);
184 } else {
185 fContent[sName].swap(entry);
186 }
187 }
188
189 /// Remove entry from RDirectory (if exists)
190 bool Remove(std::string_view name)
191 {
192 std::string sName(name);
193 auto idx = fContent.find(sName);
194 if (idx != fContent.end()) {
195 fContent.erase(idx);
196 return true;
197 }
198 return false;
199 }
200
201
202 /// Dedicated, process-wide RDirectory.
203 ///
204 /// \note This is *not* thread-safe. You will need to syncronize yourself. In
205 /// general it's a bad idea to use a global collection in a multi-threaded
206 /// environment; ROOT itself does not make use of it. It is merely offered for
207 /// historical, process-wide object registration by name. Instead, pass a
208 /// pointer to the object where you need to access it - this is also much
209 /// faster than a lookup by name.
210 static RDirectory &Heap();
211};
212
213} // namespace Experimental
214} // namespace ROOT
215
216#endif
#define R__LOG_WARNING(...)
Definition RLogger.hxx:363
char name[80]
Definition TGX11.cxx:110
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 .
const char * what() const noexcept final
RDirectoryTypeMismatch(std::string_view keyName)
Objects of this class are thrown to signal that no key with that name exists.
const char * what() const noexcept final
RDirectoryUnknownKey(std::string_view keyName)
Key/value store of objects.
typename ToContentType< T >::type ToContentType_t
bool Remove(std::string_view name)
Remove entry from RDirectory (if exists)
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.
std::shared_ptr< ToContentType_t< T > > Get(std::string_view name)
Get the object for a key.
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.
std::unordered_map< std::string, Internal::RDirectoryEntry > ContentMap_t
The directory content is a hashed map of name => Internal::RDirectoryEntry.
EFindStatus
Status of the call to Find<T>(name).
@ 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.
std::pair< Internal::RDirectoryEntry, EFindStatus > Find(std::string_view name) const
Find the RDirectoryEntry associated with the name.
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).
A log configuration for a channel, e.g.
Definition RLogger.hxx:101
RLogChannel & IOLog()
Logging for generic IO functionality.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
typename std::decay< T >::type decaytype
typename std::enable_if<!std::is_pointer< decaytype >::value &&!std::is_member_pointer< decaytype >::value &&!std::is_void< decaytype >::value, decaytype >::type type
#define ARGS(alist)
Definition gifencode.c:10