Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers factory.h Source File

factory.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_FACTORY__
00030 #define __ETL_FACTORY__
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 #if defined(ETL_COMPILER_GCC)
00046   #warning THIS CLASS IS DEPRECATED!USE VARIANT_POOL INSTEAD.
00047 #elif defined(ETL_COMPILER_MICROSOFT)
00048   #pragma message ("THIS CLASS IS DEPRECATED! USE VARIANT_POOL INSTEAD.")
00049 #endif
00050 
00051 #undef ETL_FILE
00052 #define ETL_FILE "40"
00053 
00054 namespace etl
00055 {
00056   //***************************************************************************
00057   class factory_exception : public etl::exception
00058   {
00059   public:
00060 
00061     factory_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00062       : exception(reason_, file_name_, line_number_)
00063     {
00064     }
00065   };
00066 
00067   //***************************************************************************
00068   class factory_cannot_create : public etl::factory_exception
00069   {
00070   public:
00071 
00072     factory_cannot_create(string_type file_name_, numeric_type line_number_)
00073       : factory_exception(ETL_ERROR_TEXT("factory:cannot create", ETL_FILE"A"), file_name_, line_number_)
00074     {
00075     }
00076   };
00077 
00078   //***************************************************************************
00079   class factory_did_not_create : public etl::factory_exception
00080   {
00081   public:
00082 
00083     factory_did_not_create(string_type file_name_, numeric_type line_number_)
00084       : factory_exception(ETL_ERROR_TEXT("factory:did not create", ETL_FILE"B"), file_name_, line_number_)
00085     {
00086     }
00087   };
00088 
00089   //***************************************************************************
00090   template <const size_t MAX_SIZE_,
00091             typename T1,
00092             typename T2  = etl::type_id_pair<etl::null_type, -2>,
00093             typename T3  = etl::type_id_pair<etl::null_type, -3>,
00094             typename T4  = etl::type_id_pair<etl::null_type, -4>,
00095             typename T5  = etl::type_id_pair<etl::null_type, -5>,
00096             typename T6  = etl::type_id_pair<etl::null_type, -6>,
00097             typename T7  = etl::type_id_pair<etl::null_type, -7>,
00098             typename T8  = etl::type_id_pair<etl::null_type, -8>,
00099             typename T9  = etl::type_id_pair<etl::null_type, -9>,
00100             typename T10 = etl::type_id_pair<etl::null_type, -10>,
00101             typename T11 = etl::type_id_pair<etl::null_type, -11>,
00102             typename T12 = etl::type_id_pair<etl::null_type, -12>,
00103             typename T13 = etl::type_id_pair<etl::null_type, -13>,
00104             typename T14 = etl::type_id_pair<etl::null_type, -14>,
00105             typename T15 = etl::type_id_pair<etl::null_type, -15>,
00106             typename T16 = etl::type_id_pair<etl::null_type, -16> >
00107   class factory
00108   {
00109   private:
00110 
00111     typedef typename T1::type  TT1;
00112     typedef typename T2::type  TT2;
00113     typedef typename T3::type  TT3;
00114     typedef typename T4::type  TT4;
00115     typedef typename T5::type  TT5;
00116     typedef typename T6::type  TT6;
00117     typedef typename T7::type  TT7;
00118     typedef typename T8::type  TT8;
00119     typedef typename T9::type  TT9;
00120     typedef typename T10::type TT10;
00121     typedef typename T11::type TT11;
00122     typedef typename T12::type TT12;
00123     typedef typename T13::type TT13;
00124     typedef typename T14::type TT14;
00125     typedef typename T15::type TT15;
00126     typedef typename T16::type TT16;
00127 
00128     typedef etl::type_id_lookup<T1, T2,  T3,  T4,  T5,  T6,  T7,  T8,
00129                                 T9, T10, T11, T12, T13, T14, T15, T16> lookup_t;
00130 
00131   public:
00132 
00133     static const size_t MAX_SIZE = MAX_SIZE_;
00134 
00135     //*************************************************************************
00136     /// Default constructor.
00137     //*************************************************************************
00138     factory()
00139     {
00140     }
00141 
00142 #if !ETL_CPP11_SUPPORTED
00143     //*************************************************************************
00144     /// Creates the object. Default constructor.
00145     //*************************************************************************
00146     template <typename T>
00147     T* create_from_type()
00148     {
00149       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00150 
00151       T* p = std::nullptr;
00152 
00153       if (pool.full())
00154       {
00155         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00156       }
00157       else
00158       {
00159         p = pool.template allocate<T>();
00160 
00161         if (p != std::nullptr)
00162         {
00163           new (p) T();
00164         }
00165       }
00166 
00167       return p;
00168     }
00169 
00170     //*************************************************************************
00171     /// Creates the object. One parameter constructor.
00172     //*************************************************************************
00173     template <typename T, typename TP1>
00174     T* create_from_type(const TP1& p1)
00175     {
00176       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00177 
00178       T* p = std::nullptr;
00179 
00180       if (pool.full())
00181       {
00182         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00183       }
00184       else
00185       {
00186         p = pool.template allocate<T>();
00187 
00188         if (p != std::nullptr)
00189         {
00190           new (p) T(p1);
00191         }
00192       }
00193 
00194       return p;
00195     }
00196 
00197     //*************************************************************************
00198     /// Creates the object. Two parameter constructor.
00199     //*************************************************************************
00200     template <typename T, typename TP1, typename TP2>
00201     T* create_from_type(const TP1& p1, const TP2& p2)
00202     {
00203       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00204 
00205       T* p = std::nullptr;
00206 
00207       if (pool.full())
00208       {
00209         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00210       }
00211       else
00212       {
00213         p = pool.template allocate<T>();
00214 
00215         if (p != std::nullptr)
00216         {
00217           new (p) T(p1, p2);
00218         }
00219       }
00220 
00221       return p;
00222     }
00223 
00224     //*************************************************************************
00225     /// Creates the object. Three parameter constructor.
00226     //*************************************************************************
00227     template <typename T, typename TP1, typename TP2, typename TP3>
00228     T* create_from_type(const TP1& p1, const TP2& p2, const TP3& p3)
00229     {
00230       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00231 
00232       T* p = std::nullptr;
00233 
00234       if (pool.full())
00235       {
00236         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00237       }
00238       else
00239       {
00240         p = pool.template allocate<T>();
00241 
00242         if (p != std::nullptr)
00243         {
00244           new (p) T(p1, p2, p3);
00245         }
00246       }
00247 
00248       return p;
00249     }
00250 
00251     //*************************************************************************
00252     /// Creates the object. Four parameter constructor.
00253     //*************************************************************************
00254     template <typename T, typename TP1, typename TP2, typename TP3, typename TP4>
00255     T* create_from_type(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4)
00256     {
00257       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00258 
00259       T* p = std::nullptr;
00260 
00261       if (pool.full())
00262       {
00263         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00264       }
00265       else
00266       {
00267         p = pool.template allocate<T>();
00268 
00269         if (p != std::nullptr)
00270         {
00271           new (p) T(p1, p2, p3, p4);
00272         }
00273       }
00274 
00275       return p;
00276     }
00277 
00278     //*************************************************************************
00279     /// Creates the object from an index. Default constructor.
00280     //*************************************************************************
00281     template <size_t ID>
00282     typename lookup_t::template type_from_id<ID>::type* create_from_id()
00283     {
00284       typedef typename lookup_t::template type_from_id<ID>::type type;
00285       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00286       return create_from_type<type>();
00287     }
00288 
00289     //*************************************************************************
00290     /// Creates the object from an index. One parameter constructor.
00291     //*************************************************************************
00292     template <size_t ID, typename TP1>
00293     typename lookup_t::template type_from_id<ID>::type* create_from_id(const TP1& p1)
00294     {
00295       typedef typename lookup_t::template type_from_id<ID>::type type;
00296       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00297       return create_from_type<type>(p1);
00298     }
00299 
00300     //*************************************************************************
00301     /// Creates the object from an index. Two parameter constructor.
00302     //*************************************************************************
00303     template <size_t ID, typename TP1, typename TP2>
00304     typename lookup_t::template type_from_id<ID>::type* create_from_id(const TP1& p1, const TP2& p2)
00305     {
00306       typedef typename lookup_t::template type_from_id<ID>::type type;
00307       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00308       return create_from_type<type>(p1, p2);
00309     }
00310 
00311     //*************************************************************************
00312     /// Creates the object from an index. Three parameter constructor.
00313     //*************************************************************************
00314     template <size_t ID, typename TP1, typename TP2, typename TP3>
00315     typename lookup_t::template type_from_id<ID>::type* create_from_id(const TP1& p1, const TP2& p2, const TP3& p3)
00316     {
00317       typedef typename lookup_t::template type_from_id<ID>::type type;
00318       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00319       return create_from_type<type>(p1, p2, p3);
00320     }
00321 
00322     //*************************************************************************
00323     /// Creates the object from an index. Three parameter constructor.
00324     //*************************************************************************
00325     template <size_t ID, typename TP1, typename TP2, typename TP3, typename TP4>
00326     typename lookup_t::template type_from_id<ID>::type* create_from_id(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4)
00327     {
00328       typedef typename lookup_t::template type_from_id<ID>::type type;
00329       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00330       return create_from_type<type>(p1, p2, p3, p4);
00331     }
00332 #else
00333     //*************************************************************************
00334     /// Creates the object from a type. Variadic parameter constructor.
00335     //*************************************************************************
00336     template <typename T, typename... Args>
00337     T* create_from_type(Args&&... args)
00338     {
00339       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
00340 
00341       T* p = std::nullptr;
00342 
00343       if (pool.full())
00344       {
00345         ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
00346       }
00347       else
00348       {
00349         p = pool.template allocate<T>();
00350 
00351         if (p != std::nullptr)
00352         {
00353           new (p) T(std::forward<Args>(args)...);
00354         }
00355       }
00356 
00357       return p;
00358     }
00359 
00360     //*************************************************************************
00361     /// Creates the object from an index. Variadic parameter constructor.
00362     //*************************************************************************
00363     template <size_t ID, typename... Args>
00364     typename lookup_t::template type_from_id<ID>::type* create_from_id(Args&&... args)
00365     {
00366       typedef typename lookup_t::template type_from_id<ID>::type type;
00367       STATIC_ASSERT((!etl::is_same<void, type>::value), "Invalid index");
00368       return create_from_type<type>(std::forward<Args>(args)...);
00369     }
00370 #endif
00371 
00372     //*************************************************************************
00373     /// Destroys the object.
00374     //*************************************************************************
00375     template <typename T>
00376     bool destroy(const T* const p)
00377     {
00378       STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value ||
00379                      etl::is_base_of<T, TT1>::value  ||
00380                      etl::is_base_of<T, TT2>::value  ||
00381                      etl::is_base_of<T, TT3>::value  ||
00382                      etl::is_base_of<T, TT4>::value  ||
00383                      etl::is_base_of<T, TT5>::value  ||
00384                      etl::is_base_of<T, TT6>::value  ||
00385                      etl::is_base_of<T, TT7>::value  ||
00386                      etl::is_base_of<T, TT8>::value  ||
00387                      etl::is_base_of<T, TT9>::value  ||
00388                      etl::is_base_of<T, TT10>::value ||
00389                      etl::is_base_of<T, TT11>::value ||
00390                      etl::is_base_of<T, TT12>::value ||
00391                      etl::is_base_of<T, TT13>::value ||
00392                      etl::is_base_of<T, TT14>::value ||
00393                      etl::is_base_of<T, TT15>::value ||
00394                      etl::is_base_of<T, TT16>::value), "Invalid type");
00395 
00396       p->~T();
00397 
00398       void* vp = reinterpret_cast<char*>(const_cast<T*>(p));
00399 
00400       if (pool.is_in_pool(vp))
00401       {
00402         pool.release(vp);
00403         return true;
00404       }
00405       else
00406       {
00407         ETL_ASSERT(false, ETL_ERROR(factory_did_not_create));
00408         return false;
00409       }
00410     }
00411 
00412     //*************************************************************************
00413     /// Returns the maximum number of items in the factory.
00414     //*************************************************************************
00415     size_t max_size() const
00416     {
00417       return MAX_SIZE;
00418     }
00419 
00420     //*************************************************************************
00421     /// Returns the number of free items in the factory.
00422     //*************************************************************************
00423     size_t available() const
00424     {
00425       return pool.available();
00426     }
00427 
00428     //*************************************************************************
00429     /// Returns the number of allocated items in the factory.
00430     //*************************************************************************
00431     size_t size() const
00432     {
00433       return pool.size();
00434     }
00435 
00436     //*************************************************************************
00437     /// Checks to see if there are no allocated items in the factory.
00438     /// \return <b>true</b> if there are none allocated.
00439     //*************************************************************************
00440     bool empty() const
00441     {
00442       return pool.empty();
00443     }
00444 
00445     //*************************************************************************
00446     /// Checks to see if there are no free items in the factory.
00447     /// \return <b>true</b> if there are none free.
00448     //*************************************************************************
00449     bool full() const
00450     {
00451       return pool.full();
00452     }
00453 
00454   private:
00455 
00456     factory(const factory&);
00457     factory& operator =(const factory&);
00458 
00459     // The pool.
00460     etl::generic_pool<etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::size,
00461                       etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::alignment,
00462                       MAX_SIZE> pool;
00463   };
00464 }
00465 
00466 #undef ETL_FILE
00467 
00468 #endif
00469