~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): 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 embedded classes 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
#include "qlock_p.h"
 
30
 
 
31
#ifndef QT_NO_QWS_MULTIPROCESS
 
32
 
 
33
#include <unistd.h>
 
34
#include <sys/types.h>
 
35
#if defined(Q_OS_DARWIN)
 
36
#define Q_NO_SEMAPHORE
 
37
#include <sys/stat.h>
 
38
#include <sys/file.h>
 
39
#else
 
40
#include <sys/sem.h>
 
41
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) \
 
42
    || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_BSDI)
 
43
/* union semun is defined by including <sys/sem.h> */
 
44
#else
 
45
/* according to X/OPEN we have to define it ourselves */
 
46
union semun {
 
47
    int val;                    /* value for SETVAL */
 
48
    struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
 
49
    unsigned short *array;      /* array for GETALL, SETALL */
 
50
};
 
51
#endif
 
52
#endif
 
53
#include <sys/ipc.h>
 
54
#include <string.h>
 
55
#include <errno.h>
 
56
#include <qdebug.h>
 
57
 
 
58
#define MAX_LOCKS   200            // maximum simultaneous read locks
 
59
 
 
60
class QLockData
 
61
{
 
62
public:
 
63
#ifdef Q_NO_SEMAPHORE
 
64
    QByteArray file;
 
65
#endif
 
66
    int id;
 
67
    int count;
 
68
    bool owned;
 
69
};
 
70
 
 
71
#endif
 
72
 
 
73
/*!
 
74
    \class QLock qlock_p.h
 
75
    \brief The QLock class is a wrapper for a System V shared semaphore.
 
76
 
 
77
    \ingroup qws
 
78
    \ingroup io
 
79
 
 
80
    \internal
 
81
 
 
82
    It is used by Qt/Embedded for synchronizing access to the graphics
 
83
    card and shared memory region between processes.
 
84
*/
 
85
 
 
86
/*!
 
87
    \enum QLock::Type
 
88
 
 
89
    \value Read
 
90
    \value Write
 
91
*/
 
92
 
 
93
/*!
 
94
    \fn QLock::QLock(const QString &filename, char id, bool create)
 
95
 
 
96
    Creates a lock. \a filename is the file path of the Unix-domain
 
97
    socket the Qt/Embedded client is using. \a id is the name of the
 
98
    particular lock to be created on that socket. If \a create is true
 
99
    the lock is to be created (as the Qt/Embedded server does); if \a
 
100
    create is false the lock should exist already (as the Qt/Embedded
 
101
    client expects).
 
102
*/
 
103
 
 
104
QLock::QLock(const QString &filename, char id, bool create)
 
105
{
 
106
#ifndef QT_NO_QWS_MULTIPROCESS
 
107
    data = new QLockData;
 
108
    data->count = 0;
 
109
#ifdef Q_NO_SEMAPHORE
 
110
    data->file = QString(filename+id).toLocal8Bit().constData();
 
111
    for(int x = 0; x < 2; x++) {
 
112
        data->id = open(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
 
113
        if(data->id != -1 || !create) {
 
114
            data->owned = x;
 
115
            break;
 
116
        }
 
117
    }
 
118
#else
 
119
    key_t semkey = ftok(filename.toLocal8Bit().constData(), id);
 
120
    data->id = semget(semkey,0,0);
 
121
    data->owned = create;
 
122
    if (create) {
 
123
        semun arg; arg.val = 0;
 
124
        if (data->id != -1)
 
125
            semctl(data->id,0,IPC_RMID,arg);
 
126
        data->id = semget(semkey,1,IPC_CREAT|0600);
 
127
        arg.val = MAX_LOCKS;
 
128
        semctl(data->id,0,SETVAL,arg);
 
129
    }
 
130
#endif
 
131
    if (data->id == -1) {
 
132
        qWarning() << "Cannot" << (create ? "create" : "get") << "semaphore"
 
133
                   << filename << "'" << id << "'";
 
134
        qDebug() << "Error" << errno << strerror(errno);
 
135
    }
 
136
#endif
 
137
}
 
138
 
 
139
/*!
 
140
    \fn QLock::~QLock()
 
141
 
 
142
    Destroys a lock
 
143
*/
 
144
 
 
145
QLock::~QLock()
 
146
{
 
147
#ifndef QT_NO_QWS_MULTIPROCESS
 
148
    if (locked())
 
149
        unlock();
 
150
#ifdef Q_NO_SEMAPHORE
 
151
    if(isValid()) {
 
152
        close(data->id);
 
153
        if(data->owned)
 
154
            unlink(data->file);
 
155
    }
 
156
#else
 
157
    if(data->owned) {
 
158
        semun arg; arg.val = 0;
 
159
        semctl(data->id, 0, IPC_RMID, arg);
 
160
    }
 
161
#endif
 
162
    delete data;
 
163
#endif
 
164
}
 
165
 
 
166
/*!
 
167
    \fn bool QLock::isValid() const
 
168
 
 
169
    Returns true if the lock constructor was successful; returns false if
 
170
    the lock could not be created or was not available to connect to.
 
171
*/
 
172
 
 
173
bool QLock::isValid() const
 
174
{
 
175
#ifndef QT_NO_QWS_MULTIPROCESS
 
176
    return (data->id != -1);
 
177
#else
 
178
    return true;
 
179
#endif
 
180
}
 
181
 
 
182
/*!
 
183
    Locks the semaphore with a lock of type \a t. Locks can either be
 
184
    \c Read or \c Write. If a lock is \c Read, attempts by other
 
185
    processes to obtain \c Read locks will succeed, and \c Write
 
186
    attempts will block until the lock is unlocked. If locked as \c
 
187
    Write, all attempts to lock by other processes will block until
 
188
    the lock is unlocked. Locks are stacked: i.e. a given QLock can be
 
189
    locked multiple times by the same process without blocking, and
 
190
    will only be unlocked after a corresponding number of unlock()
 
191
    calls.
 
192
*/
 
193
 
 
194
void QLock::lock(Type t)
 
195
{
 
196
#ifndef QT_NO_QWS_MULTIPROCESS
 
197
    if (!data->count) {
 
198
#ifdef Q_NO_SEMAPHORE
 
199
        int op = LOCK_SH;
 
200
        if(t == Write)
 
201
            op = LOCK_EX;
 
202
        for(int rv=1; rv;) {
 
203
            rv = flock(data->id, op);
 
204
            if (rv == -1 && errno != EINTR)
 
205
                qDebug("Semop lock failure %s",strerror(errno));
 
206
        }
 
207
#else
 
208
        sembuf sops;
 
209
        sops.sem_num = 0;
 
210
        sops.sem_flg = SEM_UNDO;
 
211
 
 
212
        if (t == Write) {
 
213
            sops.sem_op = -MAX_LOCKS;
 
214
            type = Write;
 
215
        } else {
 
216
            sops.sem_op = -1;
 
217
            type = Read;
 
218
        }
 
219
 
 
220
        int rv;
 
221
        do {
 
222
            rv = semop(data->id,&sops,1);
 
223
            if (rv == -1 && errno != EINTR)
 
224
                qDebug("Semop lock failure %s",strerror(errno));
 
225
        } while (rv == -1 && errno == EINTR);
 
226
#endif
 
227
    }
 
228
    data->count++;
 
229
#endif
 
230
}
 
231
 
 
232
/*!
 
233
    \fn void QLock::unlock()
 
234
 
 
235
    Unlocks the semaphore. If other processes were blocking waiting to
 
236
    lock() the semaphore, one of them will wake up and succeed in
 
237
    lock()ing.
 
238
*/
 
239
 
 
240
void QLock::unlock()
 
241
{
 
242
#ifndef QT_NO_QWS_MULTIPROCESS
 
243
    if(data->count) {
 
244
        data->count--;
 
245
        if(!data->count) {
 
246
#ifdef Q_NO_SEMAPHORE
 
247
            for(int rv=1; rv;) {
 
248
                rv = flock(data->id, LOCK_UN);
 
249
                if (rv == -1 && errno != EINTR)
 
250
                    qDebug("Semop lock failure %s",strerror(errno));
 
251
            }
 
252
#else
 
253
            sembuf sops;
 
254
            sops.sem_num = 0;
 
255
            sops.sem_op = 1;
 
256
            sops.sem_flg = SEM_UNDO;
 
257
            if (type == Write)
 
258
                sops.sem_op = MAX_LOCKS;
 
259
 
 
260
            int rv;
 
261
            do {
 
262
                rv = semop(data->id,&sops,1);
 
263
                if (rv == -1 && errno != EINTR)
 
264
                    qDebug("Semop unlock failure %s",strerror(errno));
 
265
            } while (rv == -1 && errno == EINTR);
 
266
#endif
 
267
        }
 
268
    } else {
 
269
        qDebug("Unlock without corresponding lock");
 
270
    }
 
271
#endif
 
272
}
 
273
 
 
274
/*!
 
275
    \fn bool QLock::locked() const
 
276
 
 
277
    Returns true if the lock is currently held by the current process;
 
278
    otherwise returns false.
 
279
*/
 
280
 
 
281
bool QLock::locked() const
 
282
{
 
283
#ifndef QT_NO_QWS_MULTIPROCESS
 
284
    return (data->count > 0);
 
285
#else
 
286
    return false;
 
287
#endif
 
288
}