~ubuntu-branches/ubuntu/trusty/tomahawk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/libtomahawk/thirdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp

  • Committer: Package Import Robot
  • Author(s): Harald Sitter
  • Date: 2013-03-07 21:50:13 UTC
  • Revision ID: package-import@ubuntu.com-20130307215013-6gdjkdds7i9uenvs
Tags: upstream-0.6.0+dfsg
ImportĀ upstreamĀ versionĀ 0.6.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "kdlockedsharedmemorypointer.h"
 
2
 
 
3
#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )
 
4
#ifndef QT_NO_SHAREDMEMORY
 
5
 
 
6
namespace kdtools
 
7
{
 
8
}
 
9
using namespace kdtools;
 
10
 
 
11
KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory * m )
 
12
    : locker( m ),
 
13
      mem( m )
 
14
{
 
15
 
 
16
}
 
17
 
 
18
KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory & m )
 
19
    : locker( &m ),
 
20
      mem( &m )
 
21
{
 
22
 
 
23
}
 
24
 
 
25
KDLockedSharedMemoryPointerBase::~KDLockedSharedMemoryPointerBase() {}
 
26
 
 
27
void * KDLockedSharedMemoryPointerBase::get() {
 
28
    return mem ? mem->data() : 0 ;
 
29
}
 
30
 
 
31
const void * KDLockedSharedMemoryPointerBase::get() const {
 
32
    return mem ? mem->data() : 0 ;
 
33
}
 
34
 
 
35
size_t KDLockedSharedMemoryPointerBase::byteSize() const {
 
36
    return mem ? mem->size() : 0;
 
37
}
 
38
 
 
39
/*!
 
40
  \class KDLockedSharedMemoryPointer
 
41
  \ingroup core raii smartptr
 
42
  \brief Locking pointer for Qt shared memory segments
 
43
  \since_c 2.1
 
44
 
 
45
  (The exception safety of this class has not been evaluated yet.)
 
46
 
 
47
  KDLockedSharedMemoryPointer is a smart immutable pointer, which gives convenient and safe access to a QSharedMemory data segment.
 
48
  The content of a KDLockedSharedMemoryPointer cannot be changed during it's lifetime.
 
49
 
 
50
  You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it.
 
51
  \note You can only put simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the
 
52
  documentation of QSharedMemory for details.
 
53
*/
 
54
 
 
55
/*!
 
56
  \fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory * mem )
 
57
 
 
58
  Constructor. Constructs a KDLockedSharedMemory pointer which points to the data segment of \a mem.
 
59
  The constructor locks \a mem. If the memory segment is already locked by another process, this constructor
 
60
  blocks until the lock is released.
 
61
 
 
62
  \post data() == mem->data() and the memory segment has been locked
 
63
*/
 
64
 
 
65
/*!
 
66
  \fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory & mem )
 
67
 
 
68
  \overload
 
69
 
 
70
  \post data() == mem.data() and the memory segment has been locked
 
71
*/
 
72
 
 
73
/*!
 
74
  \fn KDLockedSharedMemoryPointer::~KDLockedSharedMemoryPointer()
 
75
 
 
76
  Destructor. Unlocks the shared memory segment.
 
77
 
 
78
  \post The shared memory segment has been unlocked
 
79
*/
 
80
 
 
81
/*!
 
82
  \fn T * KDLockedSharedMemoryPointer::get()
 
83
 
 
84
  \returns a pointer to the contained object.
 
85
*/
 
86
 
 
87
/*!
 
88
  \fn const T * KDLockedSharedMemoryPointer::get() const
 
89
 
 
90
  \returns a const pointer to the contained object
 
91
  \overload
 
92
*/
 
93
 
 
94
/*!
 
95
  \fn T * KDLockedSharedMemoryPointer::data()
 
96
 
 
97
  Equivalent to get(), provided for consistency with Qt naming conventions.
 
98
*/
 
99
 
 
100
/*!
 
101
  \fn const T * KDLockedSharedMemoryPointer::data() const
 
102
 
 
103
  \overload
 
104
*/
 
105
 
 
106
/*!
 
107
  \fn T & KDLockedSharedMemoryPointer::operator*()
 
108
 
 
109
  Dereference operator. Returns \link get() *get()\endlink.
 
110
*/
 
111
 
 
112
/*!
 
113
  \fn const T & KDLockedSharedMemoryPointer::operator*() const
 
114
 
 
115
  Dereference operator. Returns \link get() *get()\endlink.
 
116
  \overload
 
117
*/
 
118
 
 
119
/*!
 
120
  \fn T * KDLockedSharedMemoryPointer::operator->()
 
121
 
 
122
  Member-by-pointer operator. Returns get().
 
123
*/
 
124
 
 
125
/*!
 
126
  \fn const T * KDLockedSharedMemoryPointer::operator->() const
 
127
 
 
128
  Member-by-pointer operator. Returns get().
 
129
  \overload
 
130
*/
 
131
 
 
132
/*!
 
133
  \class KDLockedSharedMemoryArray
 
134
  \ingroup core raii smartptr
 
135
  \brief Locking array pointer to Qt shared memory segments
 
136
  \since_c 2.1
 
137
 
 
138
  (The exception safety of this class has not been evaluated yet.)
 
139
 
 
140
  KDLockedSharedMemoryArray is a smart immutable pointer, which gives convenient and safe access to array data stored in a QSharedMemory
 
141
  data segment.
 
142
  The content of a KDLockedSharedMemoryArray cannot be changed during it's lifetime.
 
143
 
 
144
  You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it.
 
145
  \note You can only put arrays of simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the
 
146
  documentation of QSharedMemory for details.
 
147
 
 
148
  \sa KDLockedSharedMemoryPointer
 
149
*/
 
150
 
 
151
/*!
 
152
  \fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory* mem )
 
153
  Constructor. Constructs a KDLockedSharedMemoryArray which points to the data segment of \a mem. The constructor locks \a mem. If the memory
 
154
  segment is already locked by another process, this constructor blocks until the lock is release.
 
155
 
 
156
  \post get() == mem->data() and the memory segment has been locked
 
157
*/
 
158
 
 
159
/*!
 
160
  \fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory& mem )
 
161
  \overload
 
162
 
 
163
  \post get() == mem->data() and the memory segment has been locked
 
164
*/
 
165
 
 
166
 
 
167
/*!
 
168
  \typedef KDLockedSharedMemoryArray::size_type
 
169
  Typedef for std::size_t. Provided for STL compatibility.
 
170
*/
 
171
 
 
172
/*!
 
173
  \typedef KDLockedSharedMemoryArray::difference_type
 
174
  Typedef for std::ptrdiff_t. Provided for STL compatibility.
 
175
*/
 
176
 
 
177
/*!
 
178
  \typedef KDLockedSharedMemoryArray::iterator
 
179
  Typedef for T*. Provided for STL compatibility.
 
180
  \since_t 2.2
 
181
*/
 
182
 
 
183
/*!
 
184
  \typedef KDLockedSharedMemoryArray::const_iterator
 
185
  Typedef for const T*. Provided for STL compatibility.
 
186
  \since_t 2.2
 
187
*/
 
188
 
 
189
/*!
 
190
  \typedef KDLockedSharedMemoryArray::reverse_iterator
 
191
  Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::iterator iterator\endlink >. Provided for STL compatibility.
 
192
  \since_t 2.2
 
193
*/
 
194
 
 
195
/*!
 
196
  \typedef KDLockedSharedMemoryArray::const_reverse_iterator
 
197
  Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::const_iterator const_iterator\endlink >. Provided for STL compatibility.
 
198
  \since_t 2.2
 
199
*/
 
200
 
 
201
/*!
 
202
  \fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::begin()
 
203
  Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the first item of the array.
 
204
  \since_f 2.2
 
205
*/
 
206
 
 
207
/*!
 
208
  \fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::begin() const
 
209
  \overload
 
210
  \since_f 2.2
 
211
*/
 
212
 
 
213
/*!
 
214
  \fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::end()
 
215
  Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the item after the last item of the array.
 
216
  \since_f 2.2
 
217
*/
 
218
 
 
219
/*!
 
220
  \fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::end() const
 
221
  \overload
 
222
  \since_f 2.2
 
223
*/
 
224
 
 
225
/*!
 
226
  \fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rbegin()
 
227
  Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the item after the last item of the array.
 
228
  \since_f 2.2
 
229
*/
 
230
 
 
231
/*!
 
232
  \fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rbegin() const
 
233
  \overload
 
234
  \since_f 2.2
 
235
*/
 
236
 
 
237
/*!
 
238
  \fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rend()
 
239
  Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the first item of the array.
 
240
  \since_f 2.2
 
241
*/
 
242
 
 
243
/*!
 
244
  \fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rend() const
 
245
  \overload
 
246
  \since_f 2.2
 
247
*/
 
248
 
 
249
/*!
 
250
  \fn KDLockedSharedMemoryArray::size_type KDLockedSharedMemoryArray::size() const
 
251
  Returns the size of this array. The size is calculated from the storage size of T and
 
252
  the size of the shared memory segment.
 
253
  \since_f 2.2
 
254
*/
 
255
 
 
256
/*!
 
257
  \fn T& KDLockedSharedMemoryArray::operator[]( difference_type n )
 
258
  Array access operator. Returns a reference to the item at index position \a n.
 
259
*/
 
260
 
 
261
/*!
 
262
  \fn const T& KDLockedSharedMemoryArray::operator[]( difference_type n ) const
 
263
  \overload
 
264
*/
 
265
 
 
266
/*!
 
267
 \fn T& KDLockedSharedMemoryArray::front()
 
268
 Returns a reference to the first item in the array. This is the same as operator[](0).
 
269
*/
 
270
 
 
271
/*!
 
272
 \fn const T& KDLockedSharedMemoryArray::front() const
 
273
 \overload
 
274
*/
 
275
 
 
276
/*!
 
277
 \fn T& KDLockedSharedMemoryArray::back()
 
278
 Returns a reference to the last item in the array. This is the same as operator[](size()-1).
 
279
 \since_f 2.2
 
280
*/
 
281
 
 
282
/*!
 
283
 \fn const T& KDLockedSharedMemoryArray::back() const
 
284
 \overload
 
285
 \since_f 2.2
 
286
*/
 
287
 
 
288
 
 
289
#ifdef eKDTOOLSCORE_UNITTESTS
 
290
 
 
291
#include <KDUnitTest/Test>
 
292
 
 
293
#include <QThread>
 
294
#include <QUuid>
 
295
 
 
296
namespace
 
297
{
 
298
    struct TestStruct
 
299
    {
 
300
        TestStruct( uint nn = 0 )
 
301
            : n( nn ),
 
302
              f( 0.0 ),
 
303
              c( '\0' ),
 
304
              b( false )
 
305
        {
 
306
        }
 
307
        uint n;
 
308
        double f;
 
309
        char c;
 
310
        bool b;
 
311
    };
 
312
 
 
313
    bool operator==( const TestStruct& lhs, const TestStruct& rhs )
 
314
    {
 
315
        return lhs.n == rhs.n && lhs.f == rhs.f && lhs.c == rhs.c && lhs.b == rhs.b;
 
316
    }
 
317
 
 
318
    class TestThread : public QThread
 
319
    {
 
320
    public:
 
321
        TestThread( const QString& key )
 
322
            : mem( key )
 
323
        {
 
324
            mem.attach();
 
325
        }
 
326
 
 
327
        void run()
 
328
        {
 
329
            while( true )
 
330
            {
 
331
                msleep( 100 );
 
332
                kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
 
333
                if( !p->b )
 
334
                    continue;
 
335
 
 
336
                p->n = 5;
 
337
                p->f = 3.14;
 
338
                p->c = 'A';
 
339
                p->b = false;
 
340
                return;
 
341
            }
 
342
        }
 
343
 
 
344
        QSharedMemory mem;
 
345
    };
 
346
 
 
347
    bool isConst( TestStruct* )
 
348
    {
 
349
        return false;
 
350
    }
 
351
 
 
352
    bool isConst( const TestStruct* )
 
353
    {
 
354
        return true;
 
355
    }
 
356
}
 
357
 
 
358
 
 
359
KDAB_UNITTEST_SIMPLE( KDLockedSharedMemoryPointer, "kdcoretools" ) {
 
360
 
 
361
    const QString key = QUuid::createUuid();
 
362
    QSharedMemory mem( key );
 
363
    const bool created = mem.create( sizeof( TestStruct ) );
 
364
    assertTrue( created );
 
365
    if ( !created )
 
366
        return; // don't execute tests if shm coulnd't be created
 
367
 
 
368
    // On Windows, shared mem is only available in increments of page
 
369
    // size (4k), so don't fail if the segment is larger:
 
370
    const unsigned long mem_size = mem.size();
 
371
    assertGreaterOrEqual( mem_size, sizeof( TestStruct ) );
 
372
 
 
373
    {
 
374
        kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
 
375
        assertTrue( p );
 
376
        *p = TestStruct();
 
377
        assertEqual( p->n, 0u );
 
378
        assertEqual( p->f, 0.0 );
 
379
        assertEqual( p->c, '\0' );
 
380
        assertFalse( p->b );
 
381
    }
 
382
 
 
383
    {
 
384
        TestThread thread( key );
 
385
        assertEqual( thread.mem.key().toStdString(), key.toStdString() );
 
386
        assertEqual( static_cast< unsigned long >( thread.mem.size() ), mem_size );
 
387
        thread.start();
 
388
 
 
389
        assertTrue( thread.isRunning() );
 
390
        thread.wait( 2000 );
 
391
        assertTrue( thread.isRunning() );
 
392
 
 
393
        {
 
394
            kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
 
395
            p->b = true;
 
396
        }
 
397
 
 
398
        thread.wait( 2000 );
 
399
        assertFalse( thread.isRunning() );
 
400
    }
 
401
 
 
402
    {
 
403
        kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
 
404
        assertEqual( p->n, 5u );
 
405
        assertEqual( p->f, 3.14 );
 
406
        assertEqual( p->c, 'A' );
 
407
        assertFalse( p->b );
 
408
    }
 
409
 
 
410
    {
 
411
        kdtools::KDLockedSharedMemoryPointer< TestStruct > p( mem );
 
412
        assertEqual( mem.data(), p.get() );
 
413
        assertEqual( p.get(), p.operator->() );
 
414
        assertEqual( p.get(), &(*p) );
 
415
        assertEqual( p.get(), p.data() );
 
416
        assertFalse( isConst( p.get() ) );
 
417
    }
 
418
 
 
419
    {
 
420
        const kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem );
 
421
        assertEqual( mem.data(), p.get() );
 
422
        assertEqual( p.get(), p.operator->() );
 
423
        assertEqual( p.get(), &(*p) );
 
424
        assertEqual( p.get(), p.data() );
 
425
        assertTrue( isConst( p.get() ) );
 
426
    }
 
427
 
 
428
    {
 
429
        QSharedMemory mem2( key + key );
 
430
        const bool created2 = mem2.create( 16 * sizeof( TestStruct ) );
 
431
        assertTrue( created2 );
 
432
        if ( !created2 )
 
433
            return; // don't execute tests if shm coulnd't be created
 
434
 
 
435
        kdtools::KDLockedSharedMemoryArray<TestStruct> a( mem2 );
 
436
        assertTrue( a );
 
437
        assertEqual( a.get(), mem2.data() );
 
438
        assertEqual( &a[0], a.get() );
 
439
 
 
440
        a[1] = a[0];
 
441
        assertTrue( a[0] == a[1] );
 
442
 
 
443
        TestStruct ts;
 
444
        ts.n = 5;
 
445
        ts.f = 3.14;
 
446
        a[0] = ts;
 
447
        assertFalse( a[0] == a[1] );
 
448
        assertEqual( a.front().n, ts.n );
 
449
        assertEqual( a[0].f, ts.f );
 
450
        a[0].n = 10;
 
451
        assertEqual( a.front().n, 10u );
 
452
        ts = a[0];
 
453
        assertEqual( ts.n, 10u );
 
454
 
 
455
        std::vector< TestStruct > v;
 
456
        for( uint i = 0; i < a.size(); ++i )
 
457
            v.push_back( TestStruct( i ) );
 
458
 
 
459
        std::copy( v.begin(), v.end(), a.begin() );
 
460
        for( uint i = 0; i < a.size(); ++i )
 
461
            assertEqual( a[ i ].n, i );
 
462
        assertEqual( a.front().n, 0u );
 
463
        assertEqual( a.back().n, a.size() - 1 );
 
464
 
 
465
        std::copy( v.begin(), v.end(), a.rbegin() );
 
466
        for( uint i = 0; i < a.size(); ++i )
 
467
            assertEqual( a[ i ].n, a.size() - 1 - i );
 
468
        assertEqual( a.front().n, a.size() - 1 );
 
469
        assertEqual( a.back().n, 0u );
 
470
     }
 
471
 
 
472
}
 
473
#endif // KDTOOLSCORE_UNITTESTS
 
474
#endif // QT_NO_SHAREDMEMORY
 
475
#endif // QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN )