1 /* 2 * Copyright (c) 2020, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file includes definitions for a generic object pool. 32 */ 33 34 #ifndef POOL_HPP_ 35 #define POOL_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/array.hpp" 40 #include "common/linked_list.hpp" 41 #include "common/non_copyable.hpp" 42 43 namespace ot { 44 45 class Instance; 46 47 /** 48 * @addtogroup core-pool 49 * 50 * @brief 51 * This module includes definitions for OpenThread object pool. 52 * 53 * @{ 54 * 55 */ 56 57 /** 58 * This template class represents an object pool. 59 * 60 * @tparam Type The object type. Type should provide `GetNext() and `SetNext()` so that it can be added to a 61 * linked list. 62 * @tparam kPoolSize Specifies the pool size (maximum number of objects in the pool). 63 * 64 */ 65 template <class Type, uint16_t kPoolSize> class Pool : private NonCopyable 66 { 67 public: 68 /** 69 * This constructor initializes the pool. 70 * 71 */ Pool(void)72 Pool(void) 73 : mFreeList() 74 { 75 for (Type &entry : mPool) 76 { 77 mFreeList.Push(entry); 78 } 79 } 80 81 /** 82 * This constructor initializes the pool. 83 * 84 * This constructor version requires the `Type` class to provide method `void Init(Instance &)` to initialize 85 * each `Type` entry object. This can be realized by the `Type` class inheriting from `InstanceLocatorInit()`. 86 * 87 * @param[in] aInstance A reference to the OpenThread instance. 88 * 89 */ Pool(Instance & aInstance)90 explicit Pool(Instance &aInstance) 91 : mFreeList() 92 { 93 for (Type &entry : mPool) 94 { 95 entry.Init(aInstance); 96 mFreeList.Push(entry); 97 } 98 } 99 100 /** 101 * This method allocates a new object from the pool. 102 * 103 * @returns A pointer to the newly allocated object, or `nullptr` if all entries from the pool are already 104 * allocated. 105 * 106 */ Allocate(void)107 Type *Allocate(void) { return mFreeList.Pop(); } 108 109 /** 110 * This method frees a previously allocated object. 111 * 112 * The @p aEntry MUST be an entry from the pool previously allocated using `Allocate()` method and not yet freed. 113 * An already freed entry MUST not be freed again. 114 * 115 * @param[in] aEntry The pool object entry to free. 116 * 117 */ Free(Type & aEntry)118 void Free(Type &aEntry) { mFreeList.Push(aEntry); } 119 120 /** 121 * This method frees all previously allocated objects. 122 * 123 */ FreeAll(void)124 void FreeAll(void) 125 { 126 mFreeList.Clear(); 127 128 for (Type &entry : mPool) 129 { 130 mFreeList.Push(entry); 131 } 132 } 133 134 /** 135 * This method returns the pool size. 136 * 137 * @returns The pool size (maximum number of objects in the pool). 138 * 139 */ GetSize(void) const140 uint16_t GetSize(void) const { return kPoolSize; } 141 142 /** 143 * This method indicates whether or not a given `Type` object is from the pool. 144 * 145 * @param[in] aObject A reference to a `Type` object. 146 * 147 * @retval TRUE if @p aObject is from the pool. 148 * @retval FALSE if @p aObject is not from the pool. 149 * 150 */ IsPoolEntry(const Type & aObject) const151 bool IsPoolEntry(const Type &aObject) const { return (&mPool[0] <= &aObject) && (&aObject < GetArrayEnd(mPool)); } 152 153 /** 154 * This method returns the associated index of a given entry from the pool. 155 * 156 * The @p aEntry MUST be from the pool, otherwise the behavior of this method is undefined. 157 * 158 * @param[in] aEntry A reference to an entry from the pool. 159 * 160 * @returns The associated index of @p aEntry. 161 * 162 */ GetIndexOf(const Type & aEntry) const163 uint16_t GetIndexOf(const Type &aEntry) const { return static_cast<uint16_t>(&aEntry - mPool); } 164 165 /** 166 * This method retrieves a pool entry at a given index. 167 * 168 * The @p aIndex MUST be from an earlier call to `GetIndexOf()`. 169 * 170 * @param[in] aIndex An index. 171 * 172 * @returns A reference to entry at index @p aIndex. 173 * 174 */ GetEntryAt(uint16_t aIndex)175 Type &GetEntryAt(uint16_t aIndex) { return mPool[aIndex]; } 176 177 /** 178 * This method retrieves a pool entry at a given index. 179 * 180 * The @p aIndex MUST be from an earlier call to `GetIndexOf()`. 181 * 182 * @param[in] aIndex An index. 183 * 184 * @returns A reference to entry at index @p aIndex. 185 * 186 */ GetEntryAt(uint16_t aIndex) const187 const Type &GetEntryAt(uint16_t aIndex) const { return mPool[aIndex]; } 188 189 private: 190 LinkedList<Type> mFreeList; 191 Type mPool[kPoolSize]; 192 }; 193 194 /** 195 * @} 196 * 197 */ 198 199 } // namespace ot 200 201 #endif // POOL_HPP_ 202