From 5ed8d12478f74e034bee90822f25a29e6e3cc722 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Sat, 18 May 2013 13:45:44 +0900 Subject: [PATCH] Redefined smart pointer classes in safer way --- ConfigureChecks.cmake | 16 +- taglib/CMakeLists.txt | 3 +- taglib/asf/asfattribute.h | 2 +- taglib/asf/asfpicture.h | 2 +- taglib/fileref.cpp | 2 +- taglib/fileref.h | 2 +- taglib/mp4/mp4coverart.h | 2 +- taglib/mp4/mp4item.h | 2 +- taglib/mpeg/mpegheader.h | 2 +- taglib/riff/aiff/aiffproperties.h | 2 +- taglib/taglib_config.h.cmake | 10 +- taglib/tagunion.cpp | 4 +- taglib/tagunion.h | 2 +- taglib/toolkit/tbytevector.cpp | 4 +- taglib/toolkit/tbytevector.h | 2 +- taglib/toolkit/tlist.h | 2 +- taglib/toolkit/tmap.h | 2 +- taglib/toolkit/trefcountptr.h | 273 -------- .../{trefcountptr.cpp => tsmartptr.cpp} | 45 +- taglib/toolkit/tsmartptr.h | 583 +++++++++++++++++- taglib/toolkit/tstring.h | 2 +- tests/test_smartptr.cpp | 24 +- 22 files changed, 645 insertions(+), 343 deletions(-) delete mode 100644 taglib/toolkit/trefcountptr.h rename taglib/toolkit/{trefcountptr.cpp => tsmartptr.cpp} (82%) diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 134d584e..3746e6d8 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -213,7 +213,7 @@ check_cxx_source_compiles(" check_cxx_source_compiles(" #include - int main() { std::tr1::shared_ptr x; return 0; } + int main() { std::shared_ptr x; return 0; } " TAGLIB_USE_STD_SHARED_PTR) if(NOT TAGLIB_USE_STD_SHARED_PTR) @@ -230,6 +230,20 @@ if(NOT TAGLIB_USE_STD_SHARED_PTR) endif() endif() +# Determine where unique_ptr or scoped_ptr is defined regardless of C++11 support. + +check_cxx_source_compiles(" + #include + int main() { std::unique_ptr x; return 0; } +" TAGLIB_USE_STD_UNIQUE_PTR) + +if(NOT TAGLIB_USE_STD_UNIQUE_PTR) + check_cxx_source_compiles(" + #include + int main() { boost::scoped_ptr x; return 0; } + " TAGLIB_USE_BOOST_SCOPED_PTR) +endif() + # Determine whether CppUnit is installed. set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 56d4d15e..1b406ebd 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -54,7 +54,6 @@ set(tag_HDRS toolkit/tmap.tcc toolkit/tpropertymap.h toolkit/tsmartptr.h - toolkit/trefcountptr.h mpeg/mpegfile.h mpeg/mpegproperties.h mpeg/mpegheader.h @@ -301,7 +300,7 @@ set(toolkit_SRCS toolkit/tfilestream.cpp toolkit/tdebug.cpp toolkit/tpropertymap.cpp - toolkit/trefcountptr.cpp + toolkit/tsmartptr.cpp toolkit/unicode.cpp ) diff --git a/taglib/asf/asfattribute.h b/taglib/asf/asfattribute.h index 9740cb18..18269da4 100644 --- a/taglib/asf/asfattribute.h +++ b/taglib/asf/asfattribute.h @@ -205,7 +205,7 @@ namespace TagLib ByteVector render(const String &name, int kind = 0) const; class AttributePrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } diff --git a/taglib/asf/asfpicture.h b/taglib/asf/asfpicture.h index 5f688898..463bd43d 100644 --- a/taglib/asf/asfpicture.h +++ b/taglib/asf/asfpicture.h @@ -231,7 +231,7 @@ namespace TagLib #endif private: class PicturePrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } } diff --git a/taglib/fileref.cpp b/taglib/fileref.cpp index f923f3ad..f24f4c56 100644 --- a/taglib/fileref.cpp +++ b/taglib/fileref.cpp @@ -64,7 +64,7 @@ class FileRef::FileRefPrivate public: FileRefPrivate(File *f) : file(f) {} - TAGLIB_SHARED_PTR file; + RefCountPtr file; static List fileTypeResolvers; }; diff --git a/taglib/fileref.h b/taglib/fileref.h index f11e3d5d..c323b086 100644 --- a/taglib/fileref.h +++ b/taglib/fileref.h @@ -282,7 +282,7 @@ namespace TagLib { private: class FileRefPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } // namespace TagLib diff --git a/taglib/mp4/mp4coverart.h b/taglib/mp4/mp4coverart.h index e2b82c79..ea9784ad 100644 --- a/taglib/mp4/mp4coverart.h +++ b/taglib/mp4/mp4coverart.h @@ -66,7 +66,7 @@ namespace TagLib { private: class CoverArtPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; typedef List CoverArtList; diff --git a/taglib/mp4/mp4item.h b/taglib/mp4/mp4item.h index 91fd4c15..8ad23cf1 100644 --- a/taglib/mp4/mp4item.h +++ b/taglib/mp4/mp4item.h @@ -97,7 +97,7 @@ namespace TagLib { private: class ItemPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } diff --git a/taglib/mpeg/mpegheader.h b/taglib/mpeg/mpegheader.h index 56749465..0e168df1 100644 --- a/taglib/mpeg/mpegheader.h +++ b/taglib/mpeg/mpegheader.h @@ -181,7 +181,7 @@ namespace TagLib { void parse(const ByteVector &data); class HeaderPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } } diff --git a/taglib/riff/aiff/aiffproperties.h b/taglib/riff/aiff/aiffproperties.h index 903ea290..8cb78c49 100644 --- a/taglib/riff/aiff/aiffproperties.h +++ b/taglib/riff/aiff/aiffproperties.h @@ -73,7 +73,7 @@ namespace TagLib { void read(const ByteVector &data); class PropertiesPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; } } diff --git a/taglib/taglib_config.h.cmake b/taglib/taglib_config.h.cmake index 036f2cfd..4f2045d1 100644 --- a/taglib/taglib_config.h.cmake +++ b/taglib/taglib_config.h.cmake @@ -7,7 +7,11 @@ #cmakedefine TAGLIB_USE_MOVE_SEMANTICS 1 /* Defined if your compiler supports shared_ptr */ -#cmakedefine TAGLIB_USE_STD_SHARED_PTR 1 -#cmakedefine TAGLIB_USE_TR1_SHARED_PTR 1 -#cmakedefine TAGLIB_USE_BOOST_SHARED_PTR 1 +#cmakedefine TAGLIB_USE_STD_SHARED_PTR 1 // #include / std::shared_ptr +#cmakedefine TAGLIB_USE_TR1_SHARED_PTR 1 // #include / std::tr1::shared_ptr +#cmakedefine TAGLIB_USE_BOOST_SHARED_PTR 1 // #include / boost::shared_ptr + +/* Defined if your compiler supports unique_ptr or scoped_ptr */ +#cmakedefine TAGLIB_USE_STD_UNIQUE_PTR 1 // #include / std::unique_ptr +#cmakedefine TAGLIB_USE_BOOST_SCOPED_PTR 1 // #include / boost::scoped_ptr diff --git a/taglib/tagunion.cpp b/taglib/tagunion.cpp index cb45d692..fe7631d0 100644 --- a/taglib/tagunion.cpp +++ b/taglib/tagunion.cpp @@ -31,7 +31,7 @@ using namespace TagLib; namespace { - typedef std::vector > TagVector; + typedef std::vector > TagVector; typedef TagVector::iterator TagIterator; typedef TagVector::const_iterator TagConstIterator; } @@ -66,7 +66,7 @@ public: { } - std::vector > tags; + TagVector tags; }; TagUnion::TagUnion(size_t count) diff --git a/taglib/tagunion.h b/taglib/tagunion.h index 39c3e2af..5479e71a 100644 --- a/taglib/tagunion.h +++ b/taglib/tagunion.h @@ -89,7 +89,7 @@ namespace TagLib { TagUnion &operator=(const Tag &); class TagUnionPrivate; - TAGLIB_SHARED_PTR d; + NonRefCountPtr d; }; } diff --git a/taglib/toolkit/tbytevector.cpp b/taglib/toolkit/tbytevector.cpp index 19e2c8f4..d7111bda 100644 --- a/taglib/toolkit/tbytevector.cpp +++ b/taglib/toolkit/tbytevector.cpp @@ -363,7 +363,7 @@ public: { } - ByteVectorPrivate(TAGLIB_SHARED_PTR d, size_t o, size_t l) + ByteVectorPrivate(RefCountPtr d, size_t o, size_t l) : data(d->data) , offset(d->offset + o) , length(l) @@ -411,7 +411,7 @@ public: return *this; } - TAGLIB_SHARED_PTR > data; + RefCountPtr > data; size_t offset; size_t length; }; diff --git a/taglib/toolkit/tbytevector.h b/taglib/toolkit/tbytevector.h index 613f4306..ae3039a7 100644 --- a/taglib/toolkit/tbytevector.h +++ b/taglib/toolkit/tbytevector.h @@ -551,7 +551,7 @@ namespace TagLib { private: class ByteVectorPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; /*! diff --git a/taglib/toolkit/tlist.h b/taglib/toolkit/tlist.h index 51338748..dcd95b0c 100644 --- a/taglib/toolkit/tlist.h +++ b/taglib/toolkit/tlist.h @@ -305,7 +305,7 @@ namespace TagLib { private: #ifndef DO_NOT_DOCUMENT template class ListPrivate; - TAGLIB_SHARED_PTR > d; + RefCountPtr > d; #endif }; diff --git a/taglib/toolkit/tmap.h b/taglib/toolkit/tmap.h index 46d82f99..f291226f 100644 --- a/taglib/toolkit/tmap.h +++ b/taglib/toolkit/tmap.h @@ -219,7 +219,7 @@ namespace TagLib { private: #ifndef DO_NOT_DOCUMENT template class MapPrivate; - TAGLIB_SHARED_PTR > d; + RefCountPtr > d; #endif }; diff --git a/taglib/toolkit/trefcountptr.h b/taglib/toolkit/trefcountptr.h deleted file mode 100644 index a1c578b4..00000000 --- a/taglib/toolkit/trefcountptr.h +++ /dev/null @@ -1,273 +0,0 @@ -/*************************************************************************** - copyright : (C) 2013 by Tsuda Kageyu - email : tsuda.kageyu@gmail.com - ***************************************************************************/ - -/*************************************************************************** - * This library is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Lesser General Public License version * - * 2.1 as published by the Free Software Foundation. * - * * - * This library 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 * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this library; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * - * 02110-1301 USA * - * * - * Alternatively, this file is available under the Mozilla Public * - * License Version 1.1. You may obtain a copy of the License at * - * http://www.mozilla.org/MPL/ * - ***************************************************************************/ - -#ifndef TAGLIB_REFCOUNTPTR_H -#define TAGLIB_REFCOUNTPTR_H - -#include - -#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. -/*! - * \internal - * This is just used as a smart pointer for shared classes in TagLib. - * - * \warning This is not part of the TagLib public API! - */ - -namespace TagLib { - -#if defined(TAGLIB_USE_STD_SHARED_PTR) || defined(TAGLIB_USE_TR1_SHARED_PTR) - -#define TAGLIB_SHARED_PTR std::tr1::shared_ptr - -#elif defined(TAGLIB_USE_BOOST_SHARED_PTR) - -#define TAGLIB_SHARED_PTR boost::shared_ptr - -#else // TAGLIB_USE_*_SHARED_PTR - - // Self-implements RefCountPtr if shared_ptr is not available. - // I STRONGLY RECOMMEND using standard shared_ptr rather than this class. - - class RefCounter - { - public: - RefCounter(); - ~RefCounter(); - - size_t ref(); - size_t deref(); - size_t count() const; - - private: - class RefCounterPrivate; - RefCounterPrivate *d; - }; - - template - class RefCountPtr - { - private: - - // Counter base class. Provides a reference counter. - - class CounterBase - { - public: - virtual ~CounterBase() - { - } - - void addref() - { - count.ref(); - } - - void release() - { - if(count.deref() == 0) { - dispose(); - delete this; - } - } - - long use_count() const - { - return static_cast(count.count()); - } - - virtual void dispose() = 0; - - private: - RefCounter count; - }; - - // Counter impl class. Provides a dynamic deleter. - - template - class CounterImpl : public CounterBase - { - public: - CounterImpl(U *p) - : p(p) - { - } - - virtual void dispose() - { - delete p; - } - - U *get() const - { - return p; - } - - private: - U *p; - }; - - public: - explicit RefCountPtr() - : counter(0) - { - } - - template - explicit RefCountPtr(U *p) - : counter(new CounterImpl(p)) - { - } - - RefCountPtr(const RefCountPtr &x) - : counter(x.counter) - { - if(counter) - counter->addref(); - } - - template - RefCountPtr(const RefCountPtr &x) - : counter(reinterpret_cast(x.counter)) - { - if(counter) - counter->addref(); - } - - ~RefCountPtr() - { - if(counter) - counter->release(); - } - - T *get() const - { - if(counter) - return static_cast*>(counter)->get(); - else - return 0; - } - - long use_count() const - { - if(counter) - return counter->use_count(); - else - return 0; - } - - bool unique() const - { - return (use_count() == 1); - } - - template - void reset(U *p) - { - if(get() != p) - RefCountPtr(p).swap(*this); - } - - void reset() - { - RefCountPtr().swap(*this); - } - - void swap(RefCountPtr &x) - { - std::swap(counter, x.counter); - } - - RefCountPtr &operator=(const RefCountPtr &x) - { - if(get() != x.get()) { - if(counter) - counter->release(); - - counter = x.counter; - - if(counter) - counter->addref(); - } - return *this; - } - - template - RefCountPtr &operator=(const RefCountPtr &x) - { - if(get() != x.get()) { - if(counter) - counter->release(); - - counter = reinterpret_cast(x.counter); - - if(counter) - counter->addref(); - } - return *this; - } - - T& operator*() const - { - return *get(); - } - - T* operator->() const - { - return get(); - } - - bool operator==(const RefCountPtr &x) const - { - return (get() == x.get()); - } - - bool operator!=(const RefCountPtr &x) const - { - return !operator==(x); - } - - operator bool() const - { - return (get() != 0); - } - - private: - mutable CounterBase *counter; - - template friend class RefCountPtr; - }; - - template - void swap(RefCountPtr &a, RefCountPtr &b) - { - a.swap(b); - } - -#endif // TAGLIB_USE_*_SHARED_PTR -} -#endif // DO_NOT_DOCUMENT - -#endif diff --git a/taglib/toolkit/trefcountptr.cpp b/taglib/toolkit/tsmartptr.cpp similarity index 82% rename from taglib/toolkit/trefcountptr.cpp rename to taglib/toolkit/tsmartptr.cpp index cfd469a5..87ad6ee3 100644 --- a/taglib/toolkit/trefcountptr.cpp +++ b/taglib/toolkit/tsmartptr.cpp @@ -23,8 +23,14 @@ * http://www.mozilla.org/MPL/ * ***************************************************************************/ +#include "taglib_config.h" + +#if !defined(TAGLIB_USE_STD_SHARED_PTR) \ + && !defined(TAGLIB_USE_TR1_SHARED_PTR) \ + && !defined(TAGLIB_USE_BOOST_SHARED_PTR) + #include "config.h" -#include "trefcountptr.h" +#include "tsmartptr.h" #if defined(HAVE_STD_ATOMIC) # include @@ -66,41 +72,44 @@ namespace TagLib { - class RefCounter::RefCounterPrivate + class CounterBase::CounterBasePrivate { public: - RefCounterPrivate() : refCount(1) {} - - size_t ref() { return static_cast(ATOMIC_INC(refCount)); } - size_t deref() { return static_cast(ATOMIC_DEC(refCount)); } - size_t count() const { return static_cast(refCount); } + CounterBasePrivate() + : refCount(1) + { + } volatile ATOMIC_INT refCount; }; - RefCounter::RefCounter() - : d(new RefCounterPrivate()) + CounterBase::CounterBase() + : d(new CounterBasePrivate()) { } - RefCounter::~RefCounter() + CounterBase::~CounterBase() { delete d; } - size_t RefCounter::ref() + void CounterBase::addref() { - return d->ref(); + ATOMIC_INC(d->refCount); } - size_t RefCounter::deref() - { - return d->deref(); + void CounterBase::release() + { + if(ATOMIC_DEC(d->refCount) == 0) { + dispose(); + delete this; + } } - size_t RefCounter::count() const - { - return d->count(); + long CounterBase::use_count() const + { + return static_cast(d->refCount); } } +#endif diff --git a/taglib/toolkit/tsmartptr.h b/taglib/toolkit/tsmartptr.h index a86749d3..c3532195 100644 --- a/taglib/toolkit/tsmartptr.h +++ b/taglib/toolkit/tsmartptr.h @@ -27,28 +27,577 @@ #define TAGLIB_SMARTPTR_H #include "taglib_config.h" +#include #if defined(TAGLIB_USE_STD_SHARED_PTR) # include #elif defined(TAGLIB_USE_TR1_SHARED_PTR) # include -#elif defined(TAGLIB_USE_BOOST_SHARED_PTR) -# include -#else -# include "trefcountptr.h" -#endif - -#if defined(TAGLIB_USE_STD_SHARED_PTR) || defined(TAGLIB_USE_TR1_SHARED_PTR) - -# define TAGLIB_SHARED_PTR std::tr1::shared_ptr - #elif defined(TAGLIB_USE_BOOST_SHARED_PTR) - -# define TAGLIB_SHARED_PTR boost::shared_ptr - -#else - -# define TAGLIB_SHARED_PTR TagLib::RefCountPtr - +# include #endif + +#if defined(TAGLIB_USE_STD_UNIQUE_PTR) +# include +#elif defined(TAGLIB_USE_BOOST_SCOPED_PTR) +# include +#endif + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. +/*! + * \warning This is not part of the TagLib public API! + */ + +namespace TagLib +{ +#if defined(TAGLIB_USE_STD_SHARED_PTR) \ + || defined(TAGLIB_USE_TR1_SHARED_PTR) \ + || defined(TAGLIB_USE_BOOST_SHARED_PTR) + + // RefCountPtr is just a thin wrapper of shared_ptr. + // It will be optimized out by compilers and performs equivalent to them. + + template + class RefCountPtr + { + public: + RefCountPtr() + : sp() + { + } + + template + explicit RefCountPtr(U *p) + : sp(p) + { + } + + RefCountPtr(const RefCountPtr &x) + : sp(x.sp) + { + } + + template + RefCountPtr(const RefCountPtr &x) + : sp(x.sp) + { + } + +# ifdef TAGLIB_USE_MOVE_SEMANTICS + + RefCountPtr(RefCountPtr &&x) + : sp(std::move(x.sp)) + { + } + + template + RefCountPtr(RefCountPtr &&x) + : sp(std::move(x.sp)) + { + } + +# endif + + T *get() const + { + return sp.get(); + } + + long use_count() const + { + return sp.use_count(); + } + + bool unique() const + { + return sp.unique(); + } + + template + void reset(U *p) + { + sp.reset(p); + } + + void reset() + { + sp.reset(); + } + + void swap(RefCountPtr &x) + { + sp.swap(x.sp); + } + + RefCountPtr &operator=(const RefCountPtr &x) + { + sp = x.sp; + return *this; + } + + template + RefCountPtr &operator=(const RefCountPtr &x) + { + sp = x.sp; + return *this; + } + +# ifdef TAGLIB_USE_MOVE_SEMANTICS + + RefCountPtr &operator=(RefCountPtr &&x) + { + sp = std::move(x.sp); + return *this; + } + + template + RefCountPtr &operator=(RefCountPtr &&x) + { + sp = std::move(x.sp); + return *this; + } + +# endif + + T& operator*() const + { + return sp.operator*(); + } + + T* operator->() const + { + return sp.operator->(); + } + + operator bool() const + { + return static_cast(sp); + } + + bool operator!() const + { + return !static_cast(sp); + } + + private: + template friend class RefCountPtr; + +# if defined(TAGLIB_USE_STD_SHARED_PTR) + + std::shared_ptr sp; + +# elif defined(TAGLIB_USE_TR1_SHARED_PTR) + + std::tr1::shared_ptr sp; + +# else + + boost::shared_ptr sp; + +# endif + }; + +#else // TAGLIB_USE_STD_SHARED_PTR etc. + + // Self-implements RefCountPtr if shared_ptr is not available. + // I STRONGLY RECOMMEND using standard shared_ptr rather than this class. + + // Counter base class. Provides a reference counter. + + class CounterBase + { + public: + CounterBase(); + virtual ~CounterBase(); + + void addref(); + void release(); + long use_count() const; + + virtual void dispose() = 0; + + private: + class CounterBasePrivate; + CounterBasePrivate *d; + }; + + // Counter impl class. Provides a dynamic deleter. + + template + class CounterImpl : public CounterBase + { + public: + CounterImpl(T *p) + : p(p) + { + } + + virtual void dispose() + { + delete p; + } + + T *get() const + { + return p; + } + + private: + T *p; + }; + + template + class RefCountPtr + { + public: + RefCountPtr() + : px(0) + , counter(0) + { + } + + template + explicit RefCountPtr(U *p) + : px(p) + , counter(new CounterImpl(p)) + { + } + + RefCountPtr(const RefCountPtr &x) + : px(x.px) + , counter(x.counter) + { + if(counter) + counter->addref(); + } + + template + RefCountPtr(const RefCountPtr &x) + : px(x.px) + , counter(x.counter) + { + if(counter) + counter->addref(); + } + + ~RefCountPtr() + { + if(counter) + counter->release(); + } + + T *get() const + { + return px; + } + + long use_count() const + { + if(counter) + return counter->use_count(); + else + return 0; + } + + bool unique() const + { + return (use_count() == 1); + } + + template + void reset(U *p) + { + if(px != p) + RefCountPtr(p).swap(*this); + } + + void reset() + { + RefCountPtr().swap(*this); + } + + void swap(RefCountPtr &x) + { + std::swap(px, x.px); + std::swap(counter, x.counter); + } + + RefCountPtr &operator=(const RefCountPtr &x) + { + if(px != x.px) { + if(counter) + counter->release(); + + px = x.px; + counter = x.counter; + + if(counter) + counter->addref(); + } + return *this; + } + + template + RefCountPtr &operator=(const RefCountPtr &x) + { + if(px != x.px) { + if(counter) + counter->release(); + + px = x.px; + counter = x.counter; + + if(counter) + counter->addref(); + } + return *this; + } + + T& operator*() const + { + return *px; + } + + T* operator->() const + { + return px; + } + + operator bool() const + { + return (px != 0); + } + + bool operator!() const + { + return (px == 0); + } + + private: + T *px; + CounterBase *counter; + + template friend class RefCountPtr; + }; + +#endif // TAGLIB_USE_STD_SHARED_PTR etc. + +#if defined(TAGLIB_USE_STD_UNIQUE_PTR) || defined(TAGLIB_USE_BOOST_SCOPED_PTR) + + // NonRefCountPtr is just a thin wrapper of unique_ptr or scoped_ptr. + // It will be optimized out by compilers and performs equivalent to them. + + template + class NonRefCountPtr + { + public: + explicit NonRefCountPtr(T *p = 0) + : up(p) + { + } + + ~NonRefCountPtr() + { + } + + void reset(T *p = 0) + { + NonRefCountPtr(p).swap(*this); + } + + T &operator*() const + { + return up.operator*(); + } + + T *operator->() const + { + return up.operator->(); + } + + T *get() const + { + return up.get(); + } + + operator bool() const + { + return static_cast(up); + } + + bool operator!() const + { + return !static_cast(up); + } + + void swap(NonRefCountPtr &x) + { + up.swap(x.up); + } + + private: + + // Noncopyable + NonRefCountPtr(const NonRefCountPtr &); + NonRefCountPtr &operator=(const NonRefCountPtr &); + + void operator==(const NonRefCountPtr &) const; + void operator!=(const NonRefCountPtr &) const; + +# if defined(TAGLIB_USE_STD_UNIQUE_PTR) + + std::unique_ptr up; + +# else + + boost::scoped_ptr up; + +# endif + }; + +#else // TAGLIB_USE_STD_UNIQUE_PTR + + // Self-implements NonRefCountPtr if unique_ptr is not available. + // I STRONGLY RECOMMEND using standard unique_ptr rather than this class. + + template + class NonRefCountPtr + { + public: + explicit NonRefCountPtr(T *p = 0) + : px(p) + { + } + + ~NonRefCountPtr() + { + delete px; + } + + void reset(T *p = 0) + { + NonRefCountPtr(p).swap(*this); + } + + T &operator*() const + { + return *px; + } + + T *operator->() const + { + return px; + } + + T *get() const + { + return px; + } + + operator bool() const + { + return (px != 0); + } + + bool operator!() const + { + return (px == 0); + } + + + void swap(NonRefCountPtr &x) + { + std::swap(px, x.px); + } + + private: + + // Noncopyable + NonRefCountPtr(const NonRefCountPtr &); + NonRefCountPtr &operator=(const NonRefCountPtr &); + + void operator==(const NonRefCountPtr &) const; + void operator!=(const NonRefCountPtr &) const; + + T *px; + }; + +#endif // TAGLIB_USE_STD_UNIQUE_PTR + + // Comparison operators for smart pointers. + + template + bool operator==(const RefCountPtr &a, const RefCountPtr &b) + { + return (a.get() == b.get()); + } + + template + bool operator!=(const RefCountPtr &a, const RefCountPtr &b) + { + return (a.get() != b.get()); + } + + template + bool operator==(const RefCountPtr &a, U *b) + { + return (a.get() == b); + } + + template + bool operator!=(const RefCountPtr &a, U *b) + { + return (a.get() != b); + } + + template + bool operator==(const NonRefCountPtr &a, U *b) + { + return (a.get() == b); + } + + template + bool operator!=(const NonRefCountPtr &a, U *b) + { + return (a.get() != b); + } + + template + bool operator==(T *a, const RefCountPtr &b) + { + return (a == b.get()); + } + + template + bool operator!=(T *a, const RefCountPtr &b) + { + return (a != b.get()); + } + + template + bool operator==(T *a, const NonRefCountPtr &b) + { + return (a == b.get()); + } + + template + bool operator!=(T *a, const NonRefCountPtr &b) + { + return (a != b.get()); + } + + template + void swap(RefCountPtr &a, RefCountPtr &b) + { + a.swap(b); + } + + template + void swap(NonRefCountPtr &a, NonRefCountPtr &b) + { + a.swap(b); + } +} + +#endif // DO_NOT_DOCUMENT #endif diff --git a/taglib/toolkit/tstring.h b/taglib/toolkit/tstring.h index d599107d..3da8814b 100644 --- a/taglib/toolkit/tstring.h +++ b/taglib/toolkit/tstring.h @@ -520,7 +520,7 @@ namespace TagLib { static const Type WCharByteOrder; class StringPrivate; - TAGLIB_SHARED_PTR d; + RefCountPtr d; }; /*! diff --git a/tests/test_smartptr.cpp b/tests/test_smartptr.cpp index cb481684..49165d07 100644 --- a/tests/test_smartptr.cpp +++ b/tests/test_smartptr.cpp @@ -26,7 +26,7 @@ public: void testSharedptrBasic() { int * ip = new int; - TAGLIB_SHARED_PTR cp ( ip ); + RefCountPtr cp ( ip ); CPPUNIT_ASSERT( ip == cp.get() ); CPPUNIT_ASSERT( cp.use_count() == 1 ); @@ -36,7 +36,7 @@ public: ck( static_cast(cp.get()), 54321 ); ck( static_cast(ip), *cp ); - TAGLIB_SHARED_PTR cp2 ( cp ); + RefCountPtr cp2 ( cp ); CPPUNIT_ASSERT( ip == cp2.get() ); CPPUNIT_ASSERT( cp.use_count() == 2 ); CPPUNIT_ASSERT( cp2.use_count() == 2 ); @@ -46,7 +46,7 @@ public: ck( static_cast(cp2.get()), 54321 ); ck( static_cast(ip), *cp2 ); - TAGLIB_SHARED_PTR cp3 ( cp ); + RefCountPtr cp3 ( cp ); CPPUNIT_ASSERT( cp.use_count() == 3 ); CPPUNIT_ASSERT( cp2.use_count() == 3 ); CPPUNIT_ASSERT( cp3.use_count() == 3 ); @@ -76,16 +76,16 @@ public: CPPUNIT_ASSERT( cp.use_count() == 3 ); CPPUNIT_ASSERT( *cp == 87654 ); - TAGLIB_SHARED_PTR cp4; + RefCountPtr cp4; swap( cp2, cp4 ); CPPUNIT_ASSERT( cp4.use_count() == 3 ); CPPUNIT_ASSERT( *cp4 == 87654 ); CPPUNIT_ASSERT( cp2.get() == 0 ); - std::set< TAGLIB_SHARED_PTR > scp; + std::set< RefCountPtr > scp; scp.insert(cp4); CPPUNIT_ASSERT( scp.find(cp4) != scp.end() ); - CPPUNIT_ASSERT( scp.find(cp4) == scp.find( TAGLIB_SHARED_PTR(cp4) ) ); + CPPUNIT_ASSERT( scp.find(cp4) == scp.find( RefCountPtr(cp4) ) ); } private: @@ -130,7 +130,7 @@ public: derivedDestructorCalled = false; { - TAGLIB_SHARED_PTR p1(new DummyDerived(100)); + RefCountPtr p1(new DummyDerived(100)); CPPUNIT_ASSERT(p1->getValue() == 100); } @@ -141,8 +141,8 @@ public: derivedDestructorCalled = false; { - TAGLIB_SHARED_PTR p1(new DummyDerived(100)); - TAGLIB_SHARED_PTR p2 = p1; + RefCountPtr p1(new DummyDerived(100)); + RefCountPtr p2 = p1; CPPUNIT_ASSERT(p1->getValue() == 100); CPPUNIT_ASSERT(p2->getValue() == 100); @@ -155,8 +155,8 @@ public: derivedDestructorCalled = false; { - TAGLIB_SHARED_PTR p1; - TAGLIB_SHARED_PTR p2; + RefCountPtr p1; + RefCountPtr p2; p1.reset(new DummyDerived(100)); p2 = p1; @@ -171,7 +171,7 @@ public: private: class DummyIncomplete; - TAGLIB_SHARED_PTR pincomplete; + RefCountPtr pincomplete; class DummyIncomplete {