proxygen
UnionBasedStatic.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 #pragma once
11 
12 // This pattern is used to create a static whose destructor will never be
13 // called. This is useful since some proxygen clients call exit() directly in
14 // multithreaded programs explicitly against recommendations which lead to
15 // shutdown crashes due to dependent statics being cleaned up while the threads
16 // are still executing.
17 
18 // IMPLEMENTATION MACROS
19 // (Don't use these directly.)
20 #define DECLARE_UNION_STATIC_UNION_IMPL(type, name) \
21 union name##Union { \
22  type data; \
23  name##Union() {} \
24  ~name##Union() {} \
25 }
26 
27 #define DECLARE_UNION_STATIC_UNION_ARRAY_IMPL(type, size, name) \
28 union name##Union { \
29  type data[size]; \
30  name##Union() {} \
31  ~name##Union() {} \
32 }
33 
34 #define DEFINE_UNION_STATIC_UNION_IMPL(type, name, var) \
35 DECLARE_UNION_STATIC_UNION_IMPL(type, name) var;
36 
37 #define DEFINE_UNION_STATIC_UNION_CONST_IMPL(type, name, var) \
38 DECLARE_UNION_STATIC_UNION_IMPL(type, name) const var;
39 
40 #define DEFINE_UNION_STATIC_UNION_CONST_ARRAY_IMPL(type, size, name, var) \
41 DECLARE_UNION_STATIC_UNION_ARRAY_IMPL(type, size, name) const var;
42 
43 // The const_casts are only needed if creating a const union but it's a
44 // no-op otherwise so keep it to avoid creating even more macro helpers.
45 #define DEFINE_UNION_STATIC_CONSTRUCTOR_IMPL(type, name, var) \
46 __attribute__((__constructor__)) \
47 void init##name##Union() { \
48  new (const_cast<type*>(&var.data)) type(); \
49 }
50 
51 #define DEFINE_UNION_STATIC_CONSTRUCTOR_ARG_IMPL(type, name, var, ...) \
52 __attribute__((__constructor__)) \
53 void init##name##Union() { \
54  new (const_cast<type*>(&var.data)) type(__VA_ARGS__); \
55 }
56 // END IMPLEMENTATION MACROS
57 
58 // Use var.data to access the actual member of interest. Zero and argument
59 // versions are provided. If you need to do custom construction, like using a
60 // brace-enclosed initializer list, use the NO_INIT variant and then define
61 // your own __attribute__((__constructor__)) function to do the initialization.
62 #define DEFINE_UNION_STATIC(type, name, var) \
63 DEFINE_UNION_STATIC_UNION_IMPL(type, name, var) \
64 DEFINE_UNION_STATIC_CONSTRUCTOR_IMPL(type, name, var)
65 
66 #define DEFINE_UNION_STATIC_ARGS(type, name, var, ...) \
67 DEFINE_UNION_STATIC_UNION_IMPL(type, name, var) \
68 DEFINE_UNION_STATIC_CONSTRUCTOR_ARG_IMPL(type, name, var, __VA_ARGS__)
69 
70 #define DEFINE_UNION_STATIC_NO_INIT(type, name, var) \
71 DEFINE_UNION_STATIC_UNION_IMPL(type, name, var)
72 
73 // Same as the above three except used to create a const union.
74 #define DEFINE_UNION_STATIC_CONST(type, name, var) \
75 DEFINE_UNION_STATIC_UNION_CONST_IMPL(type, name, var) \
76 DEFINE_UNION_STATIC_CONSTRUCTOR_IMPL(type, name, var)
77 
78 #define DEFINE_UNION_STATIC_CONST_ARGS(type, name, var, ...) \
79 DEFINE_UNION_STATIC_UNION_CONST_IMPL(type, name, var) \
80 DEFINE_UNION_STATIC_CONSTRUCTOR_ARG_IMPL(type, name, var, __VA_ARGS__)
81 
82 #define DEFINE_UNION_STATIC_CONST_NO_INIT(type, name, var) \
83 DEFINE_UNION_STATIC_UNION_CONST_IMPL(type, name, var)
84 
85 #define DEFINE_UNION_STATIC_CONST_ARRAY_NO_INIT(type, size, name, var) \
86 DEFINE_UNION_STATIC_UNION_CONST_ARRAY_IMPL(type, size, name, var)
87 
88 // Use these if you need to extern one of these in a header and then
89 // define it in a .cpp file. For example:
90 //
91 // Header:
92 // DECLARE_UNION_STATIC(std::string, StdString);
93 // extern const StdStringUnion kStringConstant;
94 //
95 // Definition:
96 // const IMPLEMENT_DECLARED_UNION_STATIC_ARGS(
97 // std::string, StdString, DoesNotMatter, kStringConstant, "hello world");
98 //
99 #define DECLARE_UNION_STATIC(type, name) \
100 DECLARE_UNION_STATIC_UNION_IMPL(type, name)
101 
102 #define IMPLEMENT_DECLARED_UNION_STATIC(type, unionName, name, var) \
103 unionName##Union var; \
104 DEFINE_UNION_STATIC_CONSTRUCTOR_ARG_IMPL(type, name, var)
105 
106 #define IMPLEMENT_DECLARED_UNION_STATIC_ARGS(type, unionName, name, var, ...) \
107 unionName##Union var; \
108 DEFINE_UNION_STATIC_CONSTRUCTOR_ARG_IMPL(type, name, var, __VA_ARGS__)