299 lines
7.2 KiB
C++
299 lines
7.2 KiB
C++
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_REFERENCE_COUNTER_KERNEl_1_
|
|
#define DLIB_REFERENCE_COUNTER_KERNEl_1_
|
|
|
|
#include "reference_counter_kernel_abstract.h"
|
|
#include "../algs.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
template <
|
|
typename T,
|
|
typename copy = copy_functor<T>
|
|
>
|
|
class reference_counter_kernel_1
|
|
{
|
|
|
|
/*!
|
|
INITIAL VALUE
|
|
*data = item of type T with its initial value
|
|
*count = 1
|
|
|
|
CONVENTION
|
|
*data = pointer to item of type T
|
|
*count = number of references to *data
|
|
|
|
if clear() threw an exception then count = 0 and data is not a
|
|
valid pointer
|
|
!*/
|
|
|
|
public:
|
|
|
|
typedef T type;
|
|
|
|
|
|
reference_counter_kernel_1 (
|
|
);
|
|
|
|
inline reference_counter_kernel_1 (
|
|
const reference_counter_kernel_1& item
|
|
);
|
|
|
|
virtual ~reference_counter_kernel_1 (
|
|
);
|
|
|
|
void clear (
|
|
);
|
|
|
|
T& modify (
|
|
);
|
|
|
|
inline const T& access (
|
|
) const;
|
|
|
|
inline reference_counter_kernel_1& operator= (
|
|
const reference_counter_kernel_1& rhs
|
|
);
|
|
|
|
inline void swap (
|
|
reference_counter_kernel_1& item
|
|
);
|
|
|
|
|
|
private:
|
|
|
|
T* data;
|
|
unsigned long* count;
|
|
mutable copy copy_item;
|
|
};
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
inline void swap (
|
|
reference_counter_kernel_1<T,copy>& a,
|
|
reference_counter_kernel_1<T,copy>& b
|
|
) { a.swap(b); }
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// member function definitions
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
reference_counter_kernel_1<T,copy>::
|
|
reference_counter_kernel_1 (
|
|
)
|
|
{
|
|
data = new T;
|
|
try { count = new unsigned long; }
|
|
catch (...) { delete data; throw; }
|
|
|
|
*count = 1;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
reference_counter_kernel_1<T,copy>::
|
|
reference_counter_kernel_1 (
|
|
const reference_counter_kernel_1<T,copy>& item
|
|
) :
|
|
data(item.data),
|
|
count(item.count)
|
|
{
|
|
++(*count);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
reference_counter_kernel_1<T,copy>::
|
|
~reference_counter_kernel_1 (
|
|
)
|
|
{
|
|
if (*count > 1)
|
|
{
|
|
// if there are other references to this data
|
|
--(*count);
|
|
}
|
|
else
|
|
{
|
|
// if there are no other references to this data
|
|
delete count;
|
|
delete data;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
void reference_counter_kernel_1<T,copy>::
|
|
clear (
|
|
)
|
|
{
|
|
// if an exception was thrown last time clear() was called then do this
|
|
if (count == 0)
|
|
{
|
|
data = new T;
|
|
try { count = new unsigned long; }
|
|
catch (...) { delete data; throw; }
|
|
|
|
*count = 1;
|
|
}
|
|
// if there are other references to the data then do this
|
|
else if (*count > 1)
|
|
{
|
|
--(*count);
|
|
|
|
try { data = new T; }
|
|
catch (...) { count = 0; throw; }
|
|
|
|
try { count = new unsigned long; }
|
|
catch (...) { delete data; count = 0; throw; }
|
|
|
|
*count = 1;
|
|
|
|
}
|
|
else
|
|
{
|
|
// if there are no other references to this data
|
|
*count = 1;
|
|
delete data;
|
|
try { data = new T; } catch (...) { delete count; count = 0; throw; }
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
T& reference_counter_kernel_1<T,copy>::
|
|
modify (
|
|
)
|
|
{
|
|
// if this is not the only reference then make a new copy
|
|
if ( *count > 1 )
|
|
{
|
|
T& old_data = *data;
|
|
unsigned long& old_count = *count;
|
|
|
|
|
|
// get memory for the new copy
|
|
try { data = new T; }
|
|
catch (...) { data = &old_data; throw; }
|
|
|
|
try { count = new unsigned long; }
|
|
catch (...) {delete data; data = &old_data; count = &old_count; throw;}
|
|
|
|
// decrement the number of references to old_data
|
|
--(old_count);
|
|
|
|
*count = 1;
|
|
|
|
// make a copy of the old data
|
|
try { copy_item(old_data,*data); }
|
|
catch (...)
|
|
{ delete data; delete count; data = &old_data; count = &old_count; }
|
|
|
|
}
|
|
|
|
return *data;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
const T& reference_counter_kernel_1<T,copy>::
|
|
access (
|
|
) const
|
|
{
|
|
return *data;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
reference_counter_kernel_1<T,copy>& reference_counter_kernel_1<T,copy>::
|
|
operator= (
|
|
const reference_counter_kernel_1<T,copy>& rhs
|
|
)
|
|
{
|
|
if (this == &rhs)
|
|
return *this;
|
|
|
|
// delete the current data if this is the last reference to it
|
|
if (*count > 1)
|
|
{
|
|
// if there are other references to this data
|
|
--(*count);
|
|
}
|
|
else
|
|
{
|
|
// if there are no other references to this data
|
|
delete count;
|
|
delete data;
|
|
}
|
|
|
|
// copy the pointers
|
|
count = (rhs.count);
|
|
data = (rhs.data);
|
|
++(*count);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename T,
|
|
typename copy
|
|
>
|
|
void reference_counter_kernel_1<T,copy>::
|
|
swap (
|
|
reference_counter_kernel_1<T,copy>& item
|
|
)
|
|
{
|
|
T* data_temp = data;
|
|
unsigned long* count_temp = count;
|
|
|
|
data = item.data;
|
|
count = item.count;
|
|
|
|
item.data = data_temp;
|
|
item.count = count_temp;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_REFERENCE_COUNTER_KERNEl_1_
|
|
|