📄 smartptr.h
字号:
/*! \file SmartPtr.h
\brief This file contains declaration and implementation of template classes and datatypes that handles smart pointers used by the library.
*/
/*
*
* website: http://www.coolsoft-sd.com/
* contact: support@coolsoft-sd.com
*
*/
/*
* Genetic Algorithm Library
* Copyright (C) 2007-2008 Coolsoft Software Development
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __GA_SMART_PTR_H__
#define __GA_SMART_PTR_H__
#include "Platform.h"
#include "Threading.h"
namespace Common
{
template <typename T>
class GaSmartPtr;
/// <summary><c>GaSmartStorage</c> template class provides reference-counting for smart pointers.
/// <c>GaSmartStorage</c> objects holds address of used data and number of references (smart pointers) which point to the data.
/// Object of this class as well as the data are destroyed and memory is freed when there are no more references which points to the data.
/// Arrays cannot be used with this class. This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros
/// cannot be used with instances of this class, but all public method and operators are thread-safe. </summary>
template <typename T>
class GaSmartStorage
{
friend class GaSmartPtr<T>;
private:
/// <summary>Holds number of references (smart pointers) to data guarded by this object.</summary>
mutable int _count;
/// <summary>Pointer to user data.</summary>
T* _data;
public:
/// <summary><c>MakeInstance</c> makes new reference-counting object for data at address data. This method is thread-safe.</summary>
/// <param name="data">pointer to data. <c>data</c> cannot be an array.</param>
/// <returns>Method returns smart pointer which points to data and use newly created object for reference-counting.</returns>
static GaSmartPtr<T> GACALL MakeInstance(T* data) { return GaSmartPtr<T>( new GaSmartStorage<T>( data ) ); }
/// <summary><c>MakeInstance</c> makes new reference-counting object for data at address data. This method is thread-safe.</summary>
/// <param name="data">pointer to data. <c>data</c> cannot be an array.</param>
/// <returns>Method returns reference to newly created object for reference-counting.</returns>
static GaSmartStorage<T>* GACALL MakeInstanceDirect(T* data) { return new GaSmartStorage<T>( data ); }
// Increase count of references which point to this location
/// <summary>This method increments number of references to the data. <c>AddReference</c> method is called when smart pointer
/// is set to point to the location. This method is thread-safe.</summary>
/// <param name="location">pointer to location which is incremented.</param>
/// <returns>Method returns new number of references which still points to the data.</returns>
static int GACALL AddReference(GaSmartStorage<T>* location) { return location ? ATOMIC_INC( location->_count ) : 0; }
// Decrease count of references which point to this location
/// <summary>This method decrements number of references, if that number reaches 0, the data is destroyed and memory is freed.
/// <c>RemoveReference</c> method is called when smart pointers are destructed or when set to point to new location.
/// This method is thread-safe.</summary>
/// <param name="location">pointer to location which is decremented.</param>
/// <returns>Method returns new number of references which still points to the data.</returns>
static int GACALL RemoveReference(GaSmartStorage<T>* location)
{
if( location )
{
int new_count = ATOMIC_DEC( location->_count );
// no more references?
if( !new_count )
delete location;
return new_count;
}
return 0;
}
/// <summary>Initializes object for counting references to data located at <c>data</c> address. </summary>
/// <param name="data">pointer to user data. <c>data</c> cannot be an array.</param>
GaSmartStorage(T* data) : _count(0),
_data(data) { }
/// <summary>Destructor is called when there are no more references which points to the data. Destructor frees memory used by the data. </summary>
~GaSmartStorage()
{
if( _data )
delete _data;
}
/// <summary>This method is thread-safe.</summary>
/// <returns>Method returns pointer to user data.</returns>
inline T* GACALL GetData() const { return _data; }
/// <summary>This method is thread-safe.</summary>
/// <returns>Method returns number of references (smart pointers) which points to this location.</returns>
inline int GACALL GetCount() const { return _count; }
};// END CLASS DEFINITION GaSmartStorage
/// <summary><c>GaSmartPtr</c> template class wraps C++ raw pointers, and takes over responsibility of managing the allocated memory.
/// Smart pointer holds address of user data and reference to an object which is responsible for counting number of references to data,
/// when there are no instances of <c>GaSmartPtr</c> pointing to location of the data (reference count of the location reaches 0),
/// object is destroyed and memory used by the object is freed. Memory management by <c>GaSmartPtr</c> class is thread-safe,
/// but after dereferencing smart pointer to access the data, it cannot be guaranteed that memory will not be freed if some other thread
/// changes dereferenced pointer. Implemented smart pointers have some limitations:
/// <br>1. Dynamically allocated arrays cannot be managed by GaSmartPtr class.
/// <br>2. Circular references can cause memory leakage.
///
/// This class has no built-in synchronizator, so <c>LOCK_OBJECT</c> and <c>LOCK_THIS_OBJECT</c> macros cannot be used with instances of
/// this class, but all public method and operators are thread-safe.</summary>
/// <param name="T">type of data to which smart pointer references.</param>
template <typename T>
class GaSmartPtr
{
private:
/// <summary>Guards smart pointer against concurrent changes.</summary>
mutable volatile unsigned long _lock;
/// <summary>Holds address of user data.</summary>
T* _data;
/// <summary>Pointer to object which holds reference-count and address of data.</summary>
GaSmartStorage<T>* _location;
public:
/// <summary>This constructor makes new reference to data that are managed by <see cref="GaSmertStorage" />.
/// Creation of smart pointer and counting of references is thread-safe.</summary>
/// <param name="storage">reference to object responsible for reference-counting.</param>
GaSmartPtr(GaSmartStorage<T>* storage) : _lock(0)
{
Lock();
// add new reference to smart location
GaSmartStorage<T>::AddReference( storage );
_location = storage;
_data = _location ? _location->_data : NULL;
Unlock();
}
/// <summary>This constructor make instance of <see cref="GaSmartStorage" /> and binds unmanaged memory to the smart storage.
/// If the given memory is already managed by this mechanism, it can cause unexpected results.
/// Creation of smart pointer and counting of references is thread-safe.</summary>
/// <param name="rawPtr">raw pointer to data.</param>
GaSmartPtr(T* rawPtr) : _lock(0)
{
Lock();
GaSmartStorage<T>* location = GaSmartStorage<T>::MakeInstanceDirect( rawPtr );
// add new reference to smart location
GaSmartStorage<T>::AddReference( location );
_location = location;
_data = _location ? _location->_data : NULL;
Unlock();
}
/// <summary>Copy constructor makes new reference to data to which <c>ptr</c> points.
/// Creation of smart pointer and counting of references is thread-safe.</summary>
/// <param name="ptr">reference to smart pointer which should be copied.</param>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -