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