1/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_CORE_FRAMEWORK_TYPE_INDEX_H_
17#define TENSORFLOW_CORE_FRAMEWORK_TYPE_INDEX_H_
18
19#include <string>
20
21#if defined(__GXX_RTTI) || defined(_CPPRTTI)
22#include <typeinfo>
23#endif // __GXX_RTTI
24
25#include "tensorflow/core/platform/hash.h"
26#include "tensorflow/core/platform/types.h"
27
28namespace tensorflow {
29
30// On some platforms, we would like to avoid using RTTI in order to have smaller
31// binary sizes. This file provides a thin TypeIndex class that mimics
32// std::type_index but does not use RTTI (with a minimal set of functions needed
33// by the TensorFlow framework, and more can be added if necessary). In the
34// absence of RTTI, it does not provide the actual name of the type, and only
35// returns a pre-baked string specifying that RTTI is disabled. The hash code
36// provided in this class is unique for each class. However, it is generated at
37// runtime so this hash code should not be serialized - the value for the same
38// type can change from run to run.
39class TypeIndex {
40 public:
41 TypeIndex(const TypeIndex& src) : hash_(src.hash_), name_(src.name_) {}
42 TypeIndex& operator=(const TypeIndex& src) {
43 hash_ = src.hash_;
44 name_ = src.name_;
45 return *this;
46 }
47 bool operator==(const TypeIndex& rhs) const { return (hash_ == rhs.hash_); }
48 bool operator!=(const TypeIndex& rhs) const { return (hash_ != rhs.hash_); }
49 ~TypeIndex() {}
50
51 const char* name() const { return name_; }
52
53 uint64 hash_code() const { return hash_; }
54
55 // Returns a TypeIndex object that corresponds to a typename.
56 template <typename T>
57 static TypeIndex Make() {
58#ifdef PLATFORM_CLOUD_TPU
59 static bool hash_bit[1];
60 return TypeIndex(static_cast<uint64>(reinterpret_cast<intptr_t>(hash_bit)),
61 typeid(T).name());
62#endif
63#if defined(__GXX_RTTI) || defined(_CPPRTTI)
64
65 // Use a hash based on the type name to avoid issues due to RTLD_LOCAL on
66 // MacOS (b/156979412).
67 return TypeIndex(Hash64(typeid(T).name()), typeid(T).name());
68
69#else
70 static bool hash_bit[1];
71#if TARGET_OS_OSX
72 // Warn MacOS users that not using RTTI can cause problems (b/156979412).
73#warning \
74 "Compiling with RTTI disabled on MacOS can cause problems when comparing " \
75 "types across shared libraries."
76#endif // TARGET_OS_OSX
77
78 // No type names available.
79 return TypeIndex(static_cast<uint64>(reinterpret_cast<intptr_t>(hash_bit)),
80 "[RTTI disabled]");
81#endif // __GXX_RTTI
82 }
83
84 private:
85 // We hide the constructor of the TypeIndex class. Use the templated
86 // Make<T>() function to create a TypeIndex object.
87 explicit TypeIndex(const uint64 hash, const char* name)
88 : hash_(hash), name_(name) {}
89 uint64 hash_;
90 const char* name_;
91};
92
93} // namespace tensorflow
94
95#endif // TENSORFLOW_CORE_FRAMEWORK_TYPE_INDEX_H_
96