mutex_method_pointer_test.cc (4762B)
1 // Copyright 2017 The Abseil Authors. 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 // https://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 #include "absl/synchronization/mutex.h" 16 17 #include <cstdlib> 18 #include <string> 19 20 #include "gtest/gtest.h" 21 #include "absl/base/config.h" 22 23 namespace { 24 25 class IncompleteClass; 26 27 #ifdef _MSC_VER 28 // These tests verify expectations about sizes of MSVC pointers to methods. 29 // Pointers to methods are distinguished by whether their class hierarchies 30 // contain single inheritance, multiple inheritance, or virtual inheritance. 31 32 // Declare classes of the various MSVC inheritance types. 33 class __single_inheritance SingleInheritance{}; 34 class __multiple_inheritance MultipleInheritance; 35 class __virtual_inheritance VirtualInheritance; 36 37 TEST(MutexMethodPointerTest, MicrosoftMethodPointerSize) { 38 void (SingleInheritance::*single_inheritance_method_pointer)(); 39 void (MultipleInheritance::*multiple_inheritance_method_pointer)(); 40 void (VirtualInheritance::*virtual_inheritance_method_pointer)(); 41 42 #if defined(_M_IX86) || defined(_M_ARM) 43 static_assert(sizeof(single_inheritance_method_pointer) == 4, 44 "Unexpected sizeof(single_inheritance_method_pointer)."); 45 static_assert(sizeof(multiple_inheritance_method_pointer) == 8, 46 "Unexpected sizeof(multiple_inheritance_method_pointer)."); 47 static_assert(sizeof(virtual_inheritance_method_pointer) == 12, 48 "Unexpected sizeof(virtual_inheritance_method_pointer)."); 49 #elif defined(_M_X64) || defined(__aarch64__) 50 static_assert(sizeof(single_inheritance_method_pointer) == 8, 51 "Unexpected sizeof(single_inheritance_method_pointer)."); 52 static_assert(sizeof(multiple_inheritance_method_pointer) == 16, 53 "Unexpected sizeof(multiple_inheritance_method_pointer)."); 54 static_assert(sizeof(virtual_inheritance_method_pointer) == 16, 55 "Unexpected sizeof(virtual_inheritance_method_pointer)."); 56 #endif 57 void (IncompleteClass::*incomplete_class_method_pointer)(); 58 static_assert(sizeof(incomplete_class_method_pointer) >= 59 sizeof(virtual_inheritance_method_pointer), 60 "Failed invariant: sizeof(incomplete_class_method_pointer) >= " 61 "sizeof(virtual_inheritance_method_pointer)!"); 62 } 63 64 class Callback { 65 bool x = true; 66 67 public: 68 Callback() {} 69 bool method() { 70 x = !x; 71 return x; 72 } 73 }; 74 75 class M2 { 76 bool x = true; 77 78 public: 79 M2() {} 80 bool method2() { 81 x = !x; 82 return x; 83 } 84 }; 85 86 class MultipleInheritance : public Callback, public M2 {}; 87 88 TEST(MutexMethodPointerTest, ConditionWithMultipleInheritanceMethod) { 89 // This test ensures that Condition can deal with method pointers from classes 90 // with multiple inheritance. 91 MultipleInheritance object = MultipleInheritance(); 92 absl::Condition condition(&object, &MultipleInheritance::method); 93 EXPECT_FALSE(condition.Eval()); 94 EXPECT_TRUE(condition.Eval()); 95 } 96 97 class __virtual_inheritance VirtualInheritance : virtual public Callback { 98 bool x = false; 99 100 public: 101 VirtualInheritance() {} 102 bool method() { 103 x = !x; 104 return x; 105 } 106 }; 107 108 TEST(MutexMethodPointerTest, ConditionWithVirtualInheritanceMethod) { 109 // This test ensures that Condition can deal with method pointers from classes 110 // with virtual inheritance. 111 VirtualInheritance object = VirtualInheritance(); 112 absl::Condition condition(&object, &VirtualInheritance::method); 113 EXPECT_TRUE(condition.Eval()); 114 EXPECT_FALSE(condition.Eval()); 115 } 116 #endif // #ifdef _MSC_VER 117 118 TEST(MutexMethodPointerTest, ConditionWithIncompleteClassMethod) { 119 using IncompleteClassMethodPointer = void (IncompleteClass::*)(); 120 121 union CallbackSlot { 122 void (*anonymous_function_pointer)(); 123 IncompleteClassMethodPointer incomplete_class_method_pointer; 124 }; 125 126 static_assert(sizeof(CallbackSlot) >= sizeof(IncompleteClassMethodPointer), 127 "The callback slot is not big enough for method pointers."); 128 static_assert( 129 sizeof(CallbackSlot) == sizeof(IncompleteClassMethodPointer), 130 "The callback slot is not big enough for anonymous function pointers."); 131 132 #if defined(_MSC_VER) 133 static_assert(sizeof(IncompleteClassMethodPointer) <= 24, 134 "The pointer to a method of an incomplete class is too big."); 135 #endif 136 } 137 138 } // namespace