libuav original
Dependents: UAVCAN UAVCAN_Subscriber
lazy_constructor.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_UTIL_LAZY_CONSTRUCTOR_HPP_INCLUDED 00006 #define UAVCAN_UTIL_LAZY_CONSTRUCTOR_HPP_INCLUDED 00007 00008 #include <cstdlib> 00009 #include <uavcan/error.hpp> 00010 #include <uavcan/build_config.hpp> 00011 #include <uavcan/util/templates.hpp> 00012 00013 #ifndef UAVCAN_CPP_VERSION 00014 # error UAVCAN_CPP_VERSION 00015 #endif 00016 00017 namespace uavcan 00018 { 00019 /** 00020 * This class allows to postpone the object contruction. 00021 * It statically allocates a pool of memory of just enough size to fit the object being constructed. 00022 * Later call to construct<>() calls the constructor of the object. 00023 * The object will be destroyed automatically when the container class destructor is called. 00024 * The memory pool is aligned at the size of the largest primitive type (long double or long long int). 00025 */ 00026 template <typename T> 00027 class UAVCAN_EXPORT LazyConstructor 00028 { 00029 #if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 00030 struct 00031 { 00032 alignas(T) unsigned char pool[sizeof(T)]; 00033 } data_; 00034 #else 00035 union 00036 { 00037 unsigned char pool[sizeof(T)]; 00038 long double _aligner1; 00039 long long _aligner2; 00040 } data_; 00041 #endif 00042 00043 T* ptr_; 00044 00045 void ensureConstructed() const 00046 { 00047 if (!ptr_) 00048 { 00049 handleFatalError("LazyConstructor<T>"); 00050 } 00051 } 00052 00053 void ensureNotConstructed() const 00054 { 00055 if (ptr_) 00056 { 00057 handleFatalError("LazyConstructor<T>"); 00058 } 00059 } 00060 00061 public: 00062 LazyConstructor() 00063 : ptr_(UAVCAN_NULLPTR) 00064 { 00065 fill(data_.pool, data_.pool + sizeof(T), uint8_t(0)); 00066 } 00067 00068 LazyConstructor(const LazyConstructor<T>& rhs) // Implicit 00069 : ptr_(UAVCAN_NULLPTR) 00070 { 00071 fill(data_.pool, data_.pool + sizeof(T), uint8_t(0)); 00072 if (rhs) 00073 { 00074 construct<const T&>(*rhs); // Invoke copy constructor 00075 } 00076 } 00077 00078 ~LazyConstructor() { destroy(); } 00079 00080 LazyConstructor<T>& operator=(const LazyConstructor<T>& rhs) 00081 { 00082 destroy(); 00083 if (rhs) 00084 { 00085 construct<const T&>(*rhs); // Invoke copy constructor 00086 } 00087 return *this; 00088 } 00089 00090 bool isConstructed() const { return ptr_ != UAVCAN_NULLPTR; } 00091 00092 operator T*() const { return ptr_; } 00093 00094 const T* operator->() const { ensureConstructed(); return ptr_; } 00095 T* operator->() { ensureConstructed(); return ptr_; } 00096 00097 const T& operator*() const { ensureConstructed(); return *ptr_; } 00098 T& operator*() { ensureConstructed(); return *ptr_; } 00099 00100 void destroy() 00101 { 00102 if (ptr_) 00103 { 00104 ptr_->~T(); 00105 } 00106 ptr_ = UAVCAN_NULLPTR; 00107 fill(data_.pool, data_.pool + sizeof(T), uint8_t(0)); 00108 } 00109 00110 void construct() 00111 { 00112 ensureNotConstructed(); 00113 ptr_ = new (static_cast<void*>(data_.pool)) T(); 00114 } 00115 00116 // MAX_ARGS = 6 00117 // TEMPLATE = ''' 00118 // template <%s> 00119 // void construct(%s) 00120 // { 00121 // ensureNotConstructed(); 00122 // ptr_ = new (static_cast<void*>(data_.pool)) T(%s); 00123 // }''' 00124 // for nargs in range(1, MAX_ARGS + 1): 00125 // nums = [(x + 1) for x in range(nargs)] 00126 // l1 = ['typename P%d' % x for x in nums] 00127 // l2 = ['typename ParameterType<P%d>::Type p%d' % (x, x) for x in nums] 00128 // l3 = ['p%d' % x for x in nums] 00129 // print(TEMPLATE % (', '.join(l1), ', '.join(l2), ', '.join(l3))) 00130 00131 template <typename P1> 00132 void construct(typename ParameterType<P1>::Type p1) 00133 { 00134 ensureNotConstructed(); 00135 ptr_ = new (static_cast<void*>(data_.pool)) T(p1); 00136 } 00137 00138 template<typename P1, typename P2> 00139 void construct(typename ParameterType<P1>::Type p1, typename ParameterType<P2>::Type p2) 00140 { 00141 ensureNotConstructed(); 00142 ptr_ = new (static_cast<void*>(data_.pool)) T(p1, p2); 00143 } 00144 00145 template<typename P1, typename P2, typename P3> 00146 void construct(typename ParameterType<P1>::Type p1, typename ParameterType<P2>::Type p2, 00147 typename ParameterType<P3>::Type p3) 00148 { 00149 ensureNotConstructed(); 00150 ptr_ = new (static_cast<void*>(data_.pool)) T(p1, p2, p3); 00151 } 00152 00153 template<typename P1, typename P2, typename P3, typename P4> 00154 void construct(typename ParameterType<P1>::Type p1, typename ParameterType<P2>::Type p2, 00155 typename ParameterType<P3>::Type p3, typename ParameterType<P4>::Type p4) 00156 { 00157 ensureNotConstructed(); 00158 ptr_ = new (static_cast<void*>(data_.pool)) T(p1, p2, p3, p4); 00159 } 00160 00161 template<typename P1, typename P2, typename P3, typename P4, typename P5> 00162 void construct(typename ParameterType<P1>::Type p1, typename ParameterType<P2>::Type p2, 00163 typename ParameterType<P3>::Type p3, typename ParameterType<P4>::Type p4, 00164 typename ParameterType<P5>::Type p5) 00165 { 00166 ensureNotConstructed(); 00167 ptr_ = new (static_cast<void*>(data_.pool)) T(p1, p2, p3, p4, p5); 00168 } 00169 00170 template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6> 00171 void construct(typename ParameterType<P1>::Type p1, typename ParameterType<P2>::Type p2, 00172 typename ParameterType<P3>::Type p3, typename ParameterType<P4>::Type p4, 00173 typename ParameterType<P5>::Type p5, typename ParameterType<P6>::Type p6) 00174 { 00175 ensureNotConstructed(); 00176 ptr_ = new (static_cast<void*>(data_.pool)) T(p1, p2, p3, p4, p5, p6); 00177 } 00178 }; 00179 00180 } 00181 00182 #endif // UAVCAN_UTIL_LAZY_CONSTRUCTOR_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:32 by 1.7.2