libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lazy_constructor.hpp Source File

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