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 * Represents an object pool. 58 * 59 * @tparam Type The object type. Type should provide `GetNext() and `SetNext()` so that it can be added to a 60 * linked list. 61 * @tparam kPoolSize Specifies the pool size (maximum number of objects in the pool). 62 */ 63 template <class Type, uint16_t kPoolSize> class Pool : private NonCopyable 64 { 65 public: 66 /** 67 * Initializes the pool. 68 */ Pool(void)69 Pool(void) 70 : mFreeList() 71 { 72 for (Type &entry : mPool) 73 { 74 mFreeList.Push(entry); 75 } 76 } 77 78 /** 79 * Initializes the pool. 80 * 81 * Version requires the `Type` class to provide method `void Init(Instance &)` to initialize 82 * each `Type` entry object. This can be realized by the `Type` class inheriting from `InstanceLocatorInit()`. 83 * 84 * @param[in] aInstance A reference to the OpenThread instance. 85 */ Pool(Instance & aInstance)86 explicit Pool(Instance &aInstance) 87 : mFreeList() 88 { 89 for (Type &entry : mPool) 90 { 91 entry.Init(aInstance); 92 mFreeList.Push(entry); 93 } 94 } 95 96 /** 97 * Allocates a new object from the pool. 98 * 99 * @returns A pointer to the newly allocated object, or `nullptr` if all entries from the pool are already 100 * allocated. 101 */ Allocate(void)102 Type *Allocate(void) { return mFreeList.Pop(); } 103 104 /** 105 * Frees a previously allocated object. 106 * 107 * The @p aEntry MUST be an entry from the pool previously allocated using `Allocate()` method and not yet freed. 108 * An already freed entry MUST not be freed again. 109 * 110 * @param[in] aEntry The pool object entry to free. 111 */ Free(Type & aEntry)112 void Free(Type &aEntry) { mFreeList.Push(aEntry); } 113 114 /** 115 * Frees all previously allocated objects. 116 */ FreeAll(void)117 void FreeAll(void) 118 { 119 mFreeList.Clear(); 120 121 for (Type &entry : mPool) 122 { 123 mFreeList.Push(entry); 124 } 125 } 126 127 /** 128 * Returns the pool size. 129 * 130 * @returns The pool size (maximum number of objects in the pool). 131 */ GetSize(void) const132 uint16_t GetSize(void) const { return kPoolSize; } 133 134 /** 135 * Indicates whether or not a given `Type` object is from the pool. 136 * 137 * @param[in] aObject A reference to a `Type` object. 138 * 139 * @retval TRUE if @p aObject is from the pool. 140 * @retval FALSE if @p aObject is not from the pool. 141 */ IsPoolEntry(const Type & aObject) const142 bool IsPoolEntry(const Type &aObject) const { return (&mPool[0] <= &aObject) && (&aObject < GetArrayEnd(mPool)); } 143 144 /** 145 * Returns the associated index of a given entry from the pool. 146 * 147 * The @p aEntry MUST be from the pool, otherwise the behavior of this method is undefined. 148 * 149 * @param[in] aEntry A reference to an entry from the pool. 150 * 151 * @returns The associated index of @p aEntry. 152 */ GetIndexOf(const Type & aEntry) const153 uint16_t GetIndexOf(const Type &aEntry) const { return static_cast<uint16_t>(&aEntry - mPool); } 154 155 /** 156 * Retrieves a pool entry at a given index. 157 * 158 * The @p aIndex MUST be from an earlier call to `GetIndexOf()`. 159 * 160 * @param[in] aIndex An index. 161 * 162 * @returns A reference to entry at index @p aIndex. 163 */ GetEntryAt(uint16_t aIndex)164 Type &GetEntryAt(uint16_t aIndex) { return mPool[aIndex]; } 165 166 /** 167 * Retrieves a pool entry at a given index. 168 * 169 * The @p aIndex MUST be from an earlier call to `GetIndexOf()`. 170 * 171 * @param[in] aIndex An index. 172 * 173 * @returns A reference to entry at index @p aIndex. 174 */ GetEntryAt(uint16_t aIndex) const175 const Type &GetEntryAt(uint16_t aIndex) const { return mPool[aIndex]; } 176 177 private: 178 LinkedList<Type> mFreeList; 179 Type mPool[kPoolSize]; 180 }; 181 182 /** 183 * @} 184 */ 185 186 } // namespace ot 187 188 #endif // POOL_HPP_ 189