-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStdPool.cpp
192 lines (150 loc) · 6.1 KB
/
StdPool.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include "StdFuncs.h"
#include "StdPool.h"
/* Written: Sunday 13-May-2012 2:18 pm, Lindau (Bodensee) */
/* @param a_iSize Size of items in the pool to be created */
/* a_iNumItems # of items that can be held in the pool */
/* a_bExtensible ETrue if the pool can be extended beyond its */
/* initial size, else EFalse */
/* @return KErrNone if successful */
/* KErrNoMemory if not enough memory was available */
/* KErrInUse if the Create() has already been called */
/* Initialises a pool that is large enough to contain a_iNumItems of */
/* size a_iSize. When requests are made from the pool for items, they */
/* will be returned from the pool and the pool will be automatically */
/* enlarged if required */
TInt RStdPool::Create(TInt a_iSize, TInt a_iNumItems, TBool a_bExtensible)
{
TInt RetVal;
ASSERTM((a_iSize >= (TInt) sizeof(CPoolNode)), "RStdPool::Create() => Node size is too small");
/* Initialise the pool if it has not already been initialised */
if (m_iSize == 0)
{
m_iSize = a_iSize;
m_iNumItems = a_iNumItems;
m_bExtensible = a_bExtensible;
/* Now allocate the initial set of a_iNumItems nodes */
RetVal = ExtendPool();
}
else
{
RetVal = KErrInUse;
Utils::info("RStdPool::Create() => Pool is already in use");
}
return(RetVal);
}
/* Written: Sunday 03-Jun-2012 11:27 am, on train to Munich Deutsches Museum */
/* @param a_bFreeNodes If ETrue then all nodes referring to the pool are explicitly */
/* freed, otherwise they are implicitly freed */
/* Frees the resources allocated by the class and makes it ready for use again. After */
/* this is called, the class is back to the state it was in when it had just been */
/* initialised - that is, the constructor had been called but *not* RStdPool::Create(). */
/* You should be careful with the use of the a_bFreeNodes parameter. This is provided */
/* mainly as an optimisation for clients that have a large number (ie. In the millions) */
/* of allocated nodes. If ETrue then each node will be explicitly freed from the internal */
/* list, thus affecting the result of the RStdPool::Count() function. If EFalse then the */
/* internal list will be forcibly reset, which is much faster. ETrue should only be used */
/* when testing and in debug builds, if you need to ensure that all nodes are freed for */
/* resource tracking purposes. Either way, you should not ever access the contents of a */
/* node allocated from a pool after RStdPool::Close() has been called, as its memory will */
/* have been freed and is now invalid. Once this function has returned, you can call */
/* RStdPool::Create() to reuse the pool if desired */
void RStdPool::close(TBool a_bFreeNodes)
{
CBufferNode *Buffer;
CPoolNode *Node;
/* If required, manually iterate through the list and free each and every */
/* node */
if (a_bFreeNodes)
{
while ((Node = m_oNodes.remHead()) != NULL) { }
}
/* Otherwise just hard reset the list back to its original state */
else
{
m_oNodes.Reset();
}
/* Free the buffers used by the pool for its nodes */
while ((Buffer = m_oBuffers.remHead()) != NULL)
{
delete [] (char *) Buffer;
}
/* And reset the other variables back to their defaults */
m_bExtensible = EFalse;
m_iNumItems = m_iSize = 0;
}
/* Written: Sunday 03-Jun-2012 11:20 pm, on train to Munich Deutsches Museum */
/* @return Ptr to the new node if successful, else NULL */
/* Allocates a node from the list of available nodes. This is a very fast operation */
/* as it simply returns the first node on the list of available nodes. If there are */
/* no nodes on the list and the pool is extensible, an attempt will be made to */
/* allocate further memory for nodes via the heap. If no memory could be allocated */
/* or if the pool was not extensible, NULL will be returned. To ensure fast allocation, */
/* the contents of the node are *not* cleared to zero */
void *RStdPool::GetNode()
{
CPoolNode *RetVal;
/* Get a ptr to the first available node */
RetVal = m_oNodes.getHead();
/* If there are none left and the pool is extendable, then try to allocate */
/* another block of nodes and then get a ptr to the first available new node */
if ((!(RetVal)) && (m_bExtensible))
{
if (ExtendPool() == KErrNone)
{
RetVal = m_oNodes.getHead();
}
}
/* If we obtained a node successfully then remove it from the list of available */
/* nodes as it is no longer available */
if (RetVal)
{
m_oNodes.remove(RetVal);
}
return(RetVal);
}
/* Written: Wednesday 24-Oct-2012 6:37 am, Vis à Vis Hotel, Lindau */
/* @param a_poNode Ptr to the node to be released back to the pool */
/* Releases a node previously allocated using RPool::GetNode() back into */
/* the pool, thus making it available for allocation again */
void RStdPool::ReleaseNode(void *a_poNode)
{
ASSERTM((a_poNode != NULL), "RStdPool::ReleaseNode() => Valid node must be passed in");
m_oNodes.addTail((CPoolNode *) a_poNode);
}
/* Written: Tuesday 31-Jul-2012 9:42 am, Starbucks Nürnberg */
/* @return KErrNone if successful, else KErrNoMemory */
/* Extends the pool by allocating a further m_iNumItems of nodes in a single */
/* allocation. The block is added to the list of blocks and the nodes are */
/* added to the list of nodes */
TInt RStdPool::ExtendPool()
{
char *Buffer;
TInt Index, RetVal;
CBufferNode *BufferNode;
CPoolNode *PoolNode;
/* Allocate a buffer large enough to hold the requested number of nodes */
/* of the requested size, plus one more which can be used to keep track */
/* of the block in the list of blocks */
if ((Buffer = new char[m_iSize * (m_iNumItems + 1)]) != NULL)
{
RetVal = KErrNone;
/* Make the first node into a CBufferNode and add it to the list of buffers */
BufferNode = (CBufferNode *) Buffer;
m_oBuffers.addTail(BufferNode);
Buffer += m_iSize;
/* For the remaining nodes in the buffer transform each one into a CPoolNode, */
/* and add it to the list of nodes */
for (Index = 0; Index < m_iNumItems; ++Index)
{
PoolNode = (CPoolNode *) Buffer;
m_oNodes.addTail(PoolNode);
Buffer += m_iSize;
}
}
else
{
RetVal = KErrNoMemory;
Utils::info("RStdPool::ExtendPool() => Out of memory");
}
return(RetVal);
}