diff options
Diffstat (limited to '')
-rw-r--r-- | ml/dlib/dlib/reference_counter/reference_counter_kernel_1.h | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/ml/dlib/dlib/reference_counter/reference_counter_kernel_1.h b/ml/dlib/dlib/reference_counter/reference_counter_kernel_1.h new file mode 100644 index 000000000..64e465550 --- /dev/null +++ b/ml/dlib/dlib/reference_counter/reference_counter_kernel_1.h @@ -0,0 +1,298 @@ +// 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_ + |