1 |
/* |
2 |
****************************************************************************** |
3 |
* * |
4 |
* COPYRIGHT ACcESS 2004 - All Rights Reserved * |
5 |
* * |
6 |
* This software is the property of ACcESS. No part of this code * |
7 |
* may be copied in any form or by any means without the expressed written * |
8 |
* consent of ACcESS. Copying, use or modification of this software * |
9 |
* by any unauthorised person is illegal unless that person has a software * |
10 |
* license agreement with ACcESS. * |
11 |
* * |
12 |
****************************************************************************** |
13 |
*/ |
14 |
|
15 |
#include "escript/Data/Taipan.h" |
16 |
|
17 |
#include <iostream> |
18 |
#include <cassert> |
19 |
#ifdef _OPENMP |
20 |
#include <omp.h> |
21 |
#endif |
22 |
|
23 |
using namespace std; |
24 |
|
25 |
namespace escript { |
26 |
|
27 |
Taipan::Taipan() : |
28 |
memTable_Root(0), |
29 |
totalElements(0) |
30 |
{ |
31 |
} |
32 |
|
33 |
Taipan::~Taipan() { |
34 |
|
35 |
Taipan_MemTable *tab; |
36 |
Taipan_MemTable *tab_next; |
37 |
|
38 |
// deallocate all managed arrays and the memTable |
39 |
tab = memTable_Root; |
40 |
while (tab != 0) { |
41 |
tab_next = tab->next; |
42 |
delete[] tab->array; |
43 |
delete tab; |
44 |
tab = tab_next; |
45 |
} |
46 |
|
47 |
// clear the MemTable root node |
48 |
memTable_Root = 0; |
49 |
|
50 |
// clear the totalElements counter |
51 |
totalElements = -1; |
52 |
} |
53 |
|
54 |
double* |
55 |
Taipan::new_array(int dim, int N) { |
56 |
|
57 |
assert(totalElements >= 0); |
58 |
|
59 |
int len = 0; |
60 |
|
61 |
#ifdef _OPENMP |
62 |
int numThreads = omp_get_num_threads(); |
63 |
#else |
64 |
int numThreads = 1; |
65 |
#endif |
66 |
|
67 |
Taipan_MemTable *tab; |
68 |
Taipan_MemTable *new_tab; |
69 |
Taipan_MemTable *tab_prev; |
70 |
|
71 |
// numThreads = omp_get_max_threads(); |
72 |
|
73 |
// is a suitable array already available? |
74 |
if (memTable_Root != 0) { |
75 |
tab = memTable_Root; |
76 |
while (tab != 0) { |
77 |
if (tab->dim == dim && |
78 |
tab->N == N && |
79 |
tab->free && |
80 |
tab->numThreads == numThreads) { |
81 |
tab->free = false; |
82 |
return tab->array; |
83 |
} |
84 |
tab_prev = tab; |
85 |
tab = tab->next; |
86 |
} |
87 |
} |
88 |
|
89 |
// |
90 |
// otherwise a new array must be allocated |
91 |
|
92 |
// create the corresponding memTable entry |
93 |
len = dim * N; |
94 |
new_tab = new Taipan_MemTable; |
95 |
new_tab->dim = dim; |
96 |
new_tab->N = N; |
97 |
new_tab->numThreads = numThreads; |
98 |
new_tab->free = false; |
99 |
new_tab->next = 0; |
100 |
if (memTable_Root == 0) { |
101 |
memTable_Root = new_tab; |
102 |
} else { |
103 |
tab_prev->next = new_tab; |
104 |
} |
105 |
|
106 |
// allocate and initialise the new array |
107 |
new_tab->array = new double[len]; |
108 |
int i,j; |
109 |
#pragma omp parallel for private(i,j) schedule(static) |
110 |
for (i=0; i<N; i++) { |
111 |
for (j=0; j<dim; j++) { |
112 |
new_tab->array[j+dim*i]=0.0; |
113 |
} |
114 |
} |
115 |
totalElements += len; |
116 |
|
117 |
return new_tab->array; |
118 |
} |
119 |
|
120 |
void |
121 |
Taipan::delete_array(double* array) { |
122 |
|
123 |
assert(totalElements >= 0); |
124 |
|
125 |
int N; |
126 |
int len = 0; |
127 |
bool found = false; |
128 |
|
129 |
Taipan_MemTable *tab; |
130 |
Taipan_MemTable *tab_next; |
131 |
Taipan_MemTable *tab_prev = 0; |
132 |
|
133 |
if (memTable_Root != 0) { |
134 |
|
135 |
// find the table entry for this array and mark it as free |
136 |
tab = memTable_Root; |
137 |
while (tab != 0) { |
138 |
if (tab->array == array) { |
139 |
N = tab->N; |
140 |
tab->free = true; |
141 |
found = true; |
142 |
break; |
143 |
} |
144 |
tab = tab->next; |
145 |
} |
146 |
if (!found) { |
147 |
// this wasn't an array under management, so quit now |
148 |
return; |
149 |
} |
150 |
|
151 |
// are there any N block arrays still in use? |
152 |
tab = memTable_Root; |
153 |
while (tab != 0) { |
154 |
if (tab->N==N && !tab->free) { |
155 |
return; |
156 |
} |
157 |
tab = tab->next; |
158 |
} |
159 |
|
160 |
// if not, all N block arrays are deallocated |
161 |
tab = memTable_Root; |
162 |
while (tab != 0) { |
163 |
tab_next = tab->next; |
164 |
if (tab->N == N) { |
165 |
delete[] tab->array; |
166 |
len += tab->dim * N; |
167 |
if (tab_prev != 0) { |
168 |
tab_prev->next = tab->next; |
169 |
} else { |
170 |
memTable_Root = tab->next; |
171 |
} |
172 |
delete tab; |
173 |
} else { |
174 |
tab_prev = tab; |
175 |
} |
176 |
tab = tab_next; |
177 |
} |
178 |
|
179 |
totalElements -= len; |
180 |
|
181 |
} else { |
182 |
// what to do if no arrays under management? |
183 |
} |
184 |
} |
185 |
|
186 |
int |
187 |
Taipan::num_arrays() { |
188 |
|
189 |
assert(totalElements >= 0); |
190 |
|
191 |
int num_arrays = 0; |
192 |
|
193 |
Taipan_MemTable *tab; |
194 |
|
195 |
// count all managed arrays in the memTable |
196 |
tab = memTable_Root; |
197 |
while (tab != 0) { |
198 |
num_arrays++; |
199 |
tab = tab->next; |
200 |
} |
201 |
|
202 |
return num_arrays; |
203 |
} |
204 |
|
205 |
int |
206 |
Taipan::num_arrays(int N) { |
207 |
|
208 |
assert(totalElements >= 0); |
209 |
|
210 |
int num_arrays = 0; |
211 |
|
212 |
Taipan_MemTable *tab; |
213 |
|
214 |
// count all managed arrays of N blocks in the memTable |
215 |
tab = memTable_Root; |
216 |
while (tab != 0) { |
217 |
if (tab->N == N) { |
218 |
num_arrays++; |
219 |
} |
220 |
tab = tab->next; |
221 |
} |
222 |
|
223 |
return num_arrays; |
224 |
} |
225 |
|
226 |
int |
227 |
Taipan::num_free(int N) { |
228 |
|
229 |
assert(totalElements >= 0); |
230 |
|
231 |
int num_free = 0; |
232 |
|
233 |
Taipan_MemTable *tab; |
234 |
|
235 |
// count all free managed arrays of N blocks in the memTable |
236 |
tab = memTable_Root; |
237 |
while (tab != 0) { |
238 |
if (tab->N == N) { |
239 |
if (tab->free) { |
240 |
num_free++; |
241 |
} |
242 |
} |
243 |
tab = tab->next; |
244 |
} |
245 |
|
246 |
return num_free; |
247 |
} |
248 |
|
249 |
long |
250 |
Taipan::num_elements() { |
251 |
assert(totalElements >= 0); |
252 |
return totalElements; |
253 |
} |
254 |
|
255 |
} // end of namespace |