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