mirror of
https://github.com/taglib/taglib.git
synced 2025-06-04 01:28:21 -04:00
Improved reference-counted pointer
This commit is contained in:
parent
82e616101a
commit
36ceaadfaa
@ -6,60 +6,103 @@ include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
# check for libz using the cmake supplied FindZLIB.cmake
|
||||
find_package(ZLIB)
|
||||
if(ZLIB_FOUND)
|
||||
set(HAVE_ZLIB 1)
|
||||
else()
|
||||
set(HAVE_ZLIB 0)
|
||||
endif()
|
||||
|
||||
# Determine whether or not your compiler supports move semantics.
|
||||
check_cxx_source_compiles("
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic error \"-Wc++11-extensions\"
|
||||
#endif
|
||||
#include <utility>
|
||||
int func(int &&x) { return x - 1; }
|
||||
int main() { return func(std::move(1)); }
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic error \"-Wc++11-extensions\"
|
||||
#endif
|
||||
#include <utility>
|
||||
int func(int &&x) { return x - 1; }
|
||||
int main() { return func(std::move(1)); }
|
||||
" SUPPORT_MOVE_SEMANTICS)
|
||||
|
||||
# Determine whether or not your compiler supports template alias.
|
||||
check_cxx_source_compiles("
|
||||
#ifdef __clang__
|
||||
# pragma clang diagnostic error \"-Wc++11-extensions\"
|
||||
#endif
|
||||
#include <vector>
|
||||
template <typename T> using myVector = std::vector<T>;
|
||||
int main() { return 0; }
|
||||
" SUPPORT_TEMPLATE_ALIAS)
|
||||
|
||||
# Determine where shared_ptr<T> is defined regardless of C++11 support.
|
||||
check_cxx_source_compiles("
|
||||
#include <memory>
|
||||
int main() { std::tr1::shared_ptr<int> x; return 0; }
|
||||
#include <memory>
|
||||
int main() { std::tr1::shared_ptr<int> x; return 0; }
|
||||
" HAVE_STD_SHARED_PTR)
|
||||
|
||||
check_cxx_source_compiles("
|
||||
if(NOT HAVE_STD_SHARED_PTR)
|
||||
check_cxx_source_compiles("
|
||||
#include <tr1/memory>
|
||||
int main() { std::tr1::shared_ptr<int> x; return 0; }
|
||||
" HAVE_TR1_SHARED_PTR)
|
||||
" HAVE_TR1_SHARED_PTR)
|
||||
|
||||
if(NOT HAVE_TR1_SHARED_PTR)
|
||||
check_cxx_source_compiles("
|
||||
#include <boost/shared_ptr.hpp>
|
||||
int main() { boost::shared_ptr<int> x; return 0; }
|
||||
" HAVE_BOOST_SHARED_PTR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Determine which kind of atomic operations your compiler supports.
|
||||
if(NOT HAVE_STD_SHARED_PTR AND NOT HAVE_TR1_SHARED_PTR AND NOT HAVE_BOOST_SHARED_PTR)
|
||||
check_cxx_source_compiles("
|
||||
int main() {
|
||||
volatile int x;
|
||||
__sync_add_and_fetch(&x, 1);
|
||||
int y = __sync_sub_and_fetch(&x, 1);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_GCC_ATOMIC)
|
||||
|
||||
if(NOT HAVE_GCC_ATOMIC)
|
||||
check_cxx_source_compiles("
|
||||
#include <libkern/OSAtomic.h>
|
||||
int main() {
|
||||
volatile int32_t x;
|
||||
OSAtomicIncrement32Barrier(&x);
|
||||
int32_t y = OSAtomicDecrement32Barrier(&x);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_MAC_ATOMIC)
|
||||
|
||||
if(NOT HAVE_MAC_ATOMIC)
|
||||
check_cxx_source_compiles("
|
||||
#include <windows.h>
|
||||
int main() {
|
||||
volatile LONG x;
|
||||
InterlockedIncrement(&x);
|
||||
LONG y = InterlockedDecrement(&x);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_WIN_ATOMIC)
|
||||
|
||||
if(NOT HAVE_WIN_ATOMIC)
|
||||
check_cxx_source_compiles("
|
||||
#include <ia64intrin.h>
|
||||
int main() {
|
||||
volatile int x;
|
||||
__sync_add_and_fetch(&x, 1);
|
||||
int y = __sync_sub_and_fetch(&x, 1);
|
||||
return 0;
|
||||
}
|
||||
" HAVE_IA64_ATOMIC)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_cxx_source_compiles("
|
||||
#include <boost/shared_ptr.hpp>
|
||||
int main() { boost::shared_ptr<int> x; return 0; }
|
||||
" HAVE_BOOST_SHARED_PTR)
|
||||
|
||||
# Determine whether your compiler supports codecvt header.
|
||||
check_cxx_source_compiles("
|
||||
#include <codecvt>
|
||||
int main() { std::codecvt_utf8_utf16<wchar_t> x; return 0; }
|
||||
#include <codecvt>
|
||||
int main() { std::codecvt_utf8_utf16<wchar_t> x; return 0; }
|
||||
" HAVE_CODECVT)
|
||||
|
||||
# check for libz using the cmake supplied FindZLIB.cmake
|
||||
find_package(ZLIB)
|
||||
if(ZLIB_FOUND)
|
||||
set(HAVE_ZLIB 1)
|
||||
else()
|
||||
set(HAVE_ZLIB 0)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||
find_package(CppUnit)
|
||||
if(NOT CppUnit_FOUND AND BUILD_TESTS)
|
||||
message(STATUS "CppUnit not found, disabling tests.")
|
||||
set(BUILD_TESTS OFF)
|
||||
message(STATUS "CppUnit not found, disabling tests.")
|
||||
set(BUILD_TESTS OFF)
|
||||
endif()
|
||||
|
||||
|
@ -1,22 +1,25 @@
|
||||
/* config-taglib.h. Generated by cmake from config-taglib.h.cmake */
|
||||
|
||||
/* Define if you have libz */
|
||||
#cmakedefine HAVE_ZLIB 1
|
||||
|
||||
/* Defined if your compiler supports the move semantics */
|
||||
#cmakedefine SUPPORT_MOVE_SEMANTICS 1
|
||||
|
||||
/* Defined if your compiler supports the template alias */
|
||||
#cmakedefine SUPPORT_TEMPLATE_ALIAS 1
|
||||
|
||||
/* Defined if your compiler supports shared_ptr */
|
||||
#cmakedefine HAVE_STD_SHARED_PTR 1
|
||||
#cmakedefine HAVE_TR1_SHARED_PTR 1
|
||||
#cmakedefine HAVE_BOOST_SHARED_PTR 1
|
||||
|
||||
/* Defined if your compiler supports some atomic operations */
|
||||
#cmakedefine HAVE_GCC_ATOMIC 1
|
||||
#cmakedefine HAVE_MAC_ATOMIC 1
|
||||
#cmakedefine HAVE_WIN_ATOMIC 1
|
||||
#cmakedefine HAVE_IA64_ATOMIC 1
|
||||
|
||||
/* Defined if your compiler has <codecvt> header */
|
||||
#cmakedefine HAVE_CODECVT 1
|
||||
|
||||
/* Define if you have libz */
|
||||
#cmakedefine HAVE_ZLIB 1
|
||||
|
||||
#cmakedefine NO_ITUNES_HACKS 1
|
||||
#cmakedefine WITH_ASF 1
|
||||
#cmakedefine WITH_MP4 1
|
||||
|
@ -205,7 +205,7 @@ namespace TagLib
|
||||
ByteVector render(const String &name, int kind = 0) const;
|
||||
|
||||
class AttributePrivate;
|
||||
RefCountPtr<AttributePrivate> d;
|
||||
TAGLIB_SHARED_PTR<AttributePrivate> d;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,7 @@ namespace TagLib
|
||||
#endif
|
||||
private:
|
||||
class PicturePrivate;
|
||||
RefCountPtr<PicturePrivate> d;
|
||||
TAGLIB_SHARED_PTR<PicturePrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class FileRef::FileRefPrivate
|
||||
public:
|
||||
FileRefPrivate(File *f) : file(f) {}
|
||||
|
||||
RefCountPtr<File> file;
|
||||
TAGLIB_SHARED_PTR<File> file;
|
||||
|
||||
static List<const FileTypeResolver *> fileTypeResolvers;
|
||||
};
|
||||
|
@ -278,7 +278,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class FileRefPrivate;
|
||||
RefCountPtr<FileRefPrivate> d;
|
||||
TAGLIB_SHARED_PTR<FileRefPrivate> d;
|
||||
};
|
||||
|
||||
} // namespace TagLib
|
||||
|
@ -66,7 +66,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class CoverArtPrivate;
|
||||
RefCountPtr<CoverArtPrivate> d;
|
||||
TAGLIB_SHARED_PTR<CoverArtPrivate> d;
|
||||
};
|
||||
|
||||
typedef List<CoverArt> CoverArtList;
|
||||
|
@ -97,7 +97,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class ItemPrivate;
|
||||
RefCountPtr<ItemPrivate> d;
|
||||
TAGLIB_SHARED_PTR<ItemPrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ namespace TagLib {
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
class HeaderPrivate;
|
||||
RefCountPtr<HeaderPrivate> d;
|
||||
TAGLIB_SHARED_PTR<HeaderPrivate> d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ByteVectorPrivate(RefCountPtr<ByteVectorPrivate> d, size_t o, size_t l)
|
||||
ByteVectorPrivate(TAGLIB_SHARED_PTR<ByteVectorPrivate> d, size_t o, size_t l)
|
||||
: data(d->data)
|
||||
, offset(d->offset + o)
|
||||
, length(l)
|
||||
@ -320,7 +320,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefCountPtr<DataPrivate> data;
|
||||
TAGLIB_SHARED_PTR<DataPrivate> data;
|
||||
size_t offset;
|
||||
size_t length;
|
||||
};
|
||||
|
@ -478,7 +478,7 @@ namespace TagLib {
|
||||
|
||||
private:
|
||||
class ByteVectorPrivate;
|
||||
RefCountPtr<ByteVectorPrivate> d;
|
||||
TAGLIB_SHARED_PTR<ByteVectorPrivate> d;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -305,7 +305,7 @@ namespace TagLib {
|
||||
private:
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
template <class TP> class ListPrivate;
|
||||
RefCountPtr<ListPrivate<T> > d;
|
||||
TAGLIB_SHARED_PTR<ListPrivate<T> > d;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -219,7 +219,7 @@ namespace TagLib {
|
||||
private:
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
template <class KeyP, class TP> class MapPrivate;
|
||||
RefCountPtr<MapPrivate<Key, T> > d;
|
||||
TAGLIB_SHARED_PTR<MapPrivate<Key, T> > d;
|
||||
|
||||
#endif
|
||||
};
|
||||
|
@ -37,19 +37,33 @@
|
||||
#elif defined(HAVE_BOOST_SHARED_PTR)
|
||||
# include <boost/shared_ptr.hpp>
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# include <libkern/OSAtomic.h>
|
||||
# define TAGLIB_ATOMIC_MAC
|
||||
# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
# define TAGLIB_ATOMIC_WIN
|
||||
# elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \
|
||||
&& (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
|
||||
defined(__i686__) || defined(__x86_64) || defined(__ia64)) \
|
||||
&& !defined(__INTEL_COMPILER)
|
||||
# define TAGLIB_ATOMIC_GCC
|
||||
# elif defined(__ia64) && defined(__INTEL_COMPILER)
|
||||
# include <ia64intrin.h>
|
||||
# define TAGLIB_ATOMIC_GCC
|
||||
# include <algorithm>
|
||||
# if defined(HAVE_GCC_ATOMIC)
|
||||
# define TAGLIB_ATOMIC_INT int
|
||||
# define TAGLIB_ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
|
||||
# define TAGLIB_ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
|
||||
# elif defined(HAVE_WIN_ATOMIC)
|
||||
# if !defined(NOMINMAX)
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# define TAGLIB_ATOMIC_INT long
|
||||
# define TAGLIB_ATOMIC_INC(x) InterlockedIncrement(&x)
|
||||
# define TAGLIB_ATOMIC_DEC(x) InterlockedDecrement(&x)
|
||||
# elif defined(HAVE_MAC_ATOMIC)
|
||||
# include <libkern/OSAtomic.h>
|
||||
# define TAGLIB_ATOMIC_INT int32_t
|
||||
# define TAGLIB_ATOMIC_INC(x) OSAtomicIncrement32Barrier(&x)
|
||||
# define TAGLIB_ATOMIC_DEC(x) OSAtomicDecrement32Barrier(&x)
|
||||
# elif defined(HAVE_IA64_ATOMIC)
|
||||
# include <ia64intrin.h>
|
||||
# define TAGLIB_ATOMIC_INT int
|
||||
# define TAGLIB_ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
|
||||
# define TAGLIB_ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1)
|
||||
# else
|
||||
# define TAGLIB_ATOMIC_INT int
|
||||
# define TAGLIB_ATOMIC_INC(x) (++x)
|
||||
# define TAGLIB_ATOMIC_DEC(x) (--x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -63,55 +77,18 @@
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
#if defined(HAVE_STD_SHARED_PTR) || defined(HAVE_TR1_SHARED_PTR) || defined(HAVE_BOOST_SHARED_PTR)
|
||||
#if defined(HAVE_STD_SHARED_PTR) || defined(HAVE_TR1_SHARED_PTR)
|
||||
|
||||
#define TAGLIB_SHARED_PTR std::tr1::shared_ptr
|
||||
|
||||
# if defined(SUPPORT_TEMPLATE_ALIAS)
|
||||
#elif defined(HAVE_BOOST_SHARED_PTR)
|
||||
|
||||
// Defines RefCountPtr<T> as an alias of shared_ptr<T>
|
||||
// if shared_ptr<T> and the template alias are both available.
|
||||
|
||||
# if defined(HAVE_STD_SHARED_PTR) || defined(HAVE_TR1_SHARED_PTR)
|
||||
|
||||
template <typename T>
|
||||
using RefCountPtr = std::tr1::shared_ptr<T>;
|
||||
|
||||
# else
|
||||
|
||||
template <typename T>
|
||||
using RefCountPtr = boost::shared_ptr<T>;
|
||||
|
||||
# endif
|
||||
|
||||
# else
|
||||
|
||||
// Defines RefCountPtr<T> as a derived class of shared_ptr<T>.
|
||||
// if shared_ptr<T> is available but the template alias is not.
|
||||
|
||||
# if defined(HAVE_STD_SHARED_PTR) || defined(HAVE_TR1_SHARED_PTR)
|
||||
|
||||
template <typename T>
|
||||
class RefCountPtr : public std::tr1::shared_ptr<T>
|
||||
{
|
||||
public:
|
||||
explicit RefCountPtr(T *p) : std::tr1::shared_ptr<T>(p) {}
|
||||
};
|
||||
|
||||
# else
|
||||
|
||||
template <typename T>
|
||||
class RefCountPtr : public boost::shared_ptr<T>
|
||||
{
|
||||
public:
|
||||
explicit RefCountPtr(T *p) : boost::shared_ptr<T>(p) {}
|
||||
};
|
||||
|
||||
# endif
|
||||
|
||||
# endif
|
||||
#define TAGLIB_SHARED_PTR boost::shared_ptr
|
||||
|
||||
#else // HAVE_*_SHARED_PTR
|
||||
|
||||
// Implements RefCountPtr<T> if shared_ptr<T> is not available.
|
||||
// Self-implements RefCountPtr<T> if shared_ptr<T> is not available.
|
||||
// I STRONGLY RECOMMEND using standard shared_ptr<T> rather than this class.
|
||||
|
||||
template<typename T>
|
||||
class RefCountPtr
|
||||
@ -134,12 +111,12 @@ namespace TagLib {
|
||||
|
||||
void addref()
|
||||
{
|
||||
increment(&count);
|
||||
TAGLIB_ATOMIC_INC(count);
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if(decrement(&count) == 0) {
|
||||
if(TAGLIB_ATOMIC_DEC(count) == 0) {
|
||||
dispose();
|
||||
delete this;
|
||||
}
|
||||
@ -153,33 +130,7 @@ namespace TagLib {
|
||||
virtual void dispose() = 0;
|
||||
|
||||
private:
|
||||
# if defined(TAGLIB_ATOMIC_MAC)
|
||||
typedef volatile int32_t counter_t;
|
||||
|
||||
inline static void increment(counter_t *c) { OSAtomicIncrement32Barrier(c); }
|
||||
inline static counter_t decrement(counter_t *c) { return OSAtomicDecrement32Barrier(c); }
|
||||
|
||||
# elif defined(TAGLIB_ATOMIC_WIN)
|
||||
typedef volatile long counter_t;
|
||||
|
||||
inline static void increment(counter_t *c) { InterlockedIncrement(c); }
|
||||
inline static counter_t decrement(counter_t *c) { return InterlockedDecrement(c); }
|
||||
|
||||
# elif defined(TAGLIB_ATOMIC_GCC)
|
||||
typedef volatile int counter_t;
|
||||
|
||||
inline static void increment(counter_t *c) { __sync_add_and_fetch(c, 1); }
|
||||
inline static counter_t decrement(counter_t *c) { return __sync_sub_and_fetch(c, 1); }
|
||||
|
||||
# else
|
||||
typedef uint counter_t;
|
||||
|
||||
inline static void increment(counter_t *c) { ++(*c) }
|
||||
inline static counter_t decrement(counter_t *c) { return --(*c); }
|
||||
|
||||
# endif
|
||||
|
||||
counter_t count;
|
||||
volatile TAGLIB_ATOMIC_INT count;
|
||||
};
|
||||
|
||||
// Counter impl class. Provides a dynamic deleter.
|
||||
@ -208,31 +159,52 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
public:
|
||||
explicit RefCountPtr()
|
||||
: counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
explicit RefCountPtr(U *p)
|
||||
: counter(new CounterImpl<U>(p))
|
||||
{
|
||||
}
|
||||
|
||||
RefCountPtr(const RefCountPtr &x)
|
||||
RefCountPtr(const RefCountPtr<T> &x)
|
||||
: counter(x.counter)
|
||||
{
|
||||
counter = x.counter;
|
||||
counter->addref();
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RefCountPtr(const RefCountPtr<U> &x)
|
||||
: counter(reinterpret_cast<CounterBase*>(x.counter))
|
||||
{
|
||||
if(counter)
|
||||
counter->addref();
|
||||
}
|
||||
|
||||
~RefCountPtr()
|
||||
{
|
||||
counter->release();
|
||||
if(counter)
|
||||
counter->release();
|
||||
}
|
||||
|
||||
T *get() const
|
||||
{
|
||||
return static_cast<CounterImpl<T>*>(counter)->get();
|
||||
if(counter)
|
||||
return static_cast<CounterImpl<T>*>(counter)->get();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
long use_count() const
|
||||
{
|
||||
return counter->use_count();
|
||||
if(counter)
|
||||
return counter->use_count();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool unique() const
|
||||
@ -244,20 +216,44 @@ namespace TagLib {
|
||||
void reset(U *p)
|
||||
{
|
||||
if(get() != p)
|
||||
{
|
||||
counter->release();
|
||||
counter = new CounterImpl<U>(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())
|
||||
{
|
||||
counter->release();
|
||||
if(get() != x.get()) {
|
||||
if(counter)
|
||||
counter->release();
|
||||
|
||||
counter = x.counter;
|
||||
counter->addref();
|
||||
|
||||
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;
|
||||
}
|
||||
@ -288,9 +284,19 @@ namespace TagLib {
|
||||
}
|
||||
|
||||
private:
|
||||
CounterBase *counter;
|
||||
mutable CounterBase *counter;
|
||||
|
||||
template <typename U> friend class RefCountPtr;
|
||||
};
|
||||
|
||||
# define TAGLIB_SHARED_PTR TagLib::RefCountPtr
|
||||
|
||||
template <typename T>
|
||||
void swap(RefCountPtr<T> &a, RefCountPtr<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
#endif // HAVE_*_SHARED_PTR
|
||||
}
|
||||
#endif // DO_NOT_DOCUMENT
|
||||
|
@ -523,7 +523,7 @@ namespace TagLib {
|
||||
static const Type WCharByteOrder;
|
||||
|
||||
class StringPrivate;
|
||||
RefCountPtr<StringPrivate> d;
|
||||
TAGLIB_SHARED_PTR<StringPrivate> d;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -30,6 +30,7 @@ SET(test_runner_SRCS
|
||||
main.cpp
|
||||
test_list.cpp
|
||||
test_map.cpp
|
||||
test_smartptr.cpp
|
||||
test_mpeg.cpp
|
||||
test_synchdata.cpp
|
||||
test_trueaudio.cpp
|
||||
|
200
tests/test_smartptr.cpp
Normal file
200
tests/test_smartptr.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
#include <trefcountptr.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace TagLib;
|
||||
|
||||
bool baseDestructorCalled;
|
||||
bool derivedDestructorCalled;
|
||||
bool incompleteDestructorCalled;
|
||||
|
||||
class TestSmartptr : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE(TestSmartptr);
|
||||
CPPUNIT_TEST(testSharedptrBasic);
|
||||
CPPUNIT_TEST(testDerivedClass);
|
||||
CPPUNIT_TEST(testIncompleteClass);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
template<class T>
|
||||
void ck( const T* v1, T v2 ) { CPPUNIT_ASSERT( *v1 == v2 ); }
|
||||
|
||||
public:
|
||||
void testSharedptrBasic()
|
||||
{
|
||||
int * ip = new int;
|
||||
TAGLIB_SHARED_PTR<int> cp ( ip );
|
||||
CPPUNIT_ASSERT( ip == cp.get() );
|
||||
CPPUNIT_ASSERT( cp.use_count() == 1 );
|
||||
|
||||
*cp = 54321;
|
||||
CPPUNIT_ASSERT( *cp == 54321 );
|
||||
CPPUNIT_ASSERT( *ip == 54321 );
|
||||
ck( static_cast<int*>(cp.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp );
|
||||
|
||||
TAGLIB_SHARED_PTR<int> cp2 ( cp );
|
||||
CPPUNIT_ASSERT( ip == cp2.get() );
|
||||
CPPUNIT_ASSERT( cp.use_count() == 2 );
|
||||
CPPUNIT_ASSERT( cp2.use_count() == 2 );
|
||||
|
||||
CPPUNIT_ASSERT( *cp == 54321 );
|
||||
CPPUNIT_ASSERT( *cp2 == 54321 );
|
||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp2 );
|
||||
|
||||
TAGLIB_SHARED_PTR<int> cp3 ( cp );
|
||||
CPPUNIT_ASSERT( cp.use_count() == 3 );
|
||||
CPPUNIT_ASSERT( cp2.use_count() == 3 );
|
||||
CPPUNIT_ASSERT( cp3.use_count() == 3 );
|
||||
cp.reset();
|
||||
CPPUNIT_ASSERT( cp2.use_count() == 2 );
|
||||
CPPUNIT_ASSERT( cp3.use_count() == 2 );
|
||||
cp.reset( new int );
|
||||
*cp = 98765;
|
||||
CPPUNIT_ASSERT( *cp == 98765 );
|
||||
*cp3 = 87654;
|
||||
CPPUNIT_ASSERT( *cp3 == 87654 );
|
||||
CPPUNIT_ASSERT( *cp2 == 87654 );
|
||||
cp.swap( cp3 );
|
||||
CPPUNIT_ASSERT( *cp == 87654 );
|
||||
CPPUNIT_ASSERT( *cp2 == 87654 );
|
||||
CPPUNIT_ASSERT( *cp3 == 98765 );
|
||||
cp.swap( cp3 );
|
||||
CPPUNIT_ASSERT( *cp == 98765 );
|
||||
CPPUNIT_ASSERT( *cp2 == 87654 );
|
||||
CPPUNIT_ASSERT( *cp3 == 87654 );
|
||||
cp2 = cp2;
|
||||
CPPUNIT_ASSERT( cp2.use_count() == 2 );
|
||||
CPPUNIT_ASSERT( *cp2 == 87654 );
|
||||
cp = cp2;
|
||||
CPPUNIT_ASSERT( cp2.use_count() == 3 );
|
||||
CPPUNIT_ASSERT( *cp2 == 87654 );
|
||||
CPPUNIT_ASSERT( cp.use_count() == 3 );
|
||||
CPPUNIT_ASSERT( *cp == 87654 );
|
||||
|
||||
TAGLIB_SHARED_PTR<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;
|
||||
scp.insert(cp4);
|
||||
CPPUNIT_ASSERT( scp.find(cp4) != scp.end() );
|
||||
CPPUNIT_ASSERT( scp.find(cp4) == scp.find( TAGLIB_SHARED_PTR<int>(cp4) ) );
|
||||
}
|
||||
|
||||
private:
|
||||
class DummyBase
|
||||
{
|
||||
public:
|
||||
DummyBase(int x) : value(x)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DummyBase()
|
||||
{
|
||||
baseDestructorCalled = true;
|
||||
}
|
||||
|
||||
int getValue() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
int value;
|
||||
};
|
||||
|
||||
class DummyDerived : public DummyBase
|
||||
{
|
||||
public:
|
||||
DummyDerived(int x) : DummyBase(x)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DummyDerived()
|
||||
{
|
||||
derivedDestructorCalled = true;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
void testDerivedClass()
|
||||
{
|
||||
baseDestructorCalled = false;
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyBase> p1(new DummyDerived(100));
|
||||
CPPUNIT_ASSERT(p1->getValue() == 100);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT(baseDestructorCalled);
|
||||
CPPUNIT_ASSERT(derivedDestructorCalled);
|
||||
|
||||
baseDestructorCalled = false;
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyDerived> p1(new DummyDerived(100));
|
||||
TAGLIB_SHARED_PTR<DummyBase> p2 = p1;
|
||||
|
||||
CPPUNIT_ASSERT(p1->getValue() == 100);
|
||||
CPPUNIT_ASSERT(p2->getValue() == 100);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT(baseDestructorCalled);
|
||||
CPPUNIT_ASSERT(derivedDestructorCalled);
|
||||
|
||||
baseDestructorCalled = false;
|
||||
derivedDestructorCalled = false;
|
||||
|
||||
{
|
||||
TAGLIB_SHARED_PTR<DummyDerived> p1;
|
||||
TAGLIB_SHARED_PTR<DummyBase> p2;
|
||||
|
||||
p1.reset(new DummyDerived(100));
|
||||
p2 = p1;
|
||||
|
||||
CPPUNIT_ASSERT(p1->getValue() == 100);
|
||||
CPPUNIT_ASSERT(p2->getValue() == 100);
|
||||
}
|
||||
|
||||
CPPUNIT_ASSERT(baseDestructorCalled);
|
||||
CPPUNIT_ASSERT(derivedDestructorCalled);
|
||||
}
|
||||
|
||||
private:
|
||||
class DummyIncomplete;
|
||||
TAGLIB_SHARED_PTR<DummyIncomplete> pincomplete;
|
||||
|
||||
class DummyIncomplete
|
||||
{
|
||||
public:
|
||||
~DummyIncomplete()
|
||||
{
|
||||
incompleteDestructorCalled = true;
|
||||
}
|
||||
|
||||
int getValue() const { return 100; }
|
||||
};
|
||||
|
||||
public:
|
||||
void testIncompleteClass()
|
||||
{
|
||||
incompleteDestructorCalled = false;
|
||||
|
||||
pincomplete.reset(new DummyIncomplete());
|
||||
CPPUNIT_ASSERT(pincomplete->getValue() == 100);
|
||||
|
||||
pincomplete.reset();
|
||||
CPPUNIT_ASSERT(incompleteDestructorCalled);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestSmartptr);
|
Loading…
x
Reference in New Issue
Block a user