~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/corelib/thread/qatomic.h

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 /****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the core module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#ifndef QATOMIC_H
 
30
#define QATOMIC_H
 
31
 
 
32
#if defined(QT_MOC) || defined(QT_BUILD_QMAKE) || defined(QT_RCC) || defined(QT_UIC)
 
33
// this allows us to use -I... magic to select a specific arch (e.g. generic)
 
34
#  include <arch/qatomic.h>
 
35
#else
 
36
#  include <QtCore/arch/qatomic.h>
 
37
#endif
 
38
 
 
39
#ifndef Q_SPECIALIZED_QATOMIC
 
40
 
 
41
/*
 
42
    We assume that the following 6 functions have been declared by the
 
43
    platform specific qatomic.h:
 
44
 
 
45
    int q_atomic_test_and_set_int(volatile int *ptr, int expected, int newval);
 
46
    int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
 
47
    int q_atomic_increment(volatile int *ptr);
 
48
    int q_atomic_decrement(volatile int *ptr);
 
49
    int q_atomic_set_int(volatile int *ptr, int newval);
 
50
    void *q_atomic_set_ptr(volatile void *ptr, void *newval);
 
51
 
 
52
    If you cannot implement these functions efficiently on your
 
53
    platform without great difficulty, consider defining
 
54
    Q_SPECIALIZED_QATOMIC.  By doing this, you need to implement:
 
55
 
 
56
    struct QBasicAtomic;
 
57
    template <typename T> struct QBasicAtomicPointer<T>;
 
58
    int q_atomic_test_and_set_ptr(volatile void *ptr, void *expected, void *newval);
 
59
    void *q_atomic_set_ptr(volatile void *ptr, void *newval);
 
60
*/
 
61
 
 
62
struct QBasicAtomic {
 
63
    volatile int atomic;
 
64
 
 
65
    void init(int x = 0)
 
66
    { atomic = x; }
 
67
 
 
68
    inline bool ref()
 
69
    { return q_atomic_increment(&atomic) != 0; }
 
70
 
 
71
    inline bool deref()
 
72
    { return q_atomic_decrement(&atomic) != 0; }
 
73
 
 
74
    inline bool operator==(int x) const
 
75
    { return atomic == x; }
 
76
 
 
77
    inline bool operator!=(int x) const
 
78
    { return atomic != x; }
 
79
 
 
80
    inline bool operator!() const
 
81
    { return atomic == 0; }
 
82
 
 
83
    inline operator int() const
 
84
    { return atomic; }
 
85
 
 
86
    inline QBasicAtomic &operator=(int x)
 
87
    {
 
88
        (void) q_atomic_set_int(&atomic, x);
 
89
        return *this;
 
90
    }
 
91
 
 
92
    inline bool testAndSet(int expected, int newval)
 
93
    { return q_atomic_test_and_set_int(&atomic, expected, newval) != 0; }
 
94
 
 
95
    inline int exchange(int newval)
 
96
    { return q_atomic_set_int(&atomic, newval); }
 
97
};
 
98
 
 
99
template <typename T>
 
100
struct QBasicAtomicPointer
 
101
{
 
102
    volatile T *pointer;
 
103
 
 
104
    void init(T *t = 0)
 
105
    { pointer = t; }
 
106
 
 
107
    inline bool operator==(T *t) const
 
108
    { return pointer == t; }
 
109
 
 
110
    inline bool operator!=(T *t) const
 
111
    { return !operator==(t); }
 
112
 
 
113
    inline bool operator!() const
 
114
    { return operator==(0); }
 
115
 
 
116
    inline operator T *() const
 
117
    { return const_cast<T *>(pointer); }
 
118
 
 
119
    inline T *operator->() const
 
120
    { return const_cast<T *>(pointer); }
 
121
 
 
122
    inline QBasicAtomicPointer<T> &operator=(T *t)
 
123
    {
 
124
        (void) q_atomic_set_ptr(&pointer, t);
 
125
        return *this;
 
126
    }
 
127
 
 
128
    inline bool testAndSet(T *expected, T *newval)
 
129
    { return q_atomic_test_and_set_ptr(&pointer, expected, newval); }
 
130
 
 
131
    inline T *exchange(T * newval)
 
132
    { return static_cast<T *>(q_atomic_set_ptr(&pointer, newval)); }
 
133
};
 
134
 
 
135
#define Q_ATOMIC_INIT(a) { (a) }
 
136
 
 
137
#endif // Q_SPECIALIZED_QATOMIC
 
138
 
 
139
template <typename T>
 
140
inline T qAtomicSetPtr(volatile T *ptr, T newval)
 
141
{ return static_cast<T>(q_atomic_set_ptr(ptr, newval)); }
 
142
 
 
143
// High-level atomic integer operations
 
144
class QAtomic : public QBasicAtomic
 
145
{
 
146
public:
 
147
    inline QAtomic(int x = 0)
 
148
    { init(x); }
 
149
    inline QAtomic(const QAtomic &copy)
 
150
    { init(copy); }
 
151
 
 
152
    inline QAtomic &operator=(int x)
 
153
    {
 
154
        (void) QBasicAtomic::operator=(x);
 
155
        return *this;
 
156
    }
 
157
 
 
158
    inline QAtomic &operator=(const QAtomic &copy)
 
159
    {
 
160
        (void) QBasicAtomic::operator=(copy);
 
161
        return *this;
 
162
    }
 
163
};
 
164
 
 
165
// High-level atomic pointer operations
 
166
template <typename T>
 
167
class QAtomicPointer : public QBasicAtomicPointer<T>
 
168
{
 
169
public:
 
170
    inline QAtomicPointer(T *t = 0)
 
171
    { init(t); }
 
172
    inline QAtomicPointer(const QAtomicPointer<T> &copy)
 
173
    { init(copy); }
 
174
 
 
175
    inline QAtomicPointer<T> &operator=(T *t)
 
176
    {
 
177
        (void) QBasicAtomicPointer<T>::operator=(t);
 
178
        return *this;
 
179
    }
 
180
 
 
181
    inline QAtomicPointer<T> &operator=(const QAtomicPointer<T> &copy)
 
182
    {
 
183
        (void) QBasicAtomicPointer<T>::operator=(copy);
 
184
        return *this;
 
185
    }
 
186
};
 
187
 
 
188
/*!
 
189
    This is a helper for the assignment operators of implicitly
 
190
    shared classes. Your assignment operator should look like this:
 
191
 
 
192
    \code
 
193
        MyClass &MyClass:operator=(const MyClass &other)
 
194
        { qAtomicAssign(d, other.d); return *this; }
 
195
    \endcode
 
196
*/
 
197
template <typename T>
 
198
inline void qAtomicAssign(T *&d, T *x)
 
199
{
 
200
    x->ref.ref();
 
201
    x = qAtomicSetPtr(&d, x);
 
202
    if (!x->ref.deref())
 
203
        delete x;
 
204
}
 
205
 
 
206
/*! \internal
 
207
    \overload
 
208
*/
 
209
template <typename T>
 
210
inline void qAtomicAssign(QBasicAtomicPointer<T> &d, T *x)
 
211
{
 
212
    x->ref.ref();
 
213
    x = d.exchange(x);
 
214
    if (!x->ref.deref())
 
215
        delete x;
 
216
}
 
217
 
 
218
/*! \internal
 
219
    \overload
 
220
*/
 
221
template <typename T>
 
222
inline void qAtomicAssign(QBasicAtomicPointer<T> &d, const QBasicAtomicPointer<T> &x)
 
223
{ qAtomicAssign<T>(d, x); }
 
224
 
 
225
/*! \internal
 
226
    This is a helper for the detach function. Your private class needs
 
227
    a copy constructor which copies the members and sets the refcount
 
228
    to 1. After that, your detach function should look like this:
 
229
 
 
230
    \code
 
231
        void MyClass::detach()
 
232
        { qAtomicDetach(d); }
 
233
    \endcode
 
234
*/
 
235
template <typename T>
 
236
inline void qAtomicDetach(T *&d)
 
237
{
 
238
    if (d->ref == 1)
 
239
        return;
 
240
    T *x = new T(*d);
 
241
    x = qAtomicSetPtr(&d, x);
 
242
    if (!x->ref.deref())
 
243
        delete x;
 
244
}
 
245
 
 
246
/*! \internal
 
247
    \overload
 
248
*/
 
249
template <typename T>
 
250
inline void qAtomicDetach(QBasicAtomicPointer<T> &d)
 
251
{
 
252
    if (d->ref == 1)
 
253
        return;
 
254
    T *x = new T(*d);
 
255
    x = d.exchange(x);
 
256
    if (!x->ref.deref())
 
257
        delete x;
 
258
}
 
259
 
 
260
#endif // QATOMIC_H