From 49d57e3155fc21825c6f2da400317f74e38a3307 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 10 Mar 2015 08:40:31 +0000 Subject: [PATCH] added SharedPtr and MmgedSharedPtr --- qse/include/qse/Makefile.am | 2 +- qse/include/qse/Makefile.in | 4 +- qse/include/qse/RefCounted.hpp | 2 +- qse/include/qse/ScopedPtr.hpp | 6 +- qse/include/qse/SharedPtr.hpp | 165 +++++++++++++++++++++++ qse/include/qse/cmn/Array.hpp | 13 +- qse/include/qse/cmn/BinaryHeap.hpp | 5 +- qse/include/qse/cmn/HashList.hpp | 35 ++--- qse/include/qse/cmn/HashTable.hpp | 5 +- qse/include/qse/cmn/LinkedList.hpp | 11 +- qse/include/qse/cmn/Makefile.am | 2 +- qse/include/qse/cmn/Makefile.in | 8 +- qse/include/qse/cmn/MmgedSharedPtr.hpp | 173 +++++++++++++++++++++++++ qse/include/qse/cmn/Mmgr.hpp | 21 +++ qse/include/qse/cmn/RedBlackTable.hpp | 5 +- qse/include/qse/cmn/RedBlackTree.hpp | 17 ++- 16 files changed, 427 insertions(+), 47 deletions(-) create mode 100644 qse/include/qse/SharedPtr.hpp create mode 100644 qse/include/qse/cmn/MmgedSharedPtr.hpp diff --git a/qse/include/qse/Makefile.am b/qse/include/qse/Makefile.am index 897a9aeb..7a30bc5a 100644 --- a/qse/include/qse/Makefile.am +++ b/qse/include/qse/Makefile.am @@ -9,7 +9,7 @@ pkginclude_HEADERS = \ if ENABLE_CXX pkginclude_HEADERS += \ Types.hpp Hashable.hpp Uncopyable.hpp RefCounted.hpp \ - ScopedPtr.hpp Exception.hpp + ScopedPtr.hpp SharedPtr.hpp Exception.hpp endif install-data-hook: diff --git a/qse/include/qse/Makefile.in b/qse/include/qse/Makefile.in index 279625c7..970f268d 100644 --- a/qse/include/qse/Makefile.in +++ b/qse/include/qse/Makefile.in @@ -52,7 +52,7 @@ build_triplet = @build@ host_triplet = @host@ @ENABLE_CXX_TRUE@am__append_1 = \ @ENABLE_CXX_TRUE@ Types.hpp Hashable.hpp Uncopyable.hpp RefCounted.hpp \ -@ENABLE_CXX_TRUE@ ScopedPtr.hpp Exception.hpp +@ENABLE_CXX_TRUE@ ScopedPtr.hpp SharedPtr.hpp Exception.hpp subdir = include/qse DIST_COMMON = $(am__pkginclude_HEADERS_DIST) $(srcdir)/Makefile.am \ @@ -95,7 +95,7 @@ am__can_run_installinfo = \ am__pkginclude_HEADERS_DIST = conf-msw.h conf-os2.h conf-dos.h \ conf-vms.h conf-mac.h conf-inf.h types.h macros.h pack1.h \ unpack.h Types.hpp Hashable.hpp Uncopyable.hpp RefCounted.hpp \ - ScopedPtr.hpp Exception.hpp + ScopedPtr.hpp SharedPtr.hpp Exception.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ diff --git a/qse/include/qse/RefCounted.hpp b/qse/include/qse/RefCounted.hpp index 05103295..775ec642 100644 --- a/qse/include/qse/RefCounted.hpp +++ b/qse/include/qse/RefCounted.hpp @@ -57,7 +57,7 @@ public: if (--this->ref_count == 0 && kill) delete this; } - qse_size_t count () const + qse_size_t getRefCount () const { return this->ref_count; } diff --git a/qse/include/qse/ScopedPtr.hpp b/qse/include/qse/ScopedPtr.hpp index ec2c4fd4..785e0502 100644 --- a/qse/include/qse/ScopedPtr.hpp +++ b/qse/include/qse/ScopedPtr.hpp @@ -97,12 +97,12 @@ template > class QSE_EXPORT ScopedPtr: public Uncopyable { public: + typedef SharedPtr SelfType; + typedef ScopedPtrDeleter DefaultDeleter; - ScopedPtr (T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL) + ScopedPtr (T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL): _ptr (ptr), _darg (darg) { - this->_ptr = ptr; - this->_darg = darg; } ~ScopedPtr () diff --git a/qse/include/qse/SharedPtr.hpp b/qse/include/qse/SharedPtr.hpp new file mode 100644 index 00000000..81cbaf22 --- /dev/null +++ b/qse/include/qse/SharedPtr.hpp @@ -0,0 +1,165 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _QSE_SHAREDPTR_HPP_ +#define _QSE_SHAREDPTR_HPP_ + +#include +#include + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +template +struct SharedPtrDeleter +{ + void operator() (T* ptr, void* arg) + { + delete ptr; + } +}; + +template +struct SharedPtrArrayDeleter +{ + void operator() (T* ptr, void* arg) + { + delete[] ptr; + } +}; + +/// +/// use QSE::MmgedSharedPtr if you want the instance of this class itself +/// to be memory managed. +/// +template > +class QSE_EXPORT SharedPtr +{ +public: + typedef SharedPtr SelfType; + + typedef SharedPtrDeleter DefaultDeleter; + + SharedPtr (T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL): _ptr (ptr), _darg (darg) + { + this->_ref = new qse_size_t; + (*this->_ref) = 1; + } + + SharedPtr (const SelfType& ptr): _ref(ptr._ref), _ptr (ptr._ptr), _darg (ptr._darg) + { + (*this->_ref)++; + } + + ~SharedPtr () + { + (*this->_ref)--; + if (*this->_ref <= 0) + { + if (this->_ptr) this->deleter (this->_ptr, this->_darg); + delete this->_ref; + } + } + + SelfType& operator= (const SelfType& ptr) + { + if (this != &ptr) + { + (*this->_ref)--; + if (*this->_ref <= 0) + { + if (this->_ptr) this->deleter (this->_ptr, this->_darg); + delete this->_ref; + } + + this->_ptr = ptr._ptr; + this->_darg = ptr._darg; + this->_ref = ptr._ref; + (*this->_ref)++; + } + + return *this; + } + + T& operator* () + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return *this->_ptr; + } + + const T& operator* () const + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return *this->_ptr; + } + + T* operator-> () + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr; + } + + const T* operator-> () const + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr; + } + + bool operator! () const + { + return this->_ptr == (T*)QSE_NULL; + } + + T& operator[] (qse_size_t idx) + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr[idx]; + } + + T* get () + { + return this->_ptr; + } + + const T* get () const + { + return this->_ptr; + } + + +protected: + qse_size_t* _ref; + T* _ptr; + void* _darg; + DELETER deleter; +}; + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// + +#endif diff --git a/qse/include/qse/cmn/Array.hpp b/qse/include/qse/cmn/Array.hpp index 2db824b0..49c52500 100644 --- a/qse/include/qse/cmn/Array.hpp +++ b/qse/include/qse/cmn/Array.hpp @@ -111,12 +111,15 @@ public: SelfType& operator= (const SelfType& array) { - this->clear (true); - if (array.buffer) + if (this != &array) { - this->buffer = this->clone_buffer (array, array.capacity, array.count); - this->count = array.count; - this->capacity = array.capacity; + this->clear (true); + if (array.buffer) + { + this->buffer = this->clone_buffer (array, array.capacity, array.count); + this->count = array.count; + this->capacity = array.capacity; + } } return *this; } diff --git a/qse/include/qse/cmn/BinaryHeap.hpp b/qse/include/qse/cmn/BinaryHeap.hpp index 501f84af..6cddd667 100644 --- a/qse/include/qse/cmn/BinaryHeap.hpp +++ b/qse/include/qse/cmn/BinaryHeap.hpp @@ -132,7 +132,10 @@ public: SelfType& operator= (const SelfType& heap) { - ParentType::operator= (heap); + if (this != &heap) + { + ParentType::operator= (heap); + } return *this; } diff --git a/qse/include/qse/cmn/HashList.hpp b/qse/include/qse/cmn/HashList.hpp index 5bea1754..0c5ffa13 100644 --- a/qse/include/qse/cmn/HashList.hpp +++ b/qse/include/qse/cmn/HashList.hpp @@ -220,25 +220,28 @@ public: SelfType& operator= (const SelfType& list) { - this->clear (false); - - // note that the memory pool itself is not copied. - - for (qse_size_t i = 0; i < list.node_capacity; i++) + if (this != &list) { - qse_size_t head = i << 1; - qse_size_t tail = head + 1; + this->clear (false); - Node* np = list.nodes[head]; - if (np == QSE_NULL) continue; - - do + // note that the memory pool itself is not copied. + + for (qse_size_t i = 0; i < list.node_capacity; i++) { - this->copy_datum (np, this->node_capacity, this->nodes, this->datum_list); - if (np == list.nodes[tail]) break; - np = np->getNextNode (); - } - while (1); + qse_size_t head = i << 1; + qse_size_t tail = head + 1; + + Node* np = list.nodes[head]; + if (np == QSE_NULL) continue; + + do + { + this->copy_datum (np, this->node_capacity, this->nodes, this->datum_list); + if (np == list.nodes[tail]) break; + np = np->getNextNode (); + } + while (1); + } } return *this; diff --git a/qse/include/qse/cmn/HashTable.hpp b/qse/include/qse/cmn/HashTable.hpp index 19a780fe..2ebe3575 100644 --- a/qse/include/qse/cmn/HashTable.hpp +++ b/qse/include/qse/cmn/HashTable.hpp @@ -131,7 +131,10 @@ public: SelfType& operator= (const SelfType& table) { - this->pair_list = table.pair_list; + if (this != &table) + { + this->pair_list = table.pair_list; + } return *this; } diff --git a/qse/include/qse/cmn/LinkedList.hpp b/qse/include/qse/cmn/LinkedList.hpp index 30b24e32..2655dd26 100644 --- a/qse/include/qse/cmn/LinkedList.hpp +++ b/qse/include/qse/cmn/LinkedList.hpp @@ -231,10 +231,13 @@ public: SelfType& operator= (const SelfType& ll) { - this->clear (); - // note that the memory pool itself is not copied. - for (Node* p = ll.head_node; p != QSE_NULL; p = p->next) - this->append (p->value); + if (this != &ll) + { + this->clear (); + // note that the memory pool itself is not copied. + for (Node* p = ll.head_node; p != QSE_NULL; p = p->next) + this->append (p->value); + } return *this; } diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index 637a04c0..9d521034 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -51,7 +51,7 @@ pkginclude_HEADERS = \ if ENABLE_CXX pkginclude_HEADERS += \ - Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ + Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp MmgedSharedPtr.hpp \ Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ RedBlackTree.hpp RedBlackTable.hpp \ Array.hpp BinaryHeap.hpp diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 239c5f18..b3b5a3a8 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -51,7 +51,7 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_CXX_TRUE@am__append_1 = \ -@ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ +@ENABLE_CXX_TRUE@ Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp MmgedSharedPtr.hpp \ @ENABLE_CXX_TRUE@ Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ @ENABLE_CXX_TRUE@ RedBlackTree.hpp RedBlackTable.hpp \ @ENABLE_CXX_TRUE@ Array.hpp BinaryHeap.hpp @@ -93,9 +93,9 @@ am__pkginclude_HEADERS_DIST = alg.h chr.h cp949.h cp950.h dir.h dll.h \ nwio.h oht.h opt.h path.h pio.h pma.h rbt.h rex.h sck.h sio.h \ sll.h slmb.h str.h task.h time.h tio.h tmr.h tre.h uni.h uri.h \ utf8.h xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ - Mpool.hpp Association.hpp LinkedList.hpp HashList.hpp \ - HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp Array.hpp \ - BinaryHeap.hpp + MmgedSharedPtr.hpp Mpool.hpp Association.hpp LinkedList.hpp \ + HashList.hpp HashTable.hpp RedBlackTree.hpp RedBlackTable.hpp \ + Array.hpp BinaryHeap.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ diff --git a/qse/include/qse/cmn/MmgedSharedPtr.hpp b/qse/include/qse/cmn/MmgedSharedPtr.hpp new file mode 100644 index 00000000..9127c05d --- /dev/null +++ b/qse/include/qse/cmn/MmgedSharedPtr.hpp @@ -0,0 +1,173 @@ +/* + * $Id$ + * + Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _QSE_CMN_MMGEDSHAREDPTR_HPP_ +#define _QSE_CMN_MMGEDSHAREDPTR_HPP_ + +#include + +///////////////////////////////// +QSE_BEGIN_NAMESPACE(QSE) +///////////////////////////////// + +template +struct MmgedSharedPtrDeleter +{ + void operator() (T* ptr, void* arg) + { + delete ptr; + } +}; + +template +struct MmgedSharedPtrArrayDeleter +{ + void operator() (T* ptr, void* arg) + { + delete[] ptr; + } +}; + +/// +/// The MmgedSharedPtr class is similar to SharedPtr except that i +/// accepts a pointer to a memory manager to allocate the space for +/// shared reference count. +/// +template > +class QSE_EXPORT MmgedSharedPtr: public Mmged +{ +public: + typedef MmgedSharedPtr SelfType; + + typedef MmgedSharedPtrDeleter DefaultDeleter; + + MmgedSharedPtr (T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL): Mmged(QSE_NULL), _ptr(ptr), _darg(darg) + { + this->_ref = new(this->getMmgr()) qse_size_t; + (*this->_ref) = 1; + } + + MmgedSharedPtr (Mmgr* mmgr, T* ptr = (T*)QSE_NULL, void* darg = (void*)QSE_NULL): Mmged(mmgr), _ptr(ptr), _darg(darg) + { + this->_ref = new(this->getMmgr()) qse_size_t; + (*this->_ref) = 1; + } + + MmgedSharedPtr (const SelfType& ptr): Mmged(ptr), _ref(ptr._ref), _ptr (ptr._ptr), _darg (ptr._darg) + { + (*this->_ref)++; + } + + ~MmgedSharedPtr () + { + (*this->_ref)--; + if (*this->_ref <= 0) + { + if (this->_ptr) this->deleter (this->_ptr, this->_darg); + // no destructor as *this->_ref is a plain type. + ::operator delete (this->_ref, this->getMmgr()); + } + } + + SelfType& operator= (const SelfType& ptr) + { + if (this != &ptr) + { + (*this->_ref)--; + if (*this->_ref <= 0) + { + if (this->_ptr) this->deleter (this->_ptr, this->_darg); + // no destructor as *this->_ref is a plain type. + ::operator delete (this->_ref, this->getMmgr()); + } + + this->mmgr = ptr.getMmgr(); // memory manager must be copied + this->_ptr = ptr._ptr; + this->_darg = ptr._darg; + this->_ref = ptr._ref; + (*this->_ref)++; + } + + return *this; + } + + T& operator* () + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return *this->_ptr; + } + + const T& operator* () const + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return *this->_ptr; + } + + T* operator-> () + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr; + } + + const T* operator-> () const + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr; + } + + bool operator! () const + { + return this->_ptr == (T*)QSE_NULL; + } + + T& operator[] (qse_size_t idx) + { + QSE_ASSERT (this->_ptr != (T*)QSE_NULL); + return this->_ptr[idx]; + } + + T* get () + { + return this->_ptr; + } + + const T* get () const + { + return this->_ptr; + } + +protected: + qse_size_t* _ref; + T* _ptr; + void* _darg; + DELETER deleter; +}; + +///////////////////////////////// +QSE_END_NAMESPACE(QSE) +///////////////////////////////// + +#endif diff --git a/qse/include/qse/cmn/Mmgr.hpp b/qse/include/qse/cmn/Mmgr.hpp index 7950c236..fb8d8ba8 100644 --- a/qse/include/qse/cmn/Mmgr.hpp +++ b/qse/include/qse/cmn/Mmgr.hpp @@ -209,6 +209,27 @@ struct ScopedPtrMmgrDeleter } }; +// Customized deleter for SharedPtr +template +struct SharedPtrMmgrDeleter +{ + void operator() (T* ptr, void* arg) + { + ptr->~T (); + ::operator delete (ptr, (QSE::Mmgr*)arg); + } +}; + +template +struct MmgedSharedPtrMmgrDeleter +{ + void operator() (T* ptr, void* arg) + { + ptr->~T (); + ::operator delete (ptr, (QSE::Mmgr*)arg); + } +}; + ///////////////////////////////// QSE_END_NAMESPACE(QSE) ///////////////////////////////// diff --git a/qse/include/qse/cmn/RedBlackTable.hpp b/qse/include/qse/cmn/RedBlackTable.hpp index 7a480f93..35f09b8b 100644 --- a/qse/include/qse/cmn/RedBlackTable.hpp +++ b/qse/include/qse/cmn/RedBlackTable.hpp @@ -102,7 +102,10 @@ public: SelfType& operator= (const SelfType& table) { - this->pair_tree = table.pair_tree; + if (this != &table) + { + this->pair_tree = table.pair_tree; + } return *this; } diff --git a/qse/include/qse/cmn/RedBlackTree.hpp b/qse/include/qse/cmn/RedBlackTree.hpp index 42d8eb50..dcaa46e3 100644 --- a/qse/include/qse/cmn/RedBlackTree.hpp +++ b/qse/include/qse/cmn/RedBlackTree.hpp @@ -380,14 +380,17 @@ public: SelfType& operator= (const SelfType& rbt) { - this->clear (false); - - // TODO: do the level-order traversal to minimize rebalancing. - Iterator it = rbt.getIterator(); - while (it.isLegit()) + if (this != &rbt) { - this->insert (*it); - ++it; + this->clear (false); + + // TODO: do the level-order traversal to minimize rebalancing. + Iterator it = rbt.getIterator(); + while (it.isLegit()) + { + this->insert (*it); + ++it; + } } return *this;