diff options
| author | Neo2003 <none@none> | 2008-10-02 16:23:55 -0500 |
|---|---|---|
| committer | Neo2003 <none@none> | 2008-10-02 16:23:55 -0500 |
| commit | 9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch) | |
| tree | b5d1ba94a656e6679f8737f9ea6bed1239b73b14 /src/framework/Utilities/CountedReference | |
[svn] * Proper SVN structureinit
--HG--
branch : trunk
Diffstat (limited to 'src/framework/Utilities/CountedReference')
3 files changed, 266 insertions, 0 deletions
diff --git a/src/framework/Utilities/CountedReference/Reference.h b/src/framework/Utilities/CountedReference/Reference.h new file mode 100644 index 00000000000..581c6399a1b --- /dev/null +++ b/src/framework/Utilities/CountedReference/Reference.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCE_H +#define MANGOS_REFERENCE_H + +/** + * Referencer<T> + * Referencer is an object that holds a reference holder that hold a reference + * counted object. When an object's reference count drop to zero, it removes + * the object. This is a non intrusive mechanism and any object at any point + * in time can be referenced. When and object is reference counted, do not + * pass the object directly to other methods but rather, pass its + * reference around. Objects can be reference counted in both single threaded + * model and multi-threaded model + */ + +#include <stdexcept> +#include "Platform/Define.h" +#include "Policies/ThreadingModel.h" +#include "ReferenceHolder.h" + +template +< +typename T, +class THREADING_MODEL = MaNGOS::SingleThreaded<T> +> +class MANGOS_DLL_DECL Referencer +{ + typedef typename THREADING_MODEL::Lock Lock; + typedef ReferenceHolder<T, THREADING_MODEL> ReferenceeHolder; + public: + + /// Constructs a referencer. + Referencer(T *ref = NULL); + + /// Copy constructor + Referencer(const Referencer &obj) : i_holder(NULL) { *this = obj; } + + /// Destructor + ~Referencer(); + + /// Referencee accessor + T* referencee(void) { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T* referencee(void) const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + //T& referencee(void){ return _referencee(); } + //const T& referencee(void) const { return const_cast<Referencer *>(this)->_referencee(); } + operator T&(void) { return _referencee(); } + operator const T&(void) const { return *const_cast<Referencer *>(this)->_referencee(); } + + /// cast operators + T* operator*() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + T const * operator*() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// overload operators + T* operator->() { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + const T * operator->() const { return (i_holder == NULL ? NULL : i_holder->i_referencee); } + + /// operator = + Referencer& operator=(const Referencer &obj); + Referencer& operator=(T *); + + /// returns true if i_referencee is null + bool isNull(void) const { return i_holder == NULL; } + + private: + + T& _referencee(void) + { + if( i_holder == NULL ) + throw std::runtime_error("Invalid access to null pointer"); + return *i_holder->i_referencee; + } + + void deReference(ReferenceeHolder *); + void addReference(ReferenceeHolder *); + + // private data + ReferenceeHolder *i_holder; +}; +#endif diff --git a/src/framework/Utilities/CountedReference/ReferenceHolder.h b/src/framework/Utilities/CountedReference/ReferenceHolder.h new file mode 100644 index 00000000000..5387b14107a --- /dev/null +++ b/src/framework/Utilities/CountedReference/ReferenceHolder.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCEHOLDER_H +#define MANGOS_REFERENCEHOLDER_H + +/** ReferenceHolder holds the actualy referenced obejct as well the refence + count. The ReferenecHolder implements as a policy base object and + will decided by the Reference class to be consnsitent. + */ + +template +< +typename T, +class THREADING_MODEL +> +struct ReferenceHolder : public THREADING_MODEL +{ + explicit ReferenceHolder(T *ref) : i_referencee(ref), i_referenceCount(0) {} + T *i_referencee; + unsigned int i_referenceCount; + typedef typename THREADING_MODEL::Lock Lock; +}; +#endif diff --git a/src/framework/Utilities/CountedReference/ReferenceImpl.h b/src/framework/Utilities/CountedReference/ReferenceImpl.h new file mode 100644 index 00000000000..dffd05c52c4 --- /dev/null +++ b/src/framework/Utilities/CountedReference/ReferenceImpl.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_REFERENCEIMPL_H +#define MANGOS_REFERENCEIMPL_H + +#include "Reference.h" + +template +< +typename T, +class THREADING_MODEL +> +Referencer<T, THREADING_MODEL>::Referencer(T *ref) +: i_holder(NULL) +{ + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer<T, THREADING_MODEL>::~Referencer() +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer<T, THREADING_MODEL>& +Referencer<T, THREADING_MODEL>::operator=(const Referencer<T, THREADING_MODEL> &obj) +{ + if( i_holder != NULL ) + deReference(i_holder); + if( obj.i_holder != NULL ) + addReference(obj.i_holder); + i_holder = obj.i_holder; + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +Referencer<T, THREADING_MODEL>& +Referencer<T, THREADING_MODEL>::operator=(T *ref) +{ + if( i_holder != NULL ) + deReference(i_holder); + i_holder = NULL; + if( ref != NULL ) + { + i_holder = new ReferenceeHolder(ref); + ++i_holder->i_referenceCount; + } + + return *this; +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer<T, THREADING_MODEL>::deReference(ReferenceHolder<T, THREADING_MODEL> *holder) +{ + assert( holder != NULL && holder->i_referenceCount > 0); + bool delete_object = false; + + { + // The guard is within the scope due to the guard + // must release earlier than expected. + Lock guard(*holder); + Guard(&guard); + + --holder->i_referenceCount; + if( holder->i_referenceCount == 0 ) + delete_object = true; + } + + if( delete_object ) + { + delete holder->i_referencee; + delete holder; + } +} + +template +< +typename T, +class THREADING_MODEL +> +void +Referencer<T, THREADING_MODEL>::addReference(ReferenceHolder<T, THREADING_MODEL> *holder) +{ + assert( i_holder != NULL ); + Lock guard(*holder); + Guard(&guard); + + ++holder->i_referenceCount; +} +#endif |
