tests/auto/qatomicpointer/tst_qatomicpointer.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 test suite 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 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <qatomic.h>
       
    46 
       
    47 #include <limits.h>
       
    48 
       
    49 //TESTED_CLASS=
       
    50 //TESTED_FILES=
       
    51 
       
    52 class tst_QAtomicPointer : public QObject
       
    53 {
       
    54     Q_OBJECT
       
    55 
       
    56 public:
       
    57     tst_QAtomicPointer();
       
    58     ~tst_QAtomicPointer();
       
    59 
       
    60 private slots:
       
    61     void warningFree();
       
    62 
       
    63     void constructor();
       
    64     void copy_constructor();
       
    65     void equality_operator();
       
    66     void inequality_operator();
       
    67     void assignment_operator();
       
    68     void star_operator();
       
    69     void dereference_operator();
       
    70 
       
    71     void isTestAndSetNative();
       
    72     void isTestAndSetWaitFree();
       
    73     void testAndSet();
       
    74 
       
    75     void isFetchAndStoreNative();
       
    76     void isFetchAndStoreWaitFree();
       
    77     void fetchAndStore();
       
    78 
       
    79     void isFetchAndAddNative();
       
    80     void isFetchAndAddWaitFree();
       
    81     void fetchAndAdd_data();
       
    82     void fetchAndAdd();
       
    83 
       
    84 private:
       
    85     static void warningFreeHelper();
       
    86 };
       
    87 
       
    88 tst_QAtomicPointer::tst_QAtomicPointer()
       
    89 { }
       
    90 
       
    91 tst_QAtomicPointer::~tst_QAtomicPointer()
       
    92 { }
       
    93 
       
    94 struct WFHC
       
    95 {
       
    96     void bar() {}
       
    97 };
       
    98 
       
    99 void tst_QAtomicPointer::warningFreeHelper()
       
   100 {
       
   101     Q_ASSERT(false);
       
   102     // The code below is bogus, and shouldn't be run. We're looking for warnings, only.
       
   103 
       
   104     QBasicAtomicPointer<WFHC> p = Q_BASIC_ATOMIC_INITIALIZER(0);
       
   105 
       
   106     p->bar();
       
   107 
       
   108     WFHC *expectedValue = 0;
       
   109     WFHC *newValue = 0;
       
   110     qptrdiff valueToAdd = 0;
       
   111 
       
   112     p.testAndSetRelaxed(expectedValue, newValue);
       
   113     p.testAndSetAcquire(expectedValue, newValue);
       
   114     p.testAndSetRelease(expectedValue, newValue);
       
   115     p.testAndSetOrdered(expectedValue, newValue);
       
   116 
       
   117     p.fetchAndStoreRelaxed(newValue);
       
   118     p.fetchAndStoreAcquire(newValue);
       
   119     p.fetchAndStoreRelease(newValue);
       
   120     p.fetchAndStoreOrdered(newValue);
       
   121 
       
   122     p.fetchAndAddRelaxed(valueToAdd);
       
   123     p.fetchAndAddAcquire(valueToAdd);
       
   124     p.fetchAndAddRelease(valueToAdd);
       
   125     p.fetchAndAddOrdered(valueToAdd);
       
   126 }
       
   127 
       
   128 void tst_QAtomicPointer::warningFree()
       
   129 {
       
   130     // This is a compile time check for warnings.
       
   131     // No need for actual work here.
       
   132 
       
   133     void (*foo)() = &warningFreeHelper;
       
   134     (void)foo;
       
   135 }
       
   136 
       
   137 void tst_QAtomicPointer::constructor()
       
   138 {
       
   139     void *one = this;
       
   140     QAtomicPointer<void> atomic1 = one;
       
   141     QVERIFY(atomic1 == one);
       
   142 
       
   143     void *two = &one;
       
   144     QAtomicPointer<void> atomic2 = two;
       
   145     QVERIFY(atomic2 == two);
       
   146 
       
   147     void *three = &two;
       
   148     QAtomicPointer<void> atomic3 = three;
       
   149     QVERIFY(atomic3 == three);
       
   150 }
       
   151 
       
   152 void tst_QAtomicPointer::copy_constructor()
       
   153 {
       
   154     void *one = this;
       
   155     QAtomicPointer<void> atomic1 = one;
       
   156     QAtomicPointer<void> atomic1_copy = atomic1;
       
   157     QVERIFY(atomic1_copy == one);
       
   158     QCOMPARE(atomic1_copy, atomic1);
       
   159 
       
   160     void *two = &one;
       
   161     QAtomicPointer<void> atomic2 = two;
       
   162     QAtomicPointer<void> atomic2_copy = atomic2;
       
   163     QVERIFY(atomic2_copy == two);
       
   164     QCOMPARE(atomic2_copy, atomic2);
       
   165 
       
   166     void *three = &two;
       
   167     QAtomicPointer<void> atomic3 = three;
       
   168     QAtomicPointer<void> atomic3_copy = atomic3;
       
   169     QVERIFY(atomic3_copy == three);
       
   170     QCOMPARE(atomic3_copy, atomic3);
       
   171 }
       
   172 
       
   173 void tst_QAtomicPointer::equality_operator()
       
   174 {
       
   175     void *one = this;
       
   176     void *two = &one;
       
   177     void *three = &two;
       
   178 
       
   179     QAtomicPointer<void> atomic1 = one;
       
   180     QAtomicPointer<void> atomic2 = two;
       
   181     QAtomicPointer<void> atomic3 = three;
       
   182 
       
   183     QVERIFY(atomic1 == one);
       
   184     QVERIFY(!(atomic1 == two));
       
   185     QVERIFY(!(atomic1 == three));
       
   186 
       
   187     QVERIFY(!(atomic2 == one));
       
   188     QVERIFY(atomic2 == two);
       
   189     QVERIFY(!(atomic2 == three));
       
   190 
       
   191     QVERIFY(!(atomic3 == one));
       
   192     QVERIFY(!(atomic3 == two));
       
   193     QVERIFY(atomic3 == three);
       
   194 }
       
   195 
       
   196 void tst_QAtomicPointer::inequality_operator()
       
   197 {
       
   198     void *one = this;
       
   199     void *two = &one;
       
   200     void *three = &two;
       
   201 
       
   202     QAtomicPointer<void> atomic1 = one;
       
   203     QAtomicPointer<void> atomic2 = two;
       
   204     QAtomicPointer<void> atomic3 = three;
       
   205 
       
   206     QVERIFY(!(atomic1 != one));
       
   207     QVERIFY(atomic1 != two);
       
   208     QVERIFY(atomic1 != three);
       
   209 
       
   210     QVERIFY(atomic2 != one);
       
   211     QVERIFY(!(atomic2 != two));
       
   212     QVERIFY(atomic2 != three);
       
   213 
       
   214     QVERIFY(atomic3 != one);
       
   215     QVERIFY(atomic3 != two);
       
   216     QVERIFY(!(atomic3 != three));
       
   217 }
       
   218 
       
   219 void tst_QAtomicPointer::assignment_operator()
       
   220 {
       
   221     void *one = this;
       
   222     void *two = &one;
       
   223     void *three = &two;
       
   224 
       
   225     QAtomicPointer<void> atomic1 = one;
       
   226     QAtomicPointer<void> atomic2 = two;
       
   227     QAtomicPointer<void> atomic3 = three;
       
   228 
       
   229     QVERIFY(atomic1 == one);
       
   230     QVERIFY(atomic2 == two);
       
   231     QVERIFY(atomic3 == three);
       
   232 
       
   233     atomic1 = two;
       
   234     atomic2 = three;
       
   235     atomic3 = one;
       
   236 
       
   237     QVERIFY(atomic1 == two);
       
   238     QVERIFY(atomic2 == three);
       
   239     QVERIFY(atomic3 == one);
       
   240 }
       
   241 
       
   242 struct Type
       
   243 {
       
   244     inline const Type *self() const
       
   245     { return this; }
       
   246 };
       
   247 
       
   248 void tst_QAtomicPointer::star_operator()
       
   249 {
       
   250     Type t;
       
   251     QAtomicPointer<Type> p = &t;
       
   252     QCOMPARE((*p).self(), t.self());
       
   253 }
       
   254 
       
   255 void tst_QAtomicPointer::dereference_operator()
       
   256 {
       
   257     Type t;
       
   258     QAtomicPointer<Type> p = &t;
       
   259     QCOMPARE(p->self(), t.self());
       
   260 }
       
   261 
       
   262 void tst_QAtomicPointer::isTestAndSetNative()
       
   263 {
       
   264 #if defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE)
       
   265     // the runtime test should say the same thing
       
   266     QVERIFY(QAtomicPointer<void>::isTestAndSetNative());
       
   267 
       
   268 #  if (defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE)     \
       
   269        || defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE))
       
   270 #    error "Define only one of Q_ATOMIC_POINTER_TEST_AND_SET_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   271 #  endif
       
   272 #elif defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE)
       
   273     // could be either, just want to make sure the function is implemented
       
   274     QVERIFY(QAtomicPointer<void>::isTestAndSetNative()
       
   275             || !QAtomicPointer<void>::isTestAndSetNative());
       
   276 
       
   277 #  if (defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE) \
       
   278        || defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE))
       
   279 #    error "Define only one of Q_ATOMIC_POINTER_TEST_AND_SET_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   280 #  endif
       
   281 #elif defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE)
       
   282     // the runtime test should say the same thing
       
   283     QVERIFY(!QAtomicPointer<void>::isTestAndSetNative());
       
   284 
       
   285 #  if (defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_ALWAYS_NATIVE) \
       
   286        || defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_SOMETIMES_NATIVE))
       
   287 #    error "Define only one of Q_ATOMIC_POINTER_TEST_AND_SET_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   288 #  endif
       
   289 #else
       
   290 #  error "Q_ATOMIC_POINTER_TEST_AND_SET_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE is not defined"
       
   291 #endif
       
   292 }
       
   293 
       
   294 void tst_QAtomicPointer::isTestAndSetWaitFree()
       
   295 {
       
   296 #if defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_WAIT_FREE)
       
   297     // the runtime test should say the same thing
       
   298     QVERIFY(QAtomicPointer<void>::isTestAndSetWaitFree());
       
   299 
       
   300     // enforce some invariants
       
   301     QVERIFY(QAtomicPointer<void>::isTestAndSetNative());
       
   302 #  if defined(Q_ATOMIC_POINTER_TEST_AND_SET_IS_NOT_NATIVE)
       
   303 #    error "Reference counting cannot be wait-free and unsupported at the same time!"
       
   304 #  endif
       
   305 #else
       
   306     // the runtime test should say the same thing
       
   307     QVERIFY(!QAtomicPointer<void>::isTestAndSetWaitFree());
       
   308 #endif
       
   309 }
       
   310 
       
   311 void tst_QAtomicPointer::testAndSet()
       
   312 {
       
   313     void *one = this;
       
   314     void *two = &one;
       
   315     void *three = &two;
       
   316 
       
   317     {
       
   318         QAtomicPointer<void> atomic1 = one;
       
   319         QAtomicPointer<void> atomic2 = two;
       
   320         QAtomicPointer<void> atomic3 = three;
       
   321 
       
   322         QVERIFY(atomic1 == one);
       
   323         QVERIFY(atomic2 == two);
       
   324         QVERIFY(atomic3 == three);
       
   325 
       
   326         QVERIFY(atomic1.testAndSetRelaxed(one, two));
       
   327         QVERIFY(atomic2.testAndSetRelaxed(two, three));
       
   328         QVERIFY(atomic3.testAndSetRelaxed(three, one));
       
   329 
       
   330         QVERIFY(atomic1 == two);
       
   331         QVERIFY(atomic2 == three);
       
   332         QVERIFY(atomic3 == one);
       
   333     }
       
   334 
       
   335     {
       
   336         QAtomicPointer<void> atomic1 = one;
       
   337         QAtomicPointer<void> atomic2 = two;
       
   338         QAtomicPointer<void> atomic3 = three;
       
   339 
       
   340         QVERIFY(atomic1 == one);
       
   341         QVERIFY(atomic2 == two);
       
   342         QVERIFY(atomic3 == three);
       
   343 
       
   344         QVERIFY(atomic1.testAndSetAcquire(one, two));
       
   345         QVERIFY(atomic2.testAndSetAcquire(two, three));
       
   346         QVERIFY(atomic3.testAndSetAcquire(three, one));
       
   347 
       
   348         QVERIFY(atomic1 == two);
       
   349         QVERIFY(atomic2 == three);
       
   350         QVERIFY(atomic3 == one);
       
   351     }
       
   352 
       
   353     {
       
   354         QAtomicPointer<void> atomic1 = one;
       
   355         QAtomicPointer<void> atomic2 = two;
       
   356         QAtomicPointer<void> atomic3 = three;
       
   357 
       
   358         QVERIFY(atomic1 == one);
       
   359         QVERIFY(atomic2 == two);
       
   360         QVERIFY(atomic3 == three);
       
   361 
       
   362         QVERIFY(atomic1.testAndSetRelease(one, two));
       
   363         QVERIFY(atomic2.testAndSetRelease(two, three));
       
   364         QVERIFY(atomic3.testAndSetRelease(three, one));
       
   365 
       
   366         QVERIFY(atomic1 == two);
       
   367         QVERIFY(atomic2 == three);
       
   368         QVERIFY(atomic3 == one);
       
   369     }
       
   370 
       
   371     {
       
   372         QAtomicPointer<void> atomic1 = one;
       
   373         QAtomicPointer<void> atomic2 = two;
       
   374         QAtomicPointer<void> atomic3 = three;
       
   375 
       
   376         QVERIFY(atomic1 == one);
       
   377         QVERIFY(atomic2 == two);
       
   378         QVERIFY(atomic3 == three);
       
   379 
       
   380         QVERIFY(atomic1.testAndSetOrdered(one, two));
       
   381         QVERIFY(atomic2.testAndSetOrdered(two, three));
       
   382         QVERIFY(atomic3.testAndSetOrdered(three, one));
       
   383 
       
   384         QVERIFY(atomic1 == two);
       
   385         QVERIFY(atomic2 == three);
       
   386         QVERIFY(atomic3 == one);
       
   387     }
       
   388 }
       
   389 
       
   390 void tst_QAtomicPointer::isFetchAndStoreNative()
       
   391 {
       
   392 #if defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE)
       
   393     // the runtime test should say the same thing
       
   394     QVERIFY(QAtomicPointer<void>::isFetchAndStoreNative());
       
   395 
       
   396 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE)     \
       
   397        || defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE))
       
   398 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   399 #  endif
       
   400 #elif defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE)
       
   401     // could be either, just want to make sure the function is implemented
       
   402     QVERIFY(QAtomicPointer<void>::isFetchAndStoreNative()
       
   403             || !QAtomicPointer<void>::isFetchAndStoreNative());
       
   404 
       
   405 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE) \
       
   406        || defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE))
       
   407 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   408 #  endif
       
   409 #elif defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE)
       
   410     // the runtime test should say the same thing
       
   411     QVERIFY(!QAtomicPointer<void>::isFetchAndStoreNative());
       
   412 
       
   413 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_ALWAYS_NATIVE) \
       
   414        || defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_SOMETIMES_NATIVE))
       
   415 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   416 #  endif
       
   417 #else
       
   418 #  error "Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE is not defined"
       
   419 #endif
       
   420 }
       
   421 
       
   422 void tst_QAtomicPointer::isFetchAndStoreWaitFree()
       
   423 {
       
   424 #if defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_WAIT_FREE)
       
   425     // the runtime test should say the same thing
       
   426     QVERIFY(QAtomicPointer<void>::isFetchAndStoreWaitFree());
       
   427 
       
   428     // enforce some invariants
       
   429     QVERIFY(QAtomicPointer<void>::isFetchAndStoreNative());
       
   430 #  if defined(Q_ATOMIC_POINTER_FETCH_AND_STORE_IS_NOT_NATIVE)
       
   431 #    error "Reference counting cannot be wait-free and unsupported at the same time!"
       
   432 #  endif
       
   433 #else
       
   434     // the runtime test should say the same thing
       
   435     QVERIFY(!QAtomicPointer<void>::isFetchAndStoreWaitFree());
       
   436 #endif
       
   437 }
       
   438 
       
   439 void tst_QAtomicPointer::fetchAndStore()
       
   440 {
       
   441     void *one = this;
       
   442     void *two = &one;
       
   443     void *three = &two;
       
   444 
       
   445     {
       
   446         QAtomicPointer<void> atomic1 = one;
       
   447         QAtomicPointer<void> atomic2 = two;
       
   448         QAtomicPointer<void> atomic3 = three;
       
   449 
       
   450         QVERIFY(atomic1 == one);
       
   451         QVERIFY(atomic2 == two);
       
   452         QVERIFY(atomic3 == three);
       
   453 
       
   454         QCOMPARE(atomic1.fetchAndStoreRelaxed(two), one);
       
   455         QCOMPARE(atomic2.fetchAndStoreRelaxed(three), two);
       
   456         QCOMPARE(atomic3.fetchAndStoreRelaxed(one), three);
       
   457 
       
   458         QVERIFY(atomic1 == two);
       
   459         QVERIFY(atomic2 == three);
       
   460         QVERIFY(atomic3 == one);
       
   461     }
       
   462 
       
   463     {
       
   464         QAtomicPointer<void> atomic1 = one;
       
   465         QAtomicPointer<void> atomic2 = two;
       
   466         QAtomicPointer<void> atomic3 = three;
       
   467 
       
   468         QVERIFY(atomic1 == one);
       
   469         QVERIFY(atomic2 == two);
       
   470         QVERIFY(atomic3 == three);
       
   471 
       
   472         QCOMPARE(atomic1.fetchAndStoreAcquire(two), one);
       
   473         QCOMPARE(atomic2.fetchAndStoreAcquire(three), two);
       
   474         QCOMPARE(atomic3.fetchAndStoreAcquire(one), three);
       
   475 
       
   476         QVERIFY(atomic1 == two);
       
   477         QVERIFY(atomic2 == three);
       
   478         QVERIFY(atomic3 == one);
       
   479     }
       
   480 
       
   481     {
       
   482         QAtomicPointer<void> atomic1 = one;
       
   483         QAtomicPointer<void> atomic2 = two;
       
   484         QAtomicPointer<void> atomic3 = three;
       
   485 
       
   486         QVERIFY(atomic1 == one);
       
   487         QVERIFY(atomic2 == two);
       
   488         QVERIFY(atomic3 == three);
       
   489 
       
   490         QCOMPARE(atomic1.fetchAndStoreRelease(two), one);
       
   491         QCOMPARE(atomic2.fetchAndStoreRelease(three), two);
       
   492         QCOMPARE(atomic3.fetchAndStoreRelease(one), three);
       
   493 
       
   494         QVERIFY(atomic1 == two);
       
   495         QVERIFY(atomic2 == three);
       
   496         QVERIFY(atomic3 == one);
       
   497     }
       
   498 
       
   499     {
       
   500         QAtomicPointer<void> atomic1 = one;
       
   501         QAtomicPointer<void> atomic2 = two;
       
   502         QAtomicPointer<void> atomic3 = three;
       
   503 
       
   504         QVERIFY(atomic1 == one);
       
   505         QVERIFY(atomic2 == two);
       
   506         QVERIFY(atomic3 == three);
       
   507 
       
   508         QCOMPARE(atomic1.fetchAndStoreOrdered(two), one);
       
   509         QCOMPARE(atomic2.fetchAndStoreOrdered(three), two);
       
   510         QCOMPARE(atomic3.fetchAndStoreOrdered(one), three);
       
   511 
       
   512         QVERIFY(atomic1 == two);
       
   513         QVERIFY(atomic2 == three);
       
   514         QVERIFY(atomic3 == one);
       
   515     }
       
   516 }
       
   517 
       
   518 void tst_QAtomicPointer::isFetchAndAddNative()
       
   519 {
       
   520 #if defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE)
       
   521     // the runtime test should say the same thing
       
   522     QVERIFY(QAtomicPointer<void>::isFetchAndAddNative());
       
   523 
       
   524 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE)     \
       
   525        || defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE))
       
   526 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   527 #  endif
       
   528 #elif defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE)
       
   529     // could be either, just want to make sure the function is implemented
       
   530     QVERIFY(QAtomicPointer<void>::isFetchAndAddNative()
       
   531             || !QAtomicPointer<void>::isFetchAndAddNative());
       
   532 
       
   533 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE) \
       
   534        || defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE))
       
   535 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   536 #  endif
       
   537 #elif defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE)
       
   538     // the runtime test should say the same thing
       
   539     QVERIFY(!QAtomicPointer<void>::isFetchAndAddNative());
       
   540 
       
   541 #  if (defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_ALWAYS_NATIVE) \
       
   542        || defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_SOMETIMES_NATIVE))
       
   543 #    error "Define only one of Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE"
       
   544 #  endif
       
   545 #else
       
   546 #  error "Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_{ALWAYS,SOMTIMES,NOT}_NATIVE is not defined"
       
   547 #endif
       
   548 }
       
   549 
       
   550 void tst_QAtomicPointer::isFetchAndAddWaitFree()
       
   551 {
       
   552 #if defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_WAIT_FREE)
       
   553     // the runtime test should say the same thing
       
   554     QVERIFY(QAtomicPointer<void>::isFetchAndAddWaitFree());
       
   555 
       
   556     // enforce some invariants
       
   557     QVERIFY(QAtomicPointer<void>::isFetchAndAddNative());
       
   558 #  if defined(Q_ATOMIC_POINTER_FETCH_AND_ADD_IS_NOT_NATIVE)
       
   559 #    error "Reference counting cannot be wait-free and unsupported at the same time!"
       
   560 #  endif
       
   561 #else
       
   562     // the runtime test should say the same thing
       
   563     QVERIFY(!QAtomicPointer<void>::isFetchAndAddWaitFree());
       
   564 #endif
       
   565 }
       
   566 
       
   567 void tst_QAtomicPointer::fetchAndAdd_data()
       
   568 {
       
   569     QTest::addColumn<int>("valueToAdd");
       
   570 
       
   571     QTest::newRow("0") << 0;
       
   572     QTest::newRow("1") << 1;
       
   573     QTest::newRow("2") << 2;
       
   574     QTest::newRow("10") << 10;
       
   575     QTest::newRow("31") << 31;
       
   576     QTest::newRow("51") << 51;
       
   577     QTest::newRow("72") << 72;
       
   578     QTest::newRow("810") << 810;
       
   579     QTest::newRow("631") << 631;
       
   580     QTest::newRow("451") << 451;
       
   581     QTest::newRow("272") << 272;
       
   582     QTest::newRow("1810") << 1810;
       
   583     QTest::newRow("3631") << 3631;
       
   584     QTest::newRow("5451") << 5451;
       
   585     QTest::newRow("7272") << 7272;
       
   586     QTest::newRow("-1") << -1;
       
   587     QTest::newRow("-2") << -2;
       
   588     QTest::newRow("-10") << -10;
       
   589     QTest::newRow("-31") << -31;
       
   590     QTest::newRow("-51") << -51;
       
   591     QTest::newRow("-72") << -72;
       
   592     QTest::newRow("-810") << -810;
       
   593     QTest::newRow("-631") << -631;
       
   594     QTest::newRow("-451") << -451;
       
   595     QTest::newRow("-272") << -272;
       
   596     QTest::newRow("-1810") << -1810;
       
   597     QTest::newRow("-3631") << -3631;
       
   598     QTest::newRow("-5451") << -5451;
       
   599     QTest::newRow("-7272") << -7272;
       
   600 }
       
   601 
       
   602 void tst_QAtomicPointer::fetchAndAdd()
       
   603 {
       
   604     QFETCH(int, valueToAdd);
       
   605 
       
   606     char c;
       
   607     char *pc = &c;
       
   608     short s;
       
   609     short *ps = &s;
       
   610     int i;
       
   611     int *pi = &i;
       
   612 
       
   613     {
       
   614         QAtomicPointer<char> pointer1 = pc;
       
   615         QCOMPARE(quintptr(pointer1.fetchAndAddRelaxed(valueToAdd)), quintptr(pc));
       
   616         QCOMPARE(quintptr(pointer1.fetchAndAddRelaxed(-valueToAdd)), quintptr(pc + valueToAdd));
       
   617         QCOMPARE(quintptr(static_cast<char *>(pointer1)), quintptr(pc));
       
   618         QAtomicPointer<short> pointer2 = ps;
       
   619         QCOMPARE(quintptr(pointer2.fetchAndAddRelaxed(valueToAdd)), quintptr(ps));
       
   620         QCOMPARE(quintptr(pointer2.fetchAndAddRelaxed(-valueToAdd)), quintptr(ps + valueToAdd));
       
   621         QCOMPARE(quintptr(static_cast<short *>(pointer2)), quintptr(ps));
       
   622         QAtomicPointer<int> pointer3 = pi;
       
   623         QCOMPARE(quintptr(pointer3.fetchAndAddRelaxed(valueToAdd)), quintptr(pi));
       
   624         QCOMPARE(quintptr(pointer3.fetchAndAddRelaxed(-valueToAdd)), quintptr(pi + valueToAdd));
       
   625         QCOMPARE(quintptr(static_cast<int *>(pointer3)), quintptr(pi));
       
   626     }
       
   627 
       
   628     {
       
   629         QAtomicPointer<char> pointer1 = pc;
       
   630         QCOMPARE(quintptr(pointer1.fetchAndAddAcquire(valueToAdd)), quintptr(pc));
       
   631         QCOMPARE(quintptr(pointer1.fetchAndAddAcquire(-valueToAdd)), quintptr(pc + valueToAdd));
       
   632         QCOMPARE(quintptr(static_cast<char *>(pointer1)), quintptr(pc));
       
   633         QAtomicPointer<short> pointer2 = ps;
       
   634         QCOMPARE(quintptr(pointer2.fetchAndAddAcquire(valueToAdd)), quintptr(ps));
       
   635         QCOMPARE(quintptr(pointer2.fetchAndAddAcquire(-valueToAdd)), quintptr(ps + valueToAdd));
       
   636         QCOMPARE(quintptr(static_cast<short *>(pointer2)), quintptr(ps));
       
   637         QAtomicPointer<int> pointer3 = pi;
       
   638         QCOMPARE(quintptr(pointer3.fetchAndAddAcquire(valueToAdd)), quintptr(pi));
       
   639         QCOMPARE(quintptr(pointer3.fetchAndAddAcquire(-valueToAdd)), quintptr(pi + valueToAdd));
       
   640         QCOMPARE(quintptr(static_cast<int *>(pointer3)), quintptr(pi));
       
   641     }
       
   642 
       
   643     {
       
   644         QAtomicPointer<char> pointer1 = pc;
       
   645         QCOMPARE(quintptr(pointer1.fetchAndAddRelease(valueToAdd)), quintptr(pc));
       
   646         QCOMPARE(quintptr(pointer1.fetchAndAddRelease(-valueToAdd)), quintptr(pc + valueToAdd));
       
   647         QCOMPARE(quintptr(static_cast<char *>(pointer1)), quintptr(pc));
       
   648         QAtomicPointer<short> pointer2 = ps;
       
   649         QCOMPARE(quintptr(pointer2.fetchAndAddRelease(valueToAdd)), quintptr(ps));
       
   650         QCOMPARE(quintptr(pointer2.fetchAndAddRelease(-valueToAdd)), quintptr(ps + valueToAdd));
       
   651         QCOMPARE(quintptr(static_cast<short *>(pointer2)), quintptr(ps));
       
   652         QAtomicPointer<int> pointer3 = pi;
       
   653         QCOMPARE(quintptr(pointer3.fetchAndAddRelease(valueToAdd)), quintptr(pi));
       
   654         QCOMPARE(quintptr(pointer3.fetchAndAddRelease(-valueToAdd)), quintptr(pi + valueToAdd));
       
   655         QCOMPARE(quintptr(static_cast<int *>(pointer3)), quintptr(pi));
       
   656     }
       
   657 
       
   658     {
       
   659         QAtomicPointer<char> pointer1 = pc;
       
   660         QCOMPARE(quintptr(pointer1.fetchAndAddOrdered(valueToAdd)), quintptr(pc));
       
   661         QCOMPARE(quintptr(pointer1.fetchAndAddOrdered(-valueToAdd)), quintptr(pc + valueToAdd));
       
   662         QCOMPARE(quintptr(static_cast<char *>(pointer1)), quintptr(pc));
       
   663         QAtomicPointer<short> pointer2 = ps;
       
   664         QCOMPARE(quintptr(pointer2.fetchAndAddOrdered(valueToAdd)), quintptr(ps));
       
   665         QCOMPARE(quintptr(pointer2.fetchAndAddOrdered(-valueToAdd)), quintptr(ps + valueToAdd));
       
   666         QCOMPARE(quintptr(static_cast<short *>(pointer2)), quintptr(ps));
       
   667         QAtomicPointer<int> pointer3 = pi;
       
   668         QCOMPARE(quintptr(pointer3.fetchAndAddOrdered(valueToAdd)), quintptr(pi));
       
   669         QCOMPARE(quintptr(pointer3.fetchAndAddOrdered(-valueToAdd)), quintptr(pi + valueToAdd));
       
   670         QCOMPARE(quintptr(static_cast<int *>(pointer3)), quintptr(pi));
       
   671     }
       
   672 }
       
   673 
       
   674 QTEST_APPLESS_MAIN(tst_QAtomicPointer)
       
   675 #include "tst_qatomicpointer.moc"