1/***************************************************************************
2 copyright : (C) 2013 by Tsuda Kageyu
3 email : tsuda.kageyu@gmail.com
4 ***************************************************************************/
5
6/***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
10 * *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 USA *
20 * *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
25
26#ifndef TAGLIB_REFCOUNTER_H
27#define TAGLIB_REFCOUNTER_H
28
29#include "taglib_export.h"
30#include "taglib.h"
31
32#ifdef __APPLE__
33# include <libkern/OSAtomic.h>
34# define TAGLIB_ATOMIC_MAC
35#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
36# ifndef NOMINMAX
37# define NOMINMAX
38# endif
39# include <windows.h>
40# define TAGLIB_ATOMIC_WIN
41#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \
42 && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \
43 defined(__i686__) || defined(__x86_64) || defined(__ia64)) \
44 && !defined(__INTEL_COMPILER)
45# define TAGLIB_ATOMIC_GCC
46#elif defined(__ia64) && defined(__INTEL_COMPILER)
47# include <ia64intrin.h>
48# define TAGLIB_ATOMIC_GCC
49#endif
50
51#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class.
52/*!
53 * \internal
54 * This is just used as a base class for shared classes in TagLib.
55 *
56 * \warning This <b>is not</b> part of the TagLib public API!
57 */
58namespace TagLib
59{
60
61 class TAGLIB_EXPORT RefCounter
62 {
63 public:
64 RefCounter();
65 virtual ~RefCounter();
66
67 void ref();
68 bool deref();
69 int count() const;
70
71 private:
72 class RefCounterPrivate;
73 RefCounterPrivate *d;
74 };
75
76 // BIC this old class is needed by tlist.tcc and tmap.tcc
77 class RefCounterOld
78 {
79 public:
80 RefCounterOld() : refCount(1) {}
81
82#ifdef TAGLIB_ATOMIC_MAC
83 void ref() { OSAtomicIncrement32Barrier(const_cast<int32_t*>(&refCount)); }
84 bool deref() { return ! OSAtomicDecrement32Barrier(const_cast<int32_t*>(&refCount)); }
85 int32_t count() { return refCount; }
86 private:
87 volatile int32_t refCount;
88#elif defined(TAGLIB_ATOMIC_WIN)
89 void ref() { InterlockedIncrement(&refCount); }
90 bool deref() { return ! InterlockedDecrement(&refCount); }
91 long count() { return refCount; }
92 private:
93 volatile long refCount;
94#elif defined(TAGLIB_ATOMIC_GCC)
95 void ref() { __sync_add_and_fetch(&refCount, 1); }
96 bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); }
97 int count() { return refCount; }
98 private:
99 volatile int refCount;
100#else
101 void ref() { refCount++; }
102 bool deref() { return ! --refCount; }
103 int count() { return refCount; }
104 private:
105 unsigned int refCount;
106#endif
107 };
108
109}
110
111#endif // DO_NOT_DOCUMENT
112#endif
113
114