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

« back to all changes in this revision

Viewing changes to src/gui/embedded/qlock.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 
4
** All rights reserved.
 
5
** Contact: Nokia Corporation (qt-info@nokia.com)
 
6
**
 
7
** This file is part of the QtGui module of the Qt Toolkit.
 
8
**
 
9
** $QT_BEGIN_LICENSE:LGPL$
 
10
** No Commercial Usage
 
11
** This file contains pre-release code and may not be distributed.
 
12
** You may use this file in accordance with the terms and conditions
 
13
** contained in the Technology Preview License Agreement accompanying
 
14
** this package.
 
15
**
 
16
** GNU Lesser General Public License Usage
 
17
** Alternatively, this file may be used under the terms of the GNU Lesser
 
18
** General Public License version 2.1 as published by the Free Software
 
19
** Foundation and appearing in the file LICENSE.LGPL included in the
 
20
** packaging of this file.  Please review the following information to
 
21
** ensure the GNU Lesser General Public License version 2.1 requirements
 
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
23
**
 
24
** In addition, as a special exception, Nokia gives you certain additional
 
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
 
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
27
**
 
28
** If you have questions regarding the use of this file, please contact
 
29
** Nokia at qt-info@nokia.com.
 
30
**
 
31
**
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qlock_p.h"
 
43
 
 
44
 
 
45
#ifdef QT_NO_QWS_MULTIPROCESS
 
46
 
 
47
QT_BEGIN_NAMESPACE
 
48
 
 
49
/* no multiprocess - use a dummy */
 
50
 
 
51
QLock::QLock(const QString & /*filename*/, char /*id*/, bool /*create*/)
 
52
    : type(Read), data(0)
 
53
{
 
54
}
 
55
 
 
56
QLock::~QLock()
 
57
{
 
58
}
 
59
 
 
60
bool QLock::isValid() const
 
61
{
 
62
    return true;
 
63
}
 
64
 
 
65
void QLock::lock(Type t)
 
66
{
 
67
    data = (QLockData *)-1;
 
68
    type = t;
 
69
}
 
70
 
 
71
void QLock::unlock()
 
72
{
 
73
    data = 0;
 
74
}
 
75
 
 
76
bool QLock::locked() const
 
77
{
 
78
    return data;
 
79
}
 
80
 
 
81
QT_END_NAMESPACE
 
82
 
 
83
#else // QT_NO_QWS_MULTIPROCESS
 
84
 
 
85
#include "qwssignalhandler_p.h"
 
86
 
 
87
#include <unistd.h>
 
88
#include <sys/types.h>
 
89
#if defined(Q_OS_DARWIN)
 
90
#   define Q_NO_SEMAPHORE
 
91
#   include <sys/stat.h>
 
92
#   include <sys/file.h>
 
93
#else // Q_OS_DARWIN
 
94
#   include <sys/sem.h>
 
95
#   if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) && !defined(QT_LINUXBASE)) \
 
96
    || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) \
 
97
    || defined(Q_OS_BSDI)
 
98
        /* union semun is defined by including <sys/sem.h> */
 
99
#   else
 
100
/* according to X/OPEN we have to define it ourselves */
 
101
union semun {
 
102
    int val;                    /* value for SETVAL */
 
103
    struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
 
104
    unsigned short *array;      /* array for GETALL, SETALL */
 
105
};
 
106
#   endif
 
107
#endif // Q_OS_DARWIN
 
108
#include <sys/ipc.h>
 
109
#include <string.h>
 
110
#include <errno.h>
 
111
#include <qdebug.h>
 
112
#include <signal.h>
 
113
 
 
114
#include <private/qcore_unix_p.h> // overrides QT_OPEN
 
115
 
 
116
 
 
117
QT_BEGIN_NAMESPACE
 
118
 
 
119
#define MAX_LOCKS   200            // maximum simultaneous read locks
 
120
 
 
121
class QLockData
 
122
{
 
123
public:
 
124
#ifdef Q_NO_SEMAPHORE
 
125
    QByteArray file;
 
126
#endif // Q_NO_SEMAPHORE
 
127
    int id;
 
128
    int count;
 
129
    bool owned;
 
130
};
 
131
 
 
132
/*!
 
133
    \class QLock
 
134
    \brief The QLock class is a wrapper for a System V shared semaphore.
 
135
 
 
136
    \ingroup qws
 
137
 
 
138
    \internal
 
139
 
 
140
    It is used by \l{Qt for Embedded Linux} for synchronizing access to the graphics
 
141
    card and shared memory region between processes.
 
142
*/
 
143
 
 
144
/*!
 
145
    \enum QLock::Type
 
146
 
 
147
    \value Read
 
148
    \value Write
 
149
*/
 
150
 
 
151
/*!
 
152
    \fn QLock::QLock(const QString &filename, char id, bool create)
 
153
 
 
154
    Creates a lock. \a filename is the file path of the Unix-domain
 
155
    socket the \l{Qt for Embedded Linux} client is using. \a id is the name of the
 
156
    particular lock to be created on that socket. If \a create is true
 
157
    the lock is to be created (as the Qt for Embedded Linux server does); if \a
 
158
    create is false the lock should exist already (as the Qt for Embedded Linux
 
159
    client expects).
 
160
*/
 
161
 
 
162
QLock::QLock(const QString &filename, char id, bool create)
 
163
{
 
164
    data = new QLockData;
 
165
    data->count = 0;
 
166
#ifdef Q_NO_SEMAPHORE
 
167
    data->file = QString(filename+id).toLocal8Bit().constData();
 
168
    for(int x = 0; x < 2; x++) {
 
169
        data->id = QT_OPEN(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
 
170
        if(data->id != -1 || !create) {
 
171
            data->owned = x;
 
172
            break;
 
173
        }
 
174
    }
 
175
#else
 
176
    key_t semkey = ftok(filename.toLocal8Bit().constData(), id);
 
177
    data->id = semget(semkey,0,0);
 
178
    data->owned = create;
 
179
    if (create) {
 
180
        semun arg; arg.val = 0;
 
181
        if (data->id != -1)
 
182
            semctl(data->id,0,IPC_RMID,arg);
 
183
        data->id = semget(semkey,1,IPC_CREAT|0600);
 
184
        arg.val = MAX_LOCKS;
 
185
        semctl(data->id,0,SETVAL,arg);
 
186
 
 
187
        QWSSignalHandler::instance()->addSemaphore(data->id);
 
188
    }
 
189
#endif
 
190
    if (data->id == -1) {
 
191
        int eno = errno;
 
192
        qWarning("Cannot %s semaphore %s '%c'", (create ? "create" : "get"),
 
193
                 qPrintable(filename), id);
 
194
        qDebug() << "Error" << eno << strerror(eno);
 
195
    }
 
196
}
 
197
 
 
198
/*!
 
199
    \fn QLock::~QLock()
 
200
 
 
201
    Destroys a lock
 
202
*/
 
203
 
 
204
QLock::~QLock()
 
205
{
 
206
    if (locked())
 
207
        unlock();
 
208
#ifdef Q_NO_SEMAPHORE
 
209
    if(isValid()) {
 
210
        QT_CLOSE(data->id);
 
211
        if(data->owned)
 
212
            unlink(data->file);
 
213
    }
 
214
#else
 
215
    if(data->owned)
 
216
        QWSSignalHandler::instance()->removeSemaphore(data->id);
 
217
#endif
 
218
    delete data;
 
219
}
 
220
 
 
221
/*!
 
222
    \fn bool QLock::isValid() const
 
223
 
 
224
    Returns true if the lock constructor was successful; returns false if
 
225
    the lock could not be created or was not available to connect to.
 
226
*/
 
227
 
 
228
bool QLock::isValid() const
 
229
{
 
230
    return (data->id != -1);
 
231
}
 
232
 
 
233
/*!
 
234
    Locks the semaphore with a lock of type \a t. Locks can either be
 
235
    \c Read or \c Write. If a lock is \c Read, attempts by other
 
236
    processes to obtain \c Read locks will succeed, and \c Write
 
237
    attempts will block until the lock is unlocked. If locked as \c
 
238
    Write, all attempts to lock by other processes will block until
 
239
    the lock is unlocked. Locks are stacked: i.e. a given QLock can be
 
240
    locked multiple times by the same process without blocking, and
 
241
    will only be unlocked after a corresponding number of unlock()
 
242
    calls.
 
243
*/
 
244
 
 
245
void QLock::lock(Type t)
 
246
{
 
247
    if (!data->count) {
 
248
#ifdef Q_NO_SEMAPHORE
 
249
        int op = LOCK_SH;
 
250
        if(t == Write)
 
251
            op = LOCK_EX;
 
252
        for(int rv=1; rv;) {
 
253
            rv = flock(data->id, op);
 
254
            if (rv == -1 && errno != EINTR)
 
255
                qDebug("Semop lock failure %s",strerror(errno));
 
256
        }
 
257
#else
 
258
        sembuf sops;
 
259
        sops.sem_num = 0;
 
260
        sops.sem_flg = SEM_UNDO;
 
261
 
 
262
        if (t == Write) {
 
263
            sops.sem_op = -MAX_LOCKS;
 
264
            type = Write;
 
265
        } else {
 
266
            sops.sem_op = -1;
 
267
            type = Read;
 
268
        }
 
269
 
 
270
        int rv;
 
271
        do {
 
272
            rv = semop(data->id,&sops,1);
 
273
            if (rv == -1 && errno != EINTR)
 
274
                qDebug("Semop lock failure %s",strerror(errno));
 
275
        } while (rv == -1 && errno == EINTR);
 
276
#endif
 
277
    }
 
278
    data->count++;
 
279
}
 
280
 
 
281
/*!
 
282
    \fn void QLock::unlock()
 
283
 
 
284
    Unlocks the semaphore. If other processes were blocking waiting to
 
285
    lock() the semaphore, one of them will wake up and succeed in
 
286
    lock()ing.
 
287
*/
 
288
 
 
289
void QLock::unlock()
 
290
{
 
291
    if(data->count) {
 
292
        data->count--;
 
293
        if(!data->count) {
 
294
#ifdef Q_NO_SEMAPHORE
 
295
            for(int rv=1; rv;) {
 
296
                rv = flock(data->id, LOCK_UN);
 
297
                if (rv == -1 && errno != EINTR)
 
298
                    qDebug("Semop lock failure %s",strerror(errno));
 
299
            }
 
300
#else
 
301
            sembuf sops;
 
302
            sops.sem_num = 0;
 
303
            sops.sem_op = 1;
 
304
            sops.sem_flg = SEM_UNDO;
 
305
            if (type == Write)
 
306
                sops.sem_op = MAX_LOCKS;
 
307
 
 
308
            int rv;
 
309
            do {
 
310
                rv = semop(data->id,&sops,1);
 
311
                if (rv == -1 && errno != EINTR)
 
312
                    qDebug("Semop unlock failure %s",strerror(errno));
 
313
            } while (rv == -1 && errno == EINTR);
 
314
#endif
 
315
        }
 
316
    } else {
 
317
        qDebug("Unlock without corresponding lock");
 
318
    }
 
319
}
 
320
 
 
321
/*!
 
322
    \fn bool QLock::locked() const
 
323
 
 
324
    Returns true if the lock is currently held by the current process;
 
325
    otherwise returns false.
 
326
*/
 
327
 
 
328
bool QLock::locked() const
 
329
{
 
330
    return (data->count > 0);
 
331
}
 
332
 
 
333
QT_END_NAMESPACE
 
334
 
 
335
#endif // QT_NO_QWS_MULTIPROCESS
 
336