1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 #ifndef GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 9 #define GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 10 11 #include <stdint.h> 12 13 #include <string> 14 #include <utility> 15 16 // clang-format off 17 #include "google/protobuf/port_def.inc" 18 // clang-format on 19 20 namespace google { 21 namespace protobuf { 22 namespace internal { 23 24 // Wraps a variable whose constructor and destructor are explicitly 25 // called. It is particularly useful for a global variable, without its 26 // constructor and destructor run on start and end of the program lifetime. 27 // This circumvents the initial construction order fiasco, while keeping 28 // the address of the empty string a compile time constant. 29 // 30 // Pay special attention to the initialization state of the object. 31 // 1. The object is "uninitialized" to begin with. 32 // 2. Call Construct() or DefaultConstruct() only if the object is 33 // uninitialized. After the call, the object becomes "initialized". 34 // 3. Call get() and get_mutable() only if the object is initialized. 35 // 4. Call Destruct() only if the object is initialized. 36 // After the call, the object becomes uninitialized. 37 template <typename T, size_t min_align = 1> 38 class ExplicitlyConstructed { 39 public: DefaultConstruct()40 void DefaultConstruct() { new (&union_) T(); } 41 42 template <typename... Args> Construct(Args &&...args)43 void Construct(Args&&... args) { 44 new (&union_) T(std::forward<Args>(args)...); 45 } 46 Destruct()47 void Destruct() { get_mutable()->~T(); } 48 get()49 constexpr const T& get() const { return reinterpret_cast<const T&>(union_); } get_mutable()50 T* get_mutable() { return reinterpret_cast<T*>(&union_); } 51 52 private: 53 union AlignedUnion { 54 alignas(min_align > alignof(T) ? min_align 55 : alignof(T)) char space[sizeof(T)]; 56 int64_t align_to_int64; 57 void* align_to_ptr; 58 } union_; 59 }; 60 61 // ArenaStringPtr compatible explicitly constructed string type. 62 // This empty string type is aligned with a minimum alignment of 8 bytes 63 // which is the minimum requirement of ArenaStringPtr 64 using ExplicitlyConstructedArenaString = ExplicitlyConstructed<std::string, 8>; 65 66 } // namespace internal 67 } // namespace protobuf 68 } // namespace google 69 70 #include "google/protobuf/port_undef.inc" 71 72 #endif // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__ 73