Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pool.h
00001 ///\file 00002 00003 /****************************************************************************** 00004 The MIT License(MIT) 00005 00006 Embedded Template Library. 00007 https://github.com/ETLCPP/etl 00008 http://www.etlcpp.com 00009 00010 Copyright(c) 2014 jwellbelove 00011 00012 Permission is hereby granted, free of charge, to any person obtaining a copy 00013 of this software and associated documentation files(the "Software"), to deal 00014 in the Software without restriction, including without limitation the rights 00015 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00016 copies of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions : 00018 00019 The above copyright notice and this permission notice shall be included in all 00020 copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00023 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00024 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00025 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00026 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00027 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00028 SOFTWARE. 00029 ******************************************************************************/ 00030 00031 #ifndef __ETL_POOL__ 00032 #define __ETL_POOL__ 00033 00034 #include "platform.h " 00035 #include "alignment.h " 00036 #include "array.h " 00037 #include "container.h " 00038 #include "integral_limits.h " 00039 #include "nullptr.h " 00040 #include "alignment.h " 00041 #include "error_handler.h " 00042 #include "static_assert.h" 00043 00044 #include <iterator> 00045 #include <algorithm> 00046 00047 #undef ETL_FILE 00048 #define ETL_FILE "11" 00049 00050 //***************************************************************************** 00051 ///\defgroup pool pool 00052 /// A fixed capacity pool. 00053 ///\ingroup containers 00054 //***************************************************************************** 00055 00056 namespace etl 00057 { 00058 //*************************************************************************** 00059 /// The base class for pool exceptions. 00060 ///\ingroup pool 00061 //*************************************************************************** 00062 class pool_exception : public exception 00063 { 00064 public: 00065 00066 pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_) 00067 : exception(reason_, file_name_, line_number_) 00068 {} 00069 }; 00070 00071 //*************************************************************************** 00072 /// The exception thrown when the pool has no more free items. 00073 ///\ingroup pool 00074 //*************************************************************************** 00075 class pool_no_allocation : public pool_exception 00076 { 00077 public: 00078 00079 explicit pool_no_allocation(string_type file_name_, numeric_type line_number_) 00080 : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name_, line_number_) 00081 {} 00082 }; 00083 00084 //*************************************************************************** 00085 /// The exception thrown when an object is released which does not belong to the pool. 00086 ///\ingroup pool 00087 //*************************************************************************** 00088 class pool_object_not_in_pool : public pool_exception 00089 { 00090 public: 00091 00092 pool_object_not_in_pool(string_type file_name_, numeric_type line_number_) 00093 : pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_FILE"B"), file_name_, line_number_) 00094 {} 00095 }; 00096 00097 //*************************************************************************** 00098 /// The exception thrown when an the type requested is larger than the element size. 00099 ///\ingroup pool 00100 //*************************************************************************** 00101 class pool_element_size : public pool_exception 00102 { 00103 public: 00104 00105 pool_element_size(string_type file_name_, numeric_type line_number_) 00106 : pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_FILE"C"), file_name_, line_number_) 00107 {} 00108 }; 00109 00110 //*************************************************************************** 00111 ///\ingroup pool 00112 //*************************************************************************** 00113 class ipool 00114 { 00115 public: 00116 00117 typedef size_t size_type; 00118 00119 //************************************************************************* 00120 /// Allocate an object from the pool. 00121 /// Uses the default constructor. 00122 /// If asserts or exceptions are enabled and there are no more free items an 00123 /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. 00124 //************************************************************************* 00125 template <typename T> 00126 T* allocate() 00127 { 00128 if (sizeof(T) > ITEM_SIZE) 00129 { 00130 ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size)); 00131 } 00132 00133 return reinterpret_cast<T*>(allocate_item()); 00134 } 00135 00136 //************************************************************************* 00137 /// Release an object in the pool. 00138 /// If asserts or exceptions are enabled and the object does not belong to this 00139 /// pool then an etl::pool_object_not_in_pool is thrown. 00140 /// \param p_object A pointer to the object to be released. 00141 //************************************************************************* 00142 void release(const void* p_object) 00143 { 00144 release_item((char*)p_object); 00145 } 00146 00147 //************************************************************************* 00148 /// Release all objects in the pool. 00149 //************************************************************************* 00150 void release_all() 00151 { 00152 items_allocated = 0; 00153 items_initialised = 0; 00154 p_next = p_buffer; 00155 } 00156 00157 //************************************************************************* 00158 /// Check to see if the object belongs to the pool. 00159 /// \param p_object A pointer to the object to be checked. 00160 /// \return <b>true<\b> if it does, otherwise <b>false</b> 00161 //************************************************************************* 00162 //template <typename T> 00163 bool is_in_pool(const void* p_object) const 00164 { 00165 return is_item_in_pool((const char*)p_object); 00166 } 00167 00168 //************************************************************************* 00169 /// Returns the maximum number of items in the pool. 00170 //************************************************************************* 00171 size_t max_size() const 00172 { 00173 return MAX_SIZE; 00174 } 00175 00176 //************************************************************************* 00177 /// Returns the number of free items in the pool. 00178 //************************************************************************* 00179 size_t available() const 00180 { 00181 return MAX_SIZE - items_allocated; 00182 } 00183 00184 //************************************************************************* 00185 /// Returns the number of allocated items in the pool. 00186 //************************************************************************* 00187 size_t size() const 00188 { 00189 return items_allocated; 00190 } 00191 00192 //************************************************************************* 00193 /// Checks to see if there are no allocated items in the pool. 00194 /// \return <b>true</b> if there are none allocated. 00195 //************************************************************************* 00196 bool empty() const 00197 { 00198 return items_allocated == 0; 00199 } 00200 00201 //************************************************************************* 00202 /// Checks to see if there are no free items in the pool. 00203 /// \return <b>true</b> if there are none free. 00204 //************************************************************************* 00205 bool full() const 00206 { 00207 return items_allocated == MAX_SIZE; 00208 } 00209 00210 protected: 00211 00212 //************************************************************************* 00213 /// Constructor 00214 //************************************************************************* 00215 ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_) 00216 : p_buffer(p_buffer_), 00217 p_next(p_buffer_), 00218 items_allocated(0), 00219 items_initialised(0), 00220 ITEM_SIZE(item_size_), 00221 MAX_SIZE(max_size_) 00222 { 00223 } 00224 00225 private: 00226 00227 //************************************************************************* 00228 /// Allocate an item from the pool. 00229 //************************************************************************* 00230 char* allocate_item() 00231 { 00232 char* p_value = std::nullptr; 00233 00234 // Any free space left? 00235 if (items_allocated < MAX_SIZE) 00236 { 00237 // Initialise another one if necessary. 00238 if (items_initialised < MAX_SIZE) 00239 { 00240 uintptr_t p = reinterpret_cast<uintptr_t>(p_buffer + (items_initialised * ITEM_SIZE)); 00241 *reinterpret_cast<uintptr_t*>(p) = p + ITEM_SIZE; 00242 ++items_initialised; 00243 } 00244 00245 // Get the address of new allocated item. 00246 p_value = p_next; 00247 00248 ++items_allocated; 00249 if (items_allocated != MAX_SIZE) 00250 { 00251 // Set up the pointer to the next free item 00252 p_next = *reinterpret_cast<char**>(p_next); 00253 } 00254 else 00255 { 00256 // No more left! 00257 p_next = std::nullptr; 00258 } 00259 } 00260 else 00261 { 00262 ETL_ASSERT(false, ETL_ERROR(etl::pool_no_allocation)); 00263 } 00264 00265 return p_value; 00266 } 00267 00268 //************************************************************************* 00269 /// Release an item back to the pool. 00270 //************************************************************************* 00271 void release_item(char* p_value) 00272 { 00273 // Does it belong to us? 00274 ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool)); 00275 00276 if (p_next != std::nullptr) 00277 { 00278 // Point it to the current free item. 00279 *(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next); 00280 } 00281 else 00282 { 00283 // This is the only free item. 00284 *((uintptr_t*)p_value) = 0; 00285 } 00286 00287 p_next = p_value; 00288 00289 --items_allocated; 00290 } 00291 00292 //************************************************************************* 00293 /// Check if the item belongs to this pool. 00294 //************************************************************************* 00295 bool is_item_in_pool(const char* p) const 00296 { 00297 // Within the range of the buffer? 00298 intptr_t distance = p - p_buffer; 00299 bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_SIZE) - ITEM_SIZE)); 00300 00301 // Modulus and division can be slow on some architectures, so only do this in debug. 00302 #if defined(ETL_DEBUG) 00303 // Is the address on a valid object boundary? 00304 bool is_valid_address = ((distance % ITEM_SIZE) == 0); 00305 #else 00306 bool is_valid_address = true; 00307 #endif 00308 00309 return is_within_range && is_valid_address; 00310 } 00311 00312 // Disable copy construction and assignment. 00313 ipool(const ipool&); 00314 ipool& operator =(const ipool&); 00315 00316 char* p_buffer; 00317 char* p_next; 00318 00319 uint32_t items_allocated; ///< The number of items allocated. 00320 uint32_t items_initialised; ///< The number of items initialised. 00321 00322 const uint32_t ITEM_SIZE; ///< The size of allocated items. 00323 const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated. 00324 }; 00325 00326 //************************************************************************* 00327 /// A templated pool implementation that uses a fixed size pool. 00328 ///\ingroup pool 00329 //************************************************************************* 00330 template <typename T, const size_t SIZE_> 00331 class pool : public etl::ipool 00332 { 00333 public: 00334 00335 static const size_t SIZE = SIZE_; 00336 00337 //************************************************************************* 00338 /// Constructor 00339 //************************************************************************* 00340 pool() 00341 : etl::ipool(reinterpret_cast<char*>(&buffer[0]), ELEMENT_SIZE, SIZE) 00342 { 00343 } 00344 00345 //************************************************************************* 00346 /// Allocate an object from the pool. 00347 /// Uses the default constructor. 00348 /// If asserts or exceptions are enabled and there are no more free items an 00349 /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. 00350 /// Static asserts if the specified type is too large for the pool. 00351 //************************************************************************* 00352 template <typename U> 00353 U* allocate() 00354 { 00355 STATIC_ASSERT(sizeof(U) <= ELEMENT_SIZE, "Type too large for pool"); 00356 return ipool::allocate<U>(); 00357 } 00358 00359 private: 00360 00361 // The pool element. 00362 union Element 00363 { 00364 uintptr_t next; ///< Pointer to the next free element. 00365 char value[sizeof(T)]; ///< Storage for value type. 00366 typename etl::type_with_alignment<etl::alignment_of<T>::value>::type dummy; ///< Dummy item to get correct alignment. 00367 }; 00368 00369 ///< The memory for the pool of objects. 00370 typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[SIZE]; 00371 00372 static const uint32_t ELEMENT_SIZE = sizeof(Element); 00373 00374 // Should not be copied. 00375 pool(const pool&); 00376 pool& operator =(const pool&); 00377 }; 00378 00379 //************************************************************************* 00380 /// A templated abstract pool implementation that uses a fixed size pool. 00381 ///\ingroup pool 00382 //************************************************************************* 00383 template <const size_t TYPE_SIZE_, const size_t ALIGNMENT_, const size_t SIZE_> 00384 class generic_pool : public etl::ipool 00385 { 00386 public: 00387 00388 static const size_t SIZE = SIZE_; 00389 static const size_t ALIGNMENT = ALIGNMENT_; 00390 static const size_t TYPE_SIZE = TYPE_SIZE_; 00391 00392 //************************************************************************* 00393 /// Constructor 00394 //************************************************************************* 00395 generic_pool() 00396 : etl::ipool(reinterpret_cast<char*>(&buffer[0]), ELEMENT_SIZE, SIZE) 00397 { 00398 } 00399 00400 //************************************************************************* 00401 /// Allocate an object from the pool. 00402 /// If asserts or exceptions are enabled and there are no more free items an 00403 /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. 00404 /// Static asserts if the specified type is too large for the pool. 00405 //************************************************************************* 00406 template <typename U> 00407 U* allocate() 00408 { 00409 STATIC_ASSERT(etl::alignment_of<U>::value <= ALIGNMENT_, "Type has incompatible alignment"); 00410 STATIC_ASSERT(sizeof(U) <= ELEMENT_SIZE, "Type too large for pool"); 00411 return ipool::allocate<U>(); 00412 } 00413 00414 private: 00415 00416 // The pool element. 00417 union Element 00418 { 00419 uintptr_t next; ///< Pointer to the next free element. 00420 char value[TYPE_SIZE_]; ///< Storage for value type. 00421 typename etl::type_with_alignment<ALIGNMENT_>::type dummy; ///< Dummy item to get correct alignment. 00422 }; 00423 00424 ///< The memory for the pool of objects. 00425 typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[SIZE]; 00426 00427 static const uint32_t ELEMENT_SIZE = sizeof(Element); 00428 00429 // Should not be copied. 00430 generic_pool(const generic_pool&); 00431 generic_pool& operator =(const generic_pool&); 00432 }; 00433 } 00434 00435 #undef ETL_FILE 00436 00437 #endif 00438 00439
Generated on Tue Jul 12 2022 14:05:43 by
