PSCF v1.4.0
DRArray.h
1#ifndef UTIL_DR_ARRAY_H
2#define UTIL_DR_ARRAY_H
3
4/*
5* Util Package - C++ Utilities for Scientific Computation
6*
7* Copyright 2010 - 2017, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include <util/containers/Array.h> // base class
12#include <util/misc/ReferenceCounter.h> // member
13#include <util/misc/CountedReference.h> // member
14#include <util/global.h>
15
16namespace Util {
17
72 template <typename Data>
73 class DRArray : public Array<Data>
74 {
75
76 public:
77
82
91
97 DRArray(DRArray<Data> const & other);
98
109
126
142 DRArray<Data>& operator = (Array<Data> const & other);
143
157
167
182 void associate(DRArray<Data>& arr, int beginId, int capacity);
183
193
201 bool isAllocated() const;
202
210 bool isOwner() const;
211
217 bool isAssociated() const;
218
219 protected:
220
221 using Array<Data>::data_;
222 using Array<Data>::capacity_;
223
226
229
230 };
231
232 // Inline member function definitions
233
234 /*
235 * Does this DRArray have data (either owned or associated) ?
236 */
237 template <typename Data> inline
239 { return (bool)data_; }
240
241 /*
242 * Does this object own data?
243 */
244 template <typename Data> inline
246 { return ((bool) data_ && !ref_.isAssociated()); }
247
248 /*
249 * Does this object reference data that it does not own?
250 */
251 template <typename Data> inline
253 { return ((bool) data_ && ref_.isAssociated()); }
254
255 // Non-inline member function definitions
256
257 /*
258 * Default constructor.
259 */
260 template <typename Data>
262 : Array<Data>()
263 {}
264
265 /*
266 * Allocating constructor.
267 */
268 template <typename Data>
270 : Array<Data>()
271 { allocate(capacity); }
272
273 /*
274 * Copy constructor.
275 */
276 template <typename Data>
278 : Array<Data>()
279 {
280 if (!other.isAllocated()) {
281 UTIL_THROW("Other DRArray must be allocated.");
282 }
283 allocate(other.capacity_);
284 for (int i = 0; i < capacity_; ++i) {
285 data_[i] = other.data_[i];
286 }
287 }
288
289 /*
290 * Destructor.
291 */
292 template <typename Data>
294 {
295 if (data_) {
296 if (ref_.isAssociated()) {
297 ref_.dissociate();
298 } else {
299 if (refCounter_.hasRefs()) {
300 int nRef = refCounter_.nRef();
301 std::cout
302 << std::endl
303 << "Error: Destroying a DRArray that is referenced by "
304 << nRef << " other(s)" << std::endl;
305 }
307 }
308 }
309 data_ = nullptr;
310 capacity_ = 0;
311 }
312
313 /*
314 * Assignment from another DRArray<Data> (deep copy).
315 */
316 template <typename Data>
318 {
319 // Check for self assignment
320 if (this == &other) return *this;
321
322 // Precondition - other array must be allocated
323 UTIL_CHECK (other.isAllocated());
324
325 // If this is not allocated, then allocate
326 if (!isAllocated()) {
327 allocate(other.capacity());
328 }
329
330 // Copy elements
332 for (int i = 0; i < capacity_; ++i) {
333 data_[i] = other[i];
334 }
335
336 return *this;
337 }
338
339 /*
340 * Assignment from an Array<Data> (deep copy).
341 */
342 template <typename Data>
343 DRArray<Data>& DRArray<Data>::operator = (Array<Data> const & other)
344 {
345 // Check for self assignment
346 if (dynamic_cast< Array<Data>* >(this) == &other) return *this;
347
348 // Precondition - other array must be allocated
349 UTIL_CHECK(other.capacity() > 0);
350
351 // If this is not allocated, then allocate
352 if (!isAllocated()) {
353 allocate(other.capacity());
354 }
355
356 // Copy elements
357 UTIL_CHECK(capacity_ == other.capacity());
358 for (int i = 0; i < capacity_; ++i) {
359 data_[i] = other[i];
360 }
361
362 return *this;
363 }
364
365 /*
366 * Allocate an underlying C array, which this container then owns.
367 */
368 template <typename Data>
370 {
371 if (capacity <= 0) {
372 UTIL_THROW("Attempt to allocate with capacity <= 0");
373 }
374 if (isAllocated()) {
375 UTIL_THROW("Attempt to allocate a DRArray that already has data.");
376 }
379 }
380
381 /*
382 * Deallocate a C array that is owned by this container.
383 */
384 template <typename Data>
386 {
388 UTIL_CHECK(!ref_.isAssociated());
390 capacity_ = 0;
391 UTIL_CHECK(!refCounter_.hasRefs());
392 }
393
394 /*
395 * Associate this object with a slice of a different DRArray.
396 */
397 template <typename Data>
399 int beginId, int capacity)
400 {
401 UTIL_CHECK(owner.isAllocated());
402 UTIL_CHECK(owner.isOwner());
403 UTIL_CHECK(beginId >= 0);
404 UTIL_CHECK(capacity > 0);
405 UTIL_CHECK(beginId + capacity <= owner.capacity());
407 UTIL_CHECK(!ref_.isAssociated());
408
409 // Copy data pointer and capacity
410 data_ = owner.cArray() + beginId;
412
413 // Associate private ReferencecCounter of the data owner with the
414 // CountedReference ref_ member variable of this data user.
415 ref_.associate(owner.refCounter_);
416
417 // On exit from CountedReference::associate, the ReferenceCounter
418 // is incremented and the CountedReference has a pointer to the
419 // ReferenceCounter.
420 }
421
422 /*
423 * Dissociate this object from array sliced owned by another object.
424 */
425 template <typename Data>
427 {
429 UTIL_CHECK(ref_.isAssociated());
430
431 data_ = nullptr;
432 capacity_ = 0;
433 ref_.dissociate();
434 }
435
436} // namespace Util
437#endif
Data * cArray()
Return a pointer to the underlying C array.
Definition Array.h:199
int capacity() const
Definition Array.h:144
Reference to a shared resource.
void allocate(int capacity)
Allocate an underlying C array, which this container then owns.
Definition DRArray.h:369
void associate(DRArray< Data > &arr, int beginId, int capacity)
Associate this object with a slice of a different DRArray.
Definition DRArray.h:398
DRArray()
Default constructor.
Definition DRArray.h:261
bool isOwner() const
Does this container own a dynamically allocated C array?
Definition DRArray.h:245
~DRArray()
Destructor.
Definition DRArray.h:293
DRArray< Data > & operator=(DRArray< Data > const &other)
Assignment from another DRArray<Data> container.
Definition DRArray.h:317
bool isAssociated() const
Is this container associated with a C array it does not own?
Definition DRArray.h:252
CountedReference ref_
Definition DRArray.h:228
DRArray(DRArray< Data > const &other)
Copy constructor.
Definition DRArray.h:277
ReferenceCounter refCounter_
Definition DRArray.h:225
void deallocate()
Dellocate an underlying C array that is owned by this container.
Definition DRArray.h:385
DRArray(int capacity)
Allocating constructor.
Definition DRArray.h:269
void dissociate()
Dissociate this object from an externally owned array slice.
Definition DRArray.h:426
bool isAllocated() const
Return true if this container has data, false otherwise.
Definition DRArray.h:238
static void deallocate(Data *&ptr, size_t size)
Deallocate a C++ array.
Definition Memory.h:157
static void allocate(Data *&ptr, size_t size)
Allocate a C++ array.
Definition Memory.h:136
Reference counter.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
Utility classes for scientific computation.