1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 ==============================================================================*/ 15 16 #include "tensorflow/core/lib/gtl/manual_constructor.h" 17 18 #include <stdint.h> 19 20 #include "tensorflow/core/platform/logging.h" 21 #include "tensorflow/core/platform/test.h" 22 23 namespace tensorflow { 24 namespace { 25 26 static int constructor_count_ = 0; 27 28 template <int kSize> 29 struct TestN { 30 TestN() { ++constructor_count_; } 31 ~TestN() { --constructor_count_; } 32 char a[kSize]; 33 }; 34 35 typedef TestN<1> Test1; 36 typedef TestN<2> Test2; 37 typedef TestN<3> Test3; 38 typedef TestN<4> Test4; 39 typedef TestN<5> Test5; 40 typedef TestN<9> Test9; 41 typedef TestN<15> Test15; 42 43 } // namespace 44 45 namespace { 46 47 TEST(ManualConstructorTest, Sizeof) { 48 CHECK_EQ(sizeof(ManualConstructor<Test1>), sizeof(Test1)); 49 CHECK_EQ(sizeof(ManualConstructor<Test2>), sizeof(Test2)); 50 CHECK_EQ(sizeof(ManualConstructor<Test3>), sizeof(Test3)); 51 CHECK_EQ(sizeof(ManualConstructor<Test4>), sizeof(Test4)); 52 CHECK_EQ(sizeof(ManualConstructor<Test5>), sizeof(Test5)); 53 CHECK_EQ(sizeof(ManualConstructor<Test9>), sizeof(Test9)); 54 CHECK_EQ(sizeof(ManualConstructor<Test15>), sizeof(Test15)); 55 56 CHECK_EQ(constructor_count_, 0); 57 ManualConstructor<Test1> mt[4]; 58 CHECK_EQ(sizeof(mt), 4); 59 CHECK_EQ(constructor_count_, 0); 60 mt[0].Init(); 61 CHECK_EQ(constructor_count_, 1); 62 mt[0].Destroy(); 63 } 64 65 TEST(ManualConstructorTest, Alignment) { 66 // We want to make sure that ManualConstructor aligns its memory properly 67 // on a word barrier. Otherwise, it might be unexpectedly slow, since 68 // memory access will be unaligned. 69 70 struct { 71 char a; 72 ManualConstructor<void*> b; 73 } test1; 74 struct { 75 char a; 76 void* b; 77 } control1; 78 79 // TODO(bww): Make these tests more direct with C++11 alignment_of<T>::value. 80 EXPECT_EQ(reinterpret_cast<char*>(test1.b.get()) - &test1.a, 81 reinterpret_cast<char*>(&control1.b) - &control1.a); 82 EXPECT_EQ(reinterpret_cast<intptr_t>(test1.b.get()) % sizeof(control1.b), 0); 83 84 struct { 85 char a; 86 ManualConstructor<long double> b; 87 } test2; 88 struct { 89 char a; 90 long double b; 91 } control2; 92 93 EXPECT_EQ(reinterpret_cast<char*>(test2.b.get()) - &test2.a, 94 reinterpret_cast<char*>(&control2.b) - &control2.a); 95 #ifdef ARCH_K8 96 EXPECT_EQ(reinterpret_cast<intptr_t>(test2.b.get()) % 16, 0); 97 #endif 98 #ifdef ARCH_PIII 99 EXPECT_EQ(reinterpret_cast<intptr_t>(test2.b.get()) % 4, 0); 100 #endif 101 } 102 103 TEST(ManualConstructorTest, DefaultInitialize) { 104 struct X { 105 X() : x(123) {} 106 int x; 107 }; 108 union { 109 ManualConstructor<X> x; 110 ManualConstructor<int> y; 111 } u; 112 *u.y = -1; 113 u.x.Init(); // should default-initialize u.x 114 EXPECT_EQ(123, u.x->x); 115 } 116 117 TEST(ManualConstructorTest, ZeroInitializePOD) { 118 union { 119 ManualConstructor<int> x; 120 ManualConstructor<int> y; 121 } u; 122 *u.y = -1; 123 u.x.Init(); // should not zero-initialize u.x 124 EXPECT_EQ(-1, *u.y); 125 } 126 127 } // namespace 128 } // namespace tensorflow 129