Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers variant_pool.h Source File

variant_pool.h

00001 /******************************************************************************
00002 The MIT License(MIT)
00003 
00004 Embedded Template Library.
00005 https://github.com/ETLCPP/etl
00006 https://www.etlcpp.com
00007 
00008 Copyright(c) 2017 jwellbelove
00009 
00010 Permission is hereby granted, free of charge, to any person obtaining a copy
00011 of this software and associated documentation files(the "Software"), to deal
00012 in the Software without restriction, including without limitation the rights
00013 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00014 copies of the Software, and to permit persons to whom the Software is
00015 furnished to do so, subject to the following conditions :
00016 
00017 The above copyright notice and this permission notice shall be included in all
00018 copies or substantial portions of the Software.
00019 
00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00026 SOFTWARE.
00027 ******************************************************************************/
00028 
00029 #ifndef __ETL_VARIANT_POOL__
00030 #define __ETL_VARIANT_POOL__
00031 
00032 #include <stdint.h>
00033 #include <utility>
00034 
00035 #include "platform.h "
00036 #include "error_handler.h "
00037 #include "exception.h "
00038 #include "largest.h "
00039 #include "type_traits.h "
00040 #include "alignment.h "
00041 #include "static_assert.h"
00042 #include "type_lookup.h"
00043 #include <pool.h >
00044 
00045 #undef ETL_FILE
00046 #define ETL_FILE "40"
00047 
00048 namespace etl
00049 {
00050   //***************************************************************************
00051   class variant_pool_exception : public etl::exception
00052   {
00053   public:
00054 
00055     variant_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00056       : exception(reason_, file_name_, line_number_)
00057     {
00058     }
00059   };
00060 
00061   //***************************************************************************
00062   class variant_pool_cannot_create : public etl::variant_pool_exception
00063   {
00064   public:
00065 
00066     variant_pool_cannot_create(string_type file_name_, numeric_type line_number_)
00067       : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:cannot create", ETL_FILE"A"), file_name_, line_number_)
00068     {
00069     }
00070   };
00071 
00072   //***************************************************************************
00073   class variant_pool_did_not_create : public etl::variant_pool_exception
00074   {
00075   public:
00076 
00077     variant_pool_did_not_create(string_type file_name_, numeric_type line_number_)
00078       : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:did not create", ETL_FILE"B"), file_name_, line_number_)
00079     {
00080     }
00081   };
00082 
00083   //***************************************************************************
00084   template <const size_t MAX_SIZE_,
00085             typename T1,
00086             typename T2  = void,
00087             typename T3  = void,
00088             typename T4  = void,
00089             typename T5  = void,
00090             typename T6  = void,
00091             typename T7  = void,
00092             typename T8  = void,
00093             typename T9  = void,
00094             typename T10 = void,
00095             typename T11 = void,
00096             typename T12 = void,
00097             typename T13 = void,
00098             typename T14 = void,
00099             typename T15 = void,
00100             typename T16 = void>
00101   class variant_pool
00102   {
00103   public:
00104 
00105     static const size_t MAX_SIZE = MAX_SIZE_;
00106 
00107     //*************************************************************************
00108     /// Default constructor.
00109     //*************************************************************************
00110     variant_pool()
00111     {
00112     }
00113 
00114 #if !ETL_CPP11_SUPPORTED
00115     //*************************************************************************
00116     /// Creates the object. Default constructor.
00117     //*************************************************************************
00118     template <typename T>
00119     T* create()
00120     {
00121       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00122 
00123       T* p = std::nullptr;
00124 
00125       if (pool.full())
00126       {
00127         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00128       }
00129       else
00130       {
00131         p = pool.template allocate<T>();
00132 
00133         if (p != std::nullptr)
00134         {
00135           new (p) T();
00136         }
00137       }
00138 
00139       return p;
00140     }
00141 
00142     //*************************************************************************
00143     /// Creates the object. One parameter constructor.
00144     //*************************************************************************
00145     template <typename T, typename TP1>
00146     T* create(const TP1& p1)
00147     {
00148       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00149 
00150       T* p = std::nullptr;
00151 
00152       if (pool.full())
00153       {
00154         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00155       }
00156       else
00157       {
00158         p = pool.template allocate<T>();
00159 
00160         if (p != std::nullptr)
00161         {
00162           new (p) T(p1);
00163         }
00164       }
00165 
00166       return p;
00167     }
00168 
00169     //*************************************************************************
00170     /// Creates the object. Two parameter constructor.
00171     //*************************************************************************
00172     template <typename T, typename TP1, typename TP2>
00173     T* create(const TP1& p1, const TP2& p2)
00174     {
00175       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00176 
00177       T* p = std::nullptr;
00178 
00179       if (pool.full())
00180       {
00181         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00182       }
00183       else
00184       {
00185         p = pool.template allocate<T>();
00186 
00187         if (p != std::nullptr)
00188         {
00189           new (p) T(p1, p2);
00190         }
00191       }
00192 
00193       return p;
00194     }
00195 
00196     //*************************************************************************
00197     /// Creates the object. Three parameter constructor.
00198     //*************************************************************************
00199     template <typename T, typename TP1, typename TP2, typename TP3>
00200     T* create(const TP1& p1, const TP2& p2, const TP3& p3)
00201     {
00202       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00203 
00204       T* p = std::nullptr;
00205 
00206       if (pool.full())
00207       {
00208         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00209       }
00210       else
00211       {
00212         p = pool.template allocate<T>();
00213 
00214         if (p != std::nullptr)
00215         {
00216           new (p) T(p1, p2, p3);
00217         }
00218       }
00219 
00220       return p;
00221     }
00222 
00223     //*************************************************************************
00224     /// Creates the object. Four parameter constructor.
00225     //*************************************************************************
00226     template <typename T, typename TP1, typename TP2, typename TP3, typename TP4>
00227     T* create(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4)
00228     {
00229       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00230 
00231       T* p = std::nullptr;
00232 
00233       if (pool.full())
00234       {
00235         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00236       }
00237       else
00238       {
00239         p = pool.template allocate<T>();
00240 
00241         if (p != std::nullptr)
00242         {
00243           new (p) T(p1, p2, p3, p4);
00244         }
00245       }
00246 
00247       return p;
00248     }
00249 #else
00250     //*************************************************************************
00251     /// Creates the object from a type. Variadic parameter constructor.
00252     //*************************************************************************
00253     template <typename T, typename... Args>
00254     T* create(Args&&... args)
00255     {
00256       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type");
00257 
00258       T* p = std::nullptr;
00259 
00260       if (pool.full())
00261       {
00262         ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create));
00263       }
00264       else
00265       {
00266         p = pool.template allocate<T>();
00267 
00268         if (p != std::nullptr)
00269         {
00270           new (p) T(std::forward<Args>(args)...);
00271         }
00272       }
00273 
00274       return p;
00275     }
00276 #endif
00277 
00278     //*************************************************************************
00279     /// Destroys the object.
00280     //*************************************************************************
00281     template <typename T>
00282     bool destroy(const T* const p)
00283     {
00284       STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value ||
00285                      etl::is_base_of<T, T1>::value  ||
00286                      etl::is_base_of<T, T2>::value  ||
00287                      etl::is_base_of<T, T3>::value  ||
00288                      etl::is_base_of<T, T4>::value  ||
00289                      etl::is_base_of<T, T5>::value  ||
00290                      etl::is_base_of<T, T6>::value  ||
00291                      etl::is_base_of<T, T7>::value  ||
00292                      etl::is_base_of<T, T8>::value  ||
00293                      etl::is_base_of<T, T9>::value  ||
00294                      etl::is_base_of<T, T10>::value ||
00295                      etl::is_base_of<T, T11>::value ||
00296                      etl::is_base_of<T, T12>::value ||
00297                      etl::is_base_of<T, T13>::value ||
00298                      etl::is_base_of<T, T14>::value ||
00299                      etl::is_base_of<T, T15>::value ||
00300                      etl::is_base_of<T, T16>::value), "Invalid type");
00301 
00302       p->~T();
00303 
00304       void* vp = reinterpret_cast<char*>(const_cast<T*>(p));
00305 
00306       if (pool.is_in_pool(vp))
00307       {
00308         pool.release(vp);
00309         return true;
00310       }
00311       else
00312       {
00313         ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create));
00314         return false;
00315       }
00316     }
00317 
00318     //*************************************************************************
00319     /// Returns the maximum number of items in the variant_pool.
00320     //*************************************************************************
00321     size_t max_size() const
00322     {
00323       return MAX_SIZE;
00324     }
00325 
00326     //*************************************************************************
00327     /// Returns the number of free items in the variant_pool.
00328     //*************************************************************************
00329     size_t available() const
00330     {
00331       return pool.available();
00332     }
00333 
00334     //*************************************************************************
00335     /// Returns the number of allocated items in the variant_pool.
00336     //*************************************************************************
00337     size_t size() const
00338     {
00339       return pool.size();
00340     }
00341 
00342     //*************************************************************************
00343     /// Checks to see if there are no allocated items in the variant_pool.
00344     /// \return <b>true</b> if there are none allocated.
00345     //*************************************************************************
00346     bool empty() const
00347     {
00348       return pool.empty();
00349     }
00350 
00351     //*************************************************************************
00352     /// Checks to see if there are no free items in the variant_pool.
00353     /// \return <b>true</b> if there are none free.
00354     //*************************************************************************
00355     bool full() const
00356     {
00357       return pool.full();
00358     }
00359 
00360   private:
00361 
00362     variant_pool(const variant_pool&);
00363     variant_pool& operator =(const variant_pool&);
00364 
00365     // The pool.
00366     etl::generic_pool<etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
00367                       etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment,
00368                       MAX_SIZE> pool;
00369   };
00370 }
00371 
00372 #undef ETL_FILE
00373 
00374 #endif
00375