|
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 #include <qtconcurrentrun.h> |
|
42 // #include <qtconcurrentcreatefunctor.h> |
|
43 #include <qfuture.h> |
|
44 #include <QString> |
|
45 #include <QtTest/QtTest> |
|
46 #include "../qfuture/versioncheck.h" |
|
47 |
|
48 #ifndef QT_NO_CONCURRENT_TEST |
|
49 |
|
50 using namespace QtConcurrent; |
|
51 |
|
52 class TestRunFunction: public QObject |
|
53 { |
|
54 Q_OBJECT |
|
55 private slots: |
|
56 void runLightFunction(); |
|
57 void runHeavyFunction(); |
|
58 void returnValue(); |
|
59 void functionObject(); |
|
60 void memberFunctions(); |
|
61 void implicitConvertibleTypes(); |
|
62 void runWaitLoop(); |
|
63 void recursive(); |
|
64 #if 0 |
|
65 void createFunctor(); |
|
66 #endif |
|
67 }; |
|
68 |
|
69 #if 0 |
|
70 # define F(X) createFunctor(X) |
|
71 #else |
|
72 # define F(X) X |
|
73 #endif |
|
74 |
|
75 |
|
76 QTEST_MAIN(TestRunFunction) |
|
77 |
|
78 void light() |
|
79 { |
|
80 qDebug("in function"); |
|
81 qDebug("done function"); |
|
82 } |
|
83 |
|
84 void heavy() |
|
85 { |
|
86 qDebug("in function"); |
|
87 QString str; |
|
88 for (int i = 0; i < 1000000; ++i) |
|
89 str.append("a"); |
|
90 qDebug("done function"); |
|
91 } |
|
92 |
|
93 |
|
94 void TestRunFunction::runLightFunction() |
|
95 { |
|
96 qDebug("starting function"); |
|
97 QFuture<void> future = run(F(light)); |
|
98 qDebug("waiting"); |
|
99 future.waitForFinished(); |
|
100 qDebug("done"); |
|
101 } |
|
102 |
|
103 void TestRunFunction::runHeavyFunction() |
|
104 { |
|
105 qDebug("starting function"); |
|
106 QFuture<void> future = run(F(heavy)); |
|
107 qDebug("waiting"); |
|
108 future.waitForFinished(); |
|
109 qDebug("done"); |
|
110 } |
|
111 |
|
112 int returnInt0() |
|
113 { |
|
114 return 10; |
|
115 } |
|
116 |
|
117 int returnInt1(int i) |
|
118 { |
|
119 return i; |
|
120 } |
|
121 |
|
122 class A |
|
123 { |
|
124 public: |
|
125 int member0() { return 10; } |
|
126 int member1(int in) { return in; } |
|
127 |
|
128 typedef int result_type; |
|
129 int operator()() { return 10; } |
|
130 int operator()(int in) { return in; } |
|
131 }; |
|
132 |
|
133 class AConst |
|
134 { |
|
135 public: |
|
136 int member0() const { return 10; } |
|
137 int member1(int in) const { return in; } |
|
138 |
|
139 typedef int result_type; |
|
140 int operator()() const { return 10; } |
|
141 int operator()(int in) const { return in; } |
|
142 }; |
|
143 |
|
144 void TestRunFunction::returnValue() |
|
145 { |
|
146 QFuture<int> f; |
|
147 |
|
148 f = run(F(returnInt0)); |
|
149 QCOMPARE(f.result(), 10); |
|
150 |
|
151 A a; |
|
152 f = run(&a, F(&A::member0)); |
|
153 QCOMPARE(f.result(), 10); |
|
154 |
|
155 f = run(&a, F(&A::member1), 20); |
|
156 QCOMPARE(f.result(), 20); |
|
157 |
|
158 f = run(a, F(&A::member0)); |
|
159 QCOMPARE(f.result(), 10); |
|
160 |
|
161 f = run(a, F(&A::member1), 20); |
|
162 QCOMPARE(f.result(), 20); |
|
163 |
|
164 f = run(a); |
|
165 QCOMPARE(f.result(), 10); |
|
166 |
|
167 f = run(&a); |
|
168 QCOMPARE(f.result(), 10); |
|
169 |
|
170 f = run(a, 20); |
|
171 QCOMPARE(f.result(), 20); |
|
172 |
|
173 f = run(&a, 20); |
|
174 QCOMPARE(f.result(), 20); |
|
175 |
|
176 const AConst aConst = AConst(); |
|
177 f = run(&aConst, &AConst::member0); |
|
178 QCOMPARE(f.result(), 10); |
|
179 |
|
180 f = run(&aConst, F(&AConst::member1), 20); |
|
181 QCOMPARE(f.result(), 20); |
|
182 |
|
183 f = run(aConst, F(&AConst::member0)); |
|
184 QCOMPARE(f.result(), 10); |
|
185 |
|
186 f = run(aConst, F(&AConst::member1), 20); |
|
187 QCOMPARE(f.result(), 20); |
|
188 |
|
189 f = run(aConst); |
|
190 QCOMPARE(f.result(), 10); |
|
191 |
|
192 f = run(&aConst); |
|
193 QCOMPARE(f.result(), 10); |
|
194 |
|
195 f = run(aConst, 20); |
|
196 QCOMPARE(f.result(), 20); |
|
197 |
|
198 f = run(&aConst, 20); |
|
199 QCOMPARE(f.result(), 20); |
|
200 } |
|
201 |
|
202 struct TestClass |
|
203 { |
|
204 void foo() { } |
|
205 typedef void result_type; |
|
206 void operator()() { } |
|
207 void operator()(int) { } |
|
208 void fooInt(int){ }; |
|
209 }; |
|
210 |
|
211 struct TestConstClass |
|
212 { |
|
213 void foo() const { } |
|
214 typedef void result_type; |
|
215 void operator()() const { } |
|
216 void operator()(int) const { } |
|
217 void fooInt(int) const { }; |
|
218 }; |
|
219 |
|
220 void TestRunFunction::functionObject() |
|
221 { |
|
222 QFuture<void> f; |
|
223 TestClass c; |
|
224 |
|
225 f = run(c); |
|
226 f = run(F(&c)); |
|
227 f = run(c, 10); |
|
228 f = run(F(&c), 10); |
|
229 |
|
230 const TestConstClass cc = TestConstClass(); |
|
231 f = run(cc); |
|
232 f = run(F(&cc)); |
|
233 f = run(cc, 10); |
|
234 f = run(F(&cc), 10); |
|
235 } |
|
236 |
|
237 |
|
238 void TestRunFunction::memberFunctions() |
|
239 { |
|
240 TestClass c; |
|
241 |
|
242 run(c, F(&TestClass::foo)).waitForFinished(); |
|
243 run(&c, F(&TestClass::foo)).waitForFinished(); |
|
244 run(c, F(&TestClass::fooInt), 10).waitForFinished(); |
|
245 run(&c, F(&TestClass::fooInt), 10).waitForFinished(); |
|
246 |
|
247 const TestConstClass cc = TestConstClass(); |
|
248 run(cc, F(&TestConstClass::foo)).waitForFinished(); |
|
249 run(&cc, F(&TestConstClass::foo)).waitForFinished(); |
|
250 run(cc, F(&TestConstClass::fooInt), 10).waitForFinished(); |
|
251 run(&cc, F(&TestConstClass::fooInt), 10).waitForFinished(); |
|
252 } |
|
253 |
|
254 |
|
255 void doubleFunction(double) |
|
256 { |
|
257 |
|
258 } |
|
259 |
|
260 void stringConstRefFunction(const QString &) |
|
261 { |
|
262 |
|
263 } |
|
264 |
|
265 void stringRefFunction(QString &) |
|
266 { |
|
267 |
|
268 } |
|
269 |
|
270 void stringFunction(QString) |
|
271 { |
|
272 |
|
273 } |
|
274 |
|
275 void stringIntFunction(QString) |
|
276 { |
|
277 |
|
278 } |
|
279 |
|
280 |
|
281 void TestRunFunction::implicitConvertibleTypes() |
|
282 { |
|
283 double d; |
|
284 run(F(doubleFunction), d).waitForFinished(); |
|
285 int i; |
|
286 run(F(doubleFunction), d).waitForFinished(); |
|
287 run(F(doubleFunction), i).waitForFinished(); |
|
288 run(F(doubleFunction), 10).waitForFinished(); |
|
289 run(F(stringFunction), QLatin1String("Foo")).waitForFinished(); |
|
290 run(F(stringConstRefFunction), QLatin1String("Foo")).waitForFinished(); |
|
291 QString string; |
|
292 run(F(stringRefFunction), string).waitForFinished(); |
|
293 } |
|
294 |
|
295 void fn() { } |
|
296 |
|
297 void TestRunFunction::runWaitLoop() |
|
298 { |
|
299 for (int i = 0; i < 1000; ++i) |
|
300 run(fn).waitForFinished(); |
|
301 } |
|
302 |
|
303 QAtomicInt count; |
|
304 |
|
305 void recursiveRun(int level) |
|
306 { |
|
307 count.ref(); |
|
308 if (--level > 0) { |
|
309 QFuture<void> f1 = run(recursiveRun, level); |
|
310 QFuture<void> f2 = run(recursiveRun, level); |
|
311 f1.waitForFinished(); |
|
312 f2.waitForFinished(); |
|
313 } |
|
314 } |
|
315 |
|
316 int recursiveResult(int level) |
|
317 { |
|
318 count.ref(); |
|
319 if (--level > 0) { |
|
320 QFuture<int> f1 = run(recursiveResult, level); |
|
321 QFuture<int> f2 = run(recursiveResult, level); |
|
322 return f1.result() + f2.result(); |
|
323 } |
|
324 return 1; |
|
325 } |
|
326 |
|
327 void TestRunFunction::recursive() |
|
328 { |
|
329 int levels = 15; |
|
330 |
|
331 for (int i = 0; i < QThread::idealThreadCount(); ++i) { |
|
332 count = 0; |
|
333 QThreadPool::globalInstance()->setMaxThreadCount(i); |
|
334 recursiveRun(levels); |
|
335 QCOMPARE((int)count, (int)pow(2.0, levels) - 1); |
|
336 } |
|
337 |
|
338 for (int i = 0; i < QThread::idealThreadCount(); ++i) { |
|
339 count = 0; |
|
340 QThreadPool::globalInstance()->setMaxThreadCount(i); |
|
341 recursiveResult(levels); |
|
342 QCOMPARE((int)count, (int)pow(2.0, levels) - 1); |
|
343 } |
|
344 } |
|
345 |
|
346 int e; |
|
347 void vfn0() |
|
348 { |
|
349 ++e; |
|
350 } |
|
351 |
|
352 int fn0() |
|
353 { |
|
354 return 1; |
|
355 } |
|
356 |
|
357 void vfn1(double) |
|
358 { |
|
359 ++e; |
|
360 } |
|
361 |
|
362 int fn1(int) |
|
363 { |
|
364 return 1; |
|
365 } |
|
366 |
|
367 void vfn2(double, int *) |
|
368 { |
|
369 ++e; |
|
370 } |
|
371 |
|
372 int fn2(double, int *) |
|
373 { |
|
374 return 1; |
|
375 } |
|
376 |
|
377 #if 0 |
|
378 void TestRunFunction::createFunctor() |
|
379 { |
|
380 e = 0; |
|
381 ::QtConcurrent::createFunctor(vfn0)(); |
|
382 e += QtConcurrent::createFunctor(fn0)(); |
|
383 ::QtConcurrent::createFunctor(vfn1)(1); // implicit conversions should work |
|
384 e += QtConcurrent::createFunctor(fn1)(2); |
|
385 ::QtConcurrent::createFunctor(vfn2)(1.0, &e); |
|
386 e += QtConcurrent::createFunctor(fn2)(2, &e); |
|
387 QCOMPARE(e, 6); |
|
388 |
|
389 |
|
390 e = 0; |
|
391 TestClass c; |
|
392 |
|
393 // ::QtConcurrent::createFunctor(c, &TestClass::foo)(); |
|
394 ::QtConcurrent::createFunctor(&c, &TestClass::foo)(); |
|
395 // ::QtConcurrent::createFunctor(c, &TestClass::fooInt)(10); |
|
396 ::QtConcurrent::createFunctor(&c, &TestClass::fooInt)(10); |
|
397 |
|
398 const TestConstClass cc = TestConstClass(); |
|
399 /* |
|
400 ::QtConcurrent::createFunctor(cc, &TestConstClass::foo)(); |
|
401 ::QtConcurrent::createFunctor(&cc, &TestConstClass::foo)(); |
|
402 ::QtConcurrent::createFunctor(cc, &TestConstClass::fooInt(10); |
|
403 ::QtConcurrent::createFunctor(&cc, &TestConstClass::fooInt)(10); |
|
404 */ |
|
405 qDebug() << e; |
|
406 } |
|
407 #endif |
|
408 |
|
409 #include "tst_qtconcurrentrun.moc" |
|
410 |
|
411 #else |
|
412 QTEST_NOOP_MAIN |
|
413 #endif |