CGII/framework/include/cgv/data/ref_arr.h
2018-05-17 15:50:03 +02:00

109 lines
2.4 KiB
C++

#pragma once
#include <cgv/defines/assert.h>
#include <cgv/type/cond/is_base_of.h>
#include <cgv/type/cond/has_virtual_destructor.h>
namespace cgv {
/// namespace for data management components
namespace data {
template <typename T>
class ref_arr
{
private:
/// struct to store the array pointer with a count
struct counter_type
{
counter_type(T* a, int c) : arr(a), count(c) {}
T* arr;
int count;
};
/// store pointer to counter struct
counter_type* counter;
/// store pointer to array
T* arr;
/// decrement the count, delete if it is 0
void release()
{
if (counter) {
if (--counter->count == 0) {
delete [] counter->arr;
delete counter;
}
counter = 0;
}
arr = 0;
}
public:
/// construct reference counted pointer
explicit ref_arr(T* a = 0, counter_type* c = 0) : counter(c), arr(a) {
if (!c && a)
counter = new counter_type(a, 1);
}
/// copy construct from same pointer type and increment count
ref_arr(const ref_arr<T>& ra) : counter(ra.counter), arr(ra.arr)
{
if (counter)
++counter->count;
}
/// destruct reference counted pointer
~ref_arr() {
release();
}
/// assignment to pointer of same type
ref_arr<T>& operator = (const ref_arr<T>& ra) {
if (this == &ra)
return *this;
release();
new (this) ref_arr<T>(ra);
return *this;
}
/// return array pointer
T* ptr() const {
return arr;
}
/// access to element
T& operator*() const {
return *arr;
}
/// access to element pointer
T* operator->() const {
return arr;
}
/// access to i-th element
T& operator [] (int i) {
return arr[i];
}
/// return an array pointer pointing to the i-th element
ref_arr<T> operator () (int i) const {
return ref_arr<T>(arr+i,counter);
}
/// compare by pointer
bool operator == (const ref_arr<T>& ra) const {
return arr == ra.arr;
}
/// return current count
int get_count() const {
return counter ? counter->count : 0;
}
/// check if this is the only reference
bool unique() const {
return get_count() <= 1;
}
/// check if pointer is not yet set
bool empty() const {
return get_count() == 0;
}
/// conversion to bool results in false if the stored pointer is a null pointer
operator bool () const {
return !empty();
}
/// clear the array pointer
void clear() {
release();
}
};
}
}