• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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