Caffe2 - C++ API
A deep learning, cross platform ML framework
typeid.h
1 #ifndef CAFFE2_CORE_TYPEID_H_
2 #define CAFFE2_CORE_TYPEID_H_
3 
4 #include <cassert>
5 #include <cstdlib>
6 
7 #include <iostream>
8 #include <map>
9 #include <type_traits>
10 #ifdef __GXX_RTTI
11 #include <set>
12 #include <typeinfo>
13 #endif
14 
15 #include <exception>
16 
17 #include "caffe2/core/common.h"
18 
19 namespace caffe2 {
20 
21 typedef intptr_t CaffeTypeId;
22 std::map<CaffeTypeId, string>& gTypeNames();
23 #ifdef __GXX_RTTI
24 std::set<string>& gRegisteredTypeNames();
25 #endif // __GXX_RTTI
26 
27 // A utility function to demangle a function name.
28 string Demangle(const char* name);
29 
30 // A utility function to return an exception string by prepending its exception
31 // type before its what() content.
32 string GetExceptionString(const std::exception& e);
33 
34 template <typename T>
36  explicit TypeNameRegisterer(CaffeTypeId id) {
37 #ifdef __GXX_RTTI
38  string name = Demangle(typeid(T).name());
39  gTypeNames()[id] = name;
40  // If we are in RTTI mode, we will also use this opportunity to do sanity
41  // check if there are duplicated ids registered for the same type. This
42  // usually happens when one does not do RTLD_GLOBAL, which is often the
43  // case in Python. The way we do the check is to make sure that there are
44  // no duplicated names registered - this could be done by checking the
45  // uniqueness of names.
46  if (gRegisteredTypeNames().count(name)) {
47  std::cerr << "Type name " << name
48  << " registered twice. This should "
49  "not happen. Do you have duplicated CAFFE_KNOWN_TYPE?"
50  << std::endl;
51  throw std::runtime_error("TypeNameRegisterer error with type " + name);
52  }
53  gRegisteredTypeNames().insert(name);
54 #else // __GXX_RTTI
55  gTypeNames()[id] = "(RTTI disabled, cannot show name)";
56 #endif // __GXX_RTTI
57  }
58 };
59 
66 class TypeMeta {
67  public:
68  typedef void (*PlacementNew)(void*, size_t);
69  typedef void (*TypedCopy)(const void*, void*, size_t);
70  typedef void (*TypedDestructor)(void*, size_t);
75  : id_(0), itemsize_(0), ctor_(nullptr), copy_(nullptr), dtor_(nullptr) {}
76 
80  TypeMeta(const TypeMeta& src)
81  : id_(src.id_),
82  itemsize_(src.itemsize_),
83  ctor_(src.ctor_),
84  copy_(src.copy_),
85  dtor_(src.dtor_) {}
89  TypeMeta& operator=(const TypeMeta& src) {
90  if (this == &src)
91  return *this;
92  id_ = src.id_;
93  itemsize_ = src.itemsize_;
94  ctor_ = src.ctor_;
95  copy_ = src.copy_;
96  dtor_ = src.dtor_;
97  return *this;
98  }
99 
100  private:
101  // TypeMeta can only be created by Make, making sure that we do not
102  // create incorrectly mixed up TypeMeta objects.
103  TypeMeta(
104  CaffeTypeId i,
105  size_t s,
106  PlacementNew ctor,
107  TypedCopy copy,
108  TypedDestructor dtor)
109  : id_(i), itemsize_(s), ctor_(ctor), copy_(copy), dtor_(dtor) {}
110 
111  public:
115  inline const CaffeTypeId& id() const {
116  return id_;
117  }
121  inline const size_t& itemsize() const {
122  return itemsize_;
123  }
127  inline PlacementNew ctor() const {
128  return ctor_;
129  }
133  inline TypedCopy copy() const {
134  return copy_;
135  }
139  inline TypedDestructor dtor() const {
140  return dtor_;
141  }
145  inline const char* name() const {
146  auto it = gTypeNames().find(id_);
147  assert(it != gTypeNames().end());
148  return it->second.c_str();
149  }
150  inline bool operator==(const TypeMeta& m) const {
151  return (id_ == m.id_);
152  }
153  inline bool operator!=(const TypeMeta& m) const {
154  return (id_ != m.id_);
155  }
156 
157  template <typename T>
158  inline bool Match() const {
159  return (id_ == Id<T>());
160  }
161 
162  // Below are static functions that can be called by passing a specific type.
163 
171  template <typename T>
172  CAFFE2_EXPORT static CaffeTypeId Id();
173 
177  template <typename T>
178  static size_t ItemSize() {
179  return sizeof(T);
180  }
181 
187  template <typename T>
188  static const char* Name() {
189 #ifdef __GXX_RTTI
190  static const string name = Demangle(typeid(T).name());
191  return name.c_str();
192 #else // __GXX_RTTI
193  return "(RTTI disabled, cannot show name)";
194 #endif // __GXX_RTTI
195  }
196 
200  template <typename T>
201  static void _Ctor(void* ptr, size_t n) {
202  T* typed_ptr = static_cast<T*>(ptr);
203  for (int i = 0; i < n; ++i) {
204  new (typed_ptr + i) T;
205  }
206  }
207 
211  template <typename T>
212  static void _Copy(const void* src, void* dst, size_t n) {
213  const T* typed_src = static_cast<const T*>(src);
214  T* typed_dst = static_cast<T*>(dst);
215  for (int i = 0; i < n; ++i) {
216  typed_dst[i] = typed_src[i];
217  }
218  }
219 
223  template <typename T>
224  static void _CopyNotAllowed(const void* src, void* dst, size_t n) {
225  std::cerr << "Type " << Name<T>() << " does not allow assignment.";
226  // This is an error by design, so we will quit loud.
227  abort();
228  }
229 
233  template <typename T>
234  static void _Dtor(void* ptr, size_t n) {
235  T* typed_ptr = static_cast<T*>(ptr);
236  for (int i = 0; i < n; ++i) {
237  typed_ptr[i].~T();
238  }
239  }
240 
244  template <typename T>
245  static typename std::enable_if<std::is_fundamental<T>::value, TypeMeta>::type
246  Make() {
247  return TypeMeta(Id<T>(), ItemSize<T>(), nullptr, nullptr, nullptr);
248  }
249 
250  template <
251  typename T,
252  typename std::enable_if<
253  !std::is_fundamental<T>::value &&
254  std::is_copy_assignable<T>::value>::type* = nullptr>
255  static TypeMeta Make() {
256  return TypeMeta(Id<T>(), ItemSize<T>(), _Ctor<T>, _Copy<T>, _Dtor<T>);
257  }
258 
259  template <typename T>
260  static TypeMeta Make(
261  typename std::enable_if<
262  !std::is_fundamental<T>::value &&
263  !std::is_copy_assignable<T>::value>::type* = 0) {
264  return TypeMeta(
265  Id<T>(), ItemSize<T>(), _Ctor<T>, _CopyNotAllowed<T>, _Dtor<T>);
266  }
267 
268  private:
269  CaffeTypeId id_;
270  size_t itemsize_;
271  PlacementNew ctor_;
272  TypedCopy copy_;
273  TypedDestructor dtor_;
274 };
275 
289 #define CAFFE_KNOWN_TYPE(T) \
290  template <> \
291  CaffeTypeId TypeMeta::Id<T>() { \
292  static bool type_id_bit[1]; \
293  static TypeNameRegisterer<T> registerer( \
294  reinterpret_cast<CaffeTypeId>(type_id_bit)); \
295  return reinterpret_cast<CaffeTypeId>(type_id_bit); \
296  }
297 
298 } // namespace caffe2
299 
300 #endif // CAFFE2_CORE_TYPEID_H_
TypedCopy copy() const
Returns the typed copy function pointer for individual iterms.
Definition: typeid.h:133
static void _Copy(const void *src, void *dst, size_t n)
Typed copy function for classes.
Definition: typeid.h:212
static std::enable_if< std::is_fundamental< T >::value, TypeMeta >::type Make()
Returns a TypeMeta object that corresponds to the typename T.
Definition: typeid.h:246
static size_t ItemSize()
Returns the item size of the type.
Definition: typeid.h:178
const CaffeTypeId & id() const
Returns the type id.
Definition: typeid.h:115
TypeMeta()
Create a dummy TypeMeta object.
Definition: typeid.h:74
TypeMeta is a thin class that allows us to store the type of a container such as a blob...
Definition: typeid.h:66
static void _Dtor(void *ptr, size_t n)
Destructor for non-fundamental types.
Definition: typeid.h:234
static void _CopyNotAllowed(const void *src, void *dst, size_t n)
A placeholder function for types that do not allow assignment.
Definition: typeid.h:224
const char * name() const
Returns a printable name for the type.
Definition: typeid.h:145
Simple registry implementation in Caffe2 that uses static variables to register object creators durin...
static const char * Name()
Returns the printable name of the type.
Definition: typeid.h:188
PlacementNew ctor() const
Returns the placement new function pointer for individual items.
Definition: typeid.h:127
TypedDestructor dtor() const
Returns the destructor function pointer for individual items.
Definition: typeid.h:139
const size_t & itemsize() const
Returns the size of the item.
Definition: typeid.h:121
TypeMeta(const TypeMeta &src)
Copy constructor.
Definition: typeid.h:80
TypeMeta & operator=(const TypeMeta &src)
Assignment operator.
Definition: typeid.h:89
static void _Ctor(void *ptr, size_t n)
Placement new function for the type.
Definition: typeid.h:201