mirror of
https://github.com/taglib/taglib.git
synced 2025-11-15 22:23:05 -05:00
Merge pull request #200 from TsudaKageyu/smartptr
Redefined smart pointer classes in safer way
This commit is contained in:
@ -213,7 +213,7 @@ check_cxx_source_compiles("
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <memory>
|
||||
int main() { std::tr1::shared_ptr<int> x; return 0; }
|
||||
int main() { std::shared_ptr<int> 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<T> or scoped_ptr<T> is defined regardless of C++11 support.
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <memory>
|
||||
int main() { std::unique_ptr<int> x; return 0; }
|
||||
" TAGLIB_USE_STD_UNIQUE_PTR)
|
||||
|
||||
if(NOT TAGLIB_USE_STD_UNIQUE_PTR)
|
||||
check_cxx_source_compiles("
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
int main() { boost::scoped_ptr<int> x; return 0; }
|
||||
" TAGLIB_USE_BOOST_SCOPED_PTR)
|
||||
endif()
|
||||
|
||||
# Determine whether CppUnit is installed.
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
||||
|
||||
@ -205,7 +205,7 @@ namespace TagLib
|
||||
ByteVector render(const String &name, int kind = 0) const;
|
||||
|
||||
class AttributePrivate;
|
||||
TAGLIB_SHARED_PTR<AttributePrivate> d;
|
||||
RefCountPtr<AttributePrivate> d;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -231,7 +231,7 @@ namespace TagLib
|
||||
#endif
|
||||
private:
|
||||
class PicturePrivate;
|
||||
TAGLIB_SHARED_PTR<PicturePrivate> d;
|
||||
RefCountPtr<PicturePrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ class FileRef::FileRefPrivate
|
||||
public:
|
||||
FileRefPrivate(File *f) : file(f) {}
|
||||
|
||||
TAGLIB_SHARED_PTR<File> file;
|
||||
RefCountPtr<File> file;
|
||||
|
||||
static List<const FileTypeResolver *> fileTypeResolvers;
|
||||
};
|
||||
|
||||
@ -282,7 +282,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class FileRefPrivate;
|
||||
TAGLIB_SHARED_PTR<FileRefPrivate> d;
|
||||
RefCountPtr<FileRefPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace TagLib
|
||||
|
||||
@ -66,7 +66,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class CoverArtPrivate;
|
||||
TAGLIB_SHARED_PTR<CoverArtPrivate> d;
|
||||
RefCountPtr<CoverArtPrivate> d;
|
||||
};
|
||||
|
||||
typedef List<CoverArt> CoverArtList;
|
||||
|
||||
@ -97,7 +97,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class ItemPrivate;
|
||||
TAGLIB_SHARED_PTR<ItemPrivate> d;
|
||||
RefCountPtr<ItemPrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ namespace TagLib {
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
class HeaderPrivate;
|
||||
TAGLIB_SHARED_PTR<HeaderPrivate> d;
|
||||
RefCountPtr<HeaderPrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ namespace TagLib {
|
||||
void read(const ByteVector &data);
|
||||
|
||||
class PropertiesPrivate;
|
||||
TAGLIB_SHARED_PTR<PropertiesPrivate> d;
|
||||
RefCountPtr<PropertiesPrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 <memory> / std::shared_ptr<T>
|
||||
#cmakedefine TAGLIB_USE_TR1_SHARED_PTR 1 // #include <tr1/memory> / std::tr1::shared_ptr<T>
|
||||
#cmakedefine TAGLIB_USE_BOOST_SHARED_PTR 1 // #include <boost/shared_ptr.hpp> / boost::shared_ptr<T>
|
||||
|
||||
/* Defined if your compiler supports unique_ptr or scoped_ptr */
|
||||
#cmakedefine TAGLIB_USE_STD_UNIQUE_PTR 1 // #include <memory> / std::unique_ptr<T>
|
||||
#cmakedefine TAGLIB_USE_BOOST_SCOPED_PTR 1 // #include <boost/scoped_ptr.hpp> / boost::scoped_ptr<T>
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ using namespace TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef std::vector<TAGLIB_SHARED_PTR<Tag> > TagVector;
|
||||
typedef std::vector<RefCountPtr<Tag> > TagVector;
|
||||
typedef TagVector::iterator TagIterator;
|
||||
typedef TagVector::const_iterator TagConstIterator;
|
||||
}
|
||||
@ -66,7 +66,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<TAGLIB_SHARED_PTR<Tag> > tags;
|
||||
TagVector tags;
|
||||
};
|
||||
|
||||
TagUnion::TagUnion(size_t count)
|
||||
|
||||
@ -89,7 +89,7 @@ namespace TagLib {
|
||||
TagUnion &operator=(const Tag &);
|
||||
|
||||
class TagUnionPrivate;
|
||||
TAGLIB_SHARED_PTR<TagUnionPrivate> d;
|
||||
NonRefCountPtr<TagUnionPrivate> d;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -363,7 +363,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ByteVectorPrivate(TAGLIB_SHARED_PTR<ByteVectorPrivate> d, size_t o, size_t l)
|
||||
ByteVectorPrivate(RefCountPtr<ByteVectorPrivate> 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<std::vector<char> > data;
|
||||
RefCountPtr<std::vector<char> > data;
|
||||
size_t offset;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
@ -551,7 +551,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class ByteVectorPrivate;
|
||||
TAGLIB_SHARED_PTR<ByteVectorPrivate> d;
|
||||
RefCountPtr<ByteVectorPrivate> d;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@ -305,7 +305,7 @@ namespace TagLib {
|
||||
private:
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
template <class TP> class ListPrivate;
|
||||
TAGLIB_SHARED_PTR<ListPrivate<T> > d;
|
||||
RefCountPtr<ListPrivate<T> > d;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -219,7 +219,7 @@ namespace TagLib {
|
||||
private:
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
template <class KeyP, class TP> class MapPrivate;
|
||||
TAGLIB_SHARED_PTR<MapPrivate<Key, T> > d;
|
||||
RefCountPtr<MapPrivate<Key, T> > d;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -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 <algorithm>
|
||||
|
||||
#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 <b>is not</b> 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<T> if shared_ptr<T> is not available.
|
||||
// I STRONGLY RECOMMEND using standard shared_ptr<T> 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<typename T>
|
||||
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<long>(count.count());
|
||||
}
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
private:
|
||||
RefCounter count;
|
||||
};
|
||||
|
||||
// Counter impl class. Provides a dynamic deleter.
|
||||
|
||||
template <typename U>
|
||||
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 <typename U>
|
||||
explicit RefCountPtr(U *p)
|
||||
: counter(new CounterImpl<U>(p))
|
||||
{
|
||||
}
|
||||
|
||||
RefCountPtr(const RefCountPtr<T> &x)
|
||||
: counter(x.counter)
|
||||
{
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr(const RefCountPtr<U> &x)
|
||||
: counter(reinterpret_cast<CounterBase*>(x.counter))
|
||||
{
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
|
||||
~RefCountPtr()
|
||||
{
|
||||
if(counter)
|
||||
counter->release();
|
||||
}
|
||||
|
||||
T *get() const
|
||||
{
|
||||
if(counter)
|
||||
return static_cast<CounterImpl<T>*>(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 <typename U>
|
||||
void reset(U *p)
|
||||
{
|
||||
if(get() != p)
|
||||
RefCountPtr<T>(p).swap(*this);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
RefCountPtr<T>().swap(*this);
|
||||
}
|
||||
|
||||
void swap(RefCountPtr<T> &x)
|
||||
{
|
||||
std::swap(counter, x.counter);
|
||||
}
|
||||
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<T> &x)
|
||||
{
|
||||
if(get() != x.get()) {
|
||||
if(counter)
|
||||
counter->release();
|
||||
|
||||
counter = x.counter;
|
||||
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<U> &x)
|
||||
{
|
||||
if(get() != x.get()) {
|
||||
if(counter)
|
||||
counter->release();
|
||||
|
||||
counter = reinterpret_cast<CounterBase*>(x.counter);
|
||||
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
bool operator==(const RefCountPtr<T> &x) const
|
||||
{
|
||||
return (get() == x.get());
|
||||
}
|
||||
|
||||
bool operator!=(const RefCountPtr<T> &x) const
|
||||
{
|
||||
return !operator==(x);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (get() != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable CounterBase *counter;
|
||||
|
||||
template <typename U> friend class RefCountPtr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void swap(RefCountPtr<T> &a, RefCountPtr<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
#endif // TAGLIB_USE_*_SHARED_PTR
|
||||
}
|
||||
#endif // DO_NOT_DOCUMENT
|
||||
|
||||
#endif
|
||||
@ -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 <atomic>
|
||||
@ -66,41 +72,44 @@
|
||||
|
||||
namespace TagLib
|
||||
{
|
||||
class RefCounter::RefCounterPrivate
|
||||
class CounterBase::CounterBasePrivate
|
||||
{
|
||||
public:
|
||||
RefCounterPrivate() : refCount(1) {}
|
||||
|
||||
size_t ref() { return static_cast<size_t>(ATOMIC_INC(refCount)); }
|
||||
size_t deref() { return static_cast<size_t>(ATOMIC_DEC(refCount)); }
|
||||
size_t count() const { return static_cast<size_t>(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<long>(d->refCount);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -27,28 +27,577 @@
|
||||
#define TAGLIB_SMARTPTR_H
|
||||
|
||||
#include "taglib_config.h"
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(TAGLIB_USE_STD_SHARED_PTR)
|
||||
# include <memory>
|
||||
#elif defined(TAGLIB_USE_TR1_SHARED_PTR)
|
||||
# include <tr1/memory>
|
||||
#elif defined(TAGLIB_USE_BOOST_SHARED_PTR)
|
||||
# include <boost/shared_ptr.hpp>
|
||||
#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 <boost/shared_ptr.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(TAGLIB_USE_STD_UNIQUE_PTR)
|
||||
# include <memory>
|
||||
#elif defined(TAGLIB_USE_BOOST_SCOPED_PTR)
|
||||
# include <boost/scoped_ptr.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
|
||||
/*!
|
||||
* \warning This <b>is not</b> 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<T> is just a thin wrapper of shared_ptr<T>.
|
||||
// It will be optimized out by compilers and performs equivalent to them.
|
||||
|
||||
template <typename T>
|
||||
class RefCountPtr
|
||||
{
|
||||
public:
|
||||
RefCountPtr()
|
||||
: sp()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit RefCountPtr(U *p)
|
||||
: sp(p)
|
||||
{
|
||||
}
|
||||
|
||||
RefCountPtr(const RefCountPtr<T> &x)
|
||||
: sp(x.sp)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr(const RefCountPtr<U> &x)
|
||||
: sp(x.sp)
|
||||
{
|
||||
}
|
||||
|
||||
# ifdef TAGLIB_USE_MOVE_SEMANTICS
|
||||
|
||||
RefCountPtr(RefCountPtr<T> &&x)
|
||||
: sp(std::move(x.sp))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr(RefCountPtr<U> &&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 <typename U>
|
||||
void reset(U *p)
|
||||
{
|
||||
sp.reset(p);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
sp.reset();
|
||||
}
|
||||
|
||||
void swap(RefCountPtr<T> &x)
|
||||
{
|
||||
sp.swap(x.sp);
|
||||
}
|
||||
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<T> &x)
|
||||
{
|
||||
sp = x.sp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<U> &x)
|
||||
{
|
||||
sp = x.sp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
# ifdef TAGLIB_USE_MOVE_SEMANTICS
|
||||
|
||||
RefCountPtr<T> &operator=(RefCountPtr<T> &&x)
|
||||
{
|
||||
sp = std::move(x.sp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr<T> &operator=(RefCountPtr<U> &&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<bool>(sp);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !static_cast<bool>(sp);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename U> friend class RefCountPtr;
|
||||
|
||||
# if defined(TAGLIB_USE_STD_SHARED_PTR)
|
||||
|
||||
std::shared_ptr<T> sp;
|
||||
|
||||
# elif defined(TAGLIB_USE_TR1_SHARED_PTR)
|
||||
|
||||
std::tr1::shared_ptr<T> sp;
|
||||
|
||||
# else
|
||||
|
||||
boost::shared_ptr<T> sp;
|
||||
|
||||
# endif
|
||||
};
|
||||
|
||||
#else // TAGLIB_USE_STD_SHARED_PTR etc.
|
||||
|
||||
// Self-implements RefCountPtr<T> if shared_ptr<T> is not available.
|
||||
// I STRONGLY RECOMMEND using standard shared_ptr<T> 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 <typename T>
|
||||
class CounterImpl : public CounterBase
|
||||
{
|
||||
public:
|
||||
CounterImpl(T *p)
|
||||
: p(p)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dispose()
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
T *get() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
T *p;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RefCountPtr
|
||||
{
|
||||
public:
|
||||
RefCountPtr()
|
||||
: px(0)
|
||||
, counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit RefCountPtr(U *p)
|
||||
: px(p)
|
||||
, counter(new CounterImpl<U>(p))
|
||||
{
|
||||
}
|
||||
|
||||
RefCountPtr(const RefCountPtr<T> &x)
|
||||
: px(x.px)
|
||||
, counter(x.counter)
|
||||
{
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr(const RefCountPtr<U> &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 <typename U>
|
||||
void reset(U *p)
|
||||
{
|
||||
if(px != p)
|
||||
RefCountPtr<T>(p).swap(*this);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
RefCountPtr<T>().swap(*this);
|
||||
}
|
||||
|
||||
void swap(RefCountPtr<T> &x)
|
||||
{
|
||||
std::swap(px, x.px);
|
||||
std::swap(counter, x.counter);
|
||||
}
|
||||
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<T> &x)
|
||||
{
|
||||
if(px != x.px) {
|
||||
if(counter)
|
||||
counter->release();
|
||||
|
||||
px = x.px;
|
||||
counter = x.counter;
|
||||
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr<T> &operator=(const RefCountPtr<U> &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 <typename U> friend class RefCountPtr;
|
||||
};
|
||||
|
||||
#endif // TAGLIB_USE_STD_SHARED_PTR etc.
|
||||
|
||||
#if defined(TAGLIB_USE_STD_UNIQUE_PTR) || defined(TAGLIB_USE_BOOST_SCOPED_PTR)
|
||||
|
||||
// NonRefCountPtr<T> is just a thin wrapper of unique_ptr<T> or scoped_ptr<T>.
|
||||
// It will be optimized out by compilers and performs equivalent to them.
|
||||
|
||||
template<typename T>
|
||||
class NonRefCountPtr
|
||||
{
|
||||
public:
|
||||
explicit NonRefCountPtr(T *p = 0)
|
||||
: up(p)
|
||||
{
|
||||
}
|
||||
|
||||
~NonRefCountPtr()
|
||||
{
|
||||
}
|
||||
|
||||
void reset(T *p = 0)
|
||||
{
|
||||
NonRefCountPtr<T>(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<bool>(up);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !static_cast<bool>(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<T> up;
|
||||
|
||||
# else
|
||||
|
||||
boost::scoped_ptr<T> up;
|
||||
|
||||
# endif
|
||||
};
|
||||
|
||||
#else // TAGLIB_USE_STD_UNIQUE_PTR
|
||||
|
||||
// Self-implements NonRefCountPtr<T> if unique_ptr<T> is not available.
|
||||
// I STRONGLY RECOMMEND using standard unique_ptr<T> rather than this class.
|
||||
|
||||
template<typename T>
|
||||
class NonRefCountPtr
|
||||
{
|
||||
public:
|
||||
explicit NonRefCountPtr(T *p = 0)
|
||||
: px(p)
|
||||
{
|
||||
}
|
||||
|
||||
~NonRefCountPtr()
|
||||
{
|
||||
delete px;
|
||||
}
|
||||
|
||||
void reset(T *p = 0)
|
||||
{
|
||||
NonRefCountPtr<T>(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 <typename T, typename U>
|
||||
bool operator==(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
|
||||
{
|
||||
return (a.get() == b.get());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const RefCountPtr<T> &a, const RefCountPtr<U> &b)
|
||||
{
|
||||
return (a.get() != b.get());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const RefCountPtr<T> &a, U *b)
|
||||
{
|
||||
return (a.get() == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const RefCountPtr<T> &a, U *b)
|
||||
{
|
||||
return (a.get() != b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const NonRefCountPtr<T> &a, U *b)
|
||||
{
|
||||
return (a.get() == b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const NonRefCountPtr<T> &a, U *b)
|
||||
{
|
||||
return (a.get() != b);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(T *a, const RefCountPtr<U> &b)
|
||||
{
|
||||
return (a == b.get());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(T *a, const RefCountPtr<U> &b)
|
||||
{
|
||||
return (a != b.get());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(T *a, const NonRefCountPtr<U> &b)
|
||||
{
|
||||
return (a == b.get());
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(T *a, const NonRefCountPtr<U> &b)
|
||||
{
|
||||
return (a != b.get());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void swap(RefCountPtr<T> &a, RefCountPtr<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void swap(NonRefCountPtr<T> &a, NonRefCountPtr<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DO_NOT_DOCUMENT
|
||||
#endif
|
||||
|
||||
@ -520,7 +520,7 @@ namespace TagLib {
|
||||
static const Type WCharByteOrder;
|
||||
|
||||
class StringPrivate;
|
||||
TAGLIB_SHARED_PTR<StringPrivate> d;
|
||||
RefCountPtr<StringPrivate> d;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@ -26,7 +26,7 @@ public:
|
||||
void testSharedptrBasic()
|
||||
{
|
||||
int * ip = new int;
|
||||
TAGLIB_SHARED_PTR<int> cp ( ip );
|
||||
RefCountPtr<int> cp ( ip );
|
||||
CPPUNIT_ASSERT( ip == cp.get() );
|
||||
CPPUNIT_ASSERT( cp.use_count() == 1 );
|
||||
|
||||
@ -36,7 +36,7 @@ public:
|
||||
ck( static_cast<int*>(cp.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp );
|
||||
|
||||
TAGLIB_SHARED_PTR<int> cp2 ( cp );
|
||||
RefCountPtr<int> 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<int*>(cp2.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp2 );
|
||||
|
||||
TAGLIB_SHARED_PTR<int> cp3 ( cp );
|
||||
RefCountPtr<int> 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<int> cp4;
|
||||
RefCountPtr<int> cp4;
|
||||
swap( cp2, cp4 );
|
||||
CPPUNIT_ASSERT( cp4.use_count() == 3 );
|
||||
CPPUNIT_ASSERT( *cp4 == 87654 );
|
||||
CPPUNIT_ASSERT( cp2.get() == 0 );
|
||||
|
||||
std::set< TAGLIB_SHARED_PTR<int> > scp;
|
||||
std::set< RefCountPtr<int> > scp;
|
||||
scp.insert(cp4);
|
||||
CPPUNIT_ASSERT( scp.find(cp4) != scp.end() );
|
||||
CPPUNIT_ASSERT( scp.find(cp4) == scp.find( TAGLIB_SHARED_PTR<int>(cp4) ) );
|
||||
CPPUNIT_ASSERT( scp.find(cp4) == scp.find( RefCountPtr<int>(cp4) ) );
|
||||
}
|
||||
|
||||
private:
|
||||
@ -130,7 +130,7 @@ public:
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyBase> p1(new DummyDerived(100));
|
||||
RefCountPtr<DummyBase> p1(new DummyDerived(100));
|
||||
CPPUNIT_ASSERT(p1->getValue() == 100);
|
||||
}
|
||||
|
||||
@ -141,8 +141,8 @@ public:
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyDerived> p1(new DummyDerived(100));
|
||||
TAGLIB_SHARED_PTR<DummyBase> p2 = p1;
|
||||
RefCountPtr<DummyDerived> p1(new DummyDerived(100));
|
||||
RefCountPtr<DummyBase> p2 = p1;
|
||||
|
||||
CPPUNIT_ASSERT(p1->getValue() == 100);
|
||||
CPPUNIT_ASSERT(p2->getValue() == 100);
|
||||
@ -155,8 +155,8 @@ public:
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyDerived> p1;
|
||||
TAGLIB_SHARED_PTR<DummyBase> p2;
|
||||
RefCountPtr<DummyDerived> p1;
|
||||
RefCountPtr<DummyBase> p2;
|
||||
|
||||
p1.reset(new DummyDerived(100));
|
||||
p2 = p1;
|
||||
@ -171,7 +171,7 @@ public:
|
||||
|
||||
private:
|
||||
class DummyIncomplete;
|
||||
TAGLIB_SHARED_PTR<DummyIncomplete> pincomplete;
|
||||
RefCountPtr<DummyIncomplete> pincomplete;
|
||||
|
||||
class DummyIncomplete
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user