1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include <QDebug>
29 #include <QFile>
30 #include <QDir>
31
32 #include "codegenerator.h"
33 using namespace CodeGenerator;
34
35 const Item argument = "arg" + Counter();
36 const Item argumentRef = "&arg" + Counter();
37 const Item argumentType = "Arg" + Counter();
38 const Item constArgumentType = "const Arg" + Counter();
39 const Item parameterType = "Param" + Counter();
40
41 Group argumentTypes(argumentType); // expands to ",Arg1, Arg2, ..."
42 Group argumentTypesNoPrefix(argumentType); // expands to "Arg1, Arg2, ..."
43 Group arguments(argument); // expands to ",arg1, arg2, ..."
44 Group argumentsNoPrefix(argument); // expands to "arg1, arg2, ..."
45 Group parameterTypes(parameterType); // expands to ",Param1, Param2, ..."
46 Group parameterTypesNoPrefix(parameterType); // expands to "Param1, Param2, ..."
47 Group typenameTypes("typename " + parameterType + ", typename " + argumentType); // expands to " ,typename Param1, typename Arg1, ..."
48 Group types(parameterType + ", " + argumentType); // expands to ", Param1, Arg1, ..."
49 Group functionParameters(constArgumentType + " " + argumentRef);
50 Group typenameArgumentTypes("typename " + argumentType);
51
52 Group initializers(argument + "(" + argument + ")");
53 Group classData(argumentType +" " + argument + ";");
54 Group arglist(argument);
55 Group typeList(argumentTypes);
56
init()57 void init()
58 {
59 argumentTypes.setPrefix(", ");
60 arguments.setPrefix(", ");
61 parameterTypes.setPrefix(", ");
62 typenameTypes.setPrefix(", ");
63 types.setPrefix(", ");
64 functionParameters.setPrefix(", ");
65 typenameArgumentTypes.setPrefix(", ");
66
67 initializers.setPrefix(", ");
68 classData.setSeparator(" ");
69 classData.setPrefix(" ");
70 arglist.setPrefix(", ");
71 typeList.setPrefix(", ");
72 }
73
74
Line(Item item)75 Item Line(Item item)
76 {
77 return item + "\n";
78 }
79
generateRunFunctions(int repeats,bool withExplicitPoolArg)80 Item generateRunFunctions(int repeats, bool withExplicitPoolArg)
81 {
82 Item functionPointerType = "T (*)(" + parameterTypesNoPrefix + ")";
83
84 Item functionPointerParameter = "T (*functionPointer)(" + parameterTypesNoPrefix + ")";
85
86 const Item pool = withExplicitPoolArg ? "QThreadPool *pool, " : "";
87 const char * const startArg = withExplicitPoolArg ? "pool" : "";
88
89 // plain functions
90 Repeater functions = Line ("template <typename T" + typenameTypes + ">") +
91 Line ("QFuture<T> run(" + pool + functionPointerParameter + functionParameters + ")") +
92 Line("{") +
93 Line(" return (new StoredFunctorCall" + Counter() + "<T, " +
94 functionPointerType + argumentTypes + ">(functionPointer" + arguments + "))->start(" + startArg + ");") +
95 Line("}");
96 functions.setRepeatCount(repeats);
97
98 // function objects by value
99 Repeater functionObjects = Line ("template <typename FunctionObject" + typenameArgumentTypes + ">") +
100 Line ("QFuture<typename FunctionObject::result_type> run(" + pool + "FunctionObject functionObject" + functionParameters + ")") +
101 Line("{") +
102 Line(" return (new StoredFunctorCall" + Counter() +
103 "<typename FunctionObject::result_type, FunctionObject" +
104 argumentTypes + ">(functionObject" + arguments + "))->start(" + startArg + ");") +
105 Line("}");
106 functionObjects.setRepeatCount(repeats);
107
108 // function objects by pointer
109 Repeater functionObjectsPointer = Line ("template <typename FunctionObject" + typenameArgumentTypes + ">") +
110 Line ("QFuture<typename FunctionObject::result_type> run(" + pool + "FunctionObject *functionObject" + functionParameters + ")") +
111 Line("{") +
112 Line(" return (new typename SelectStoredFunctorPointerCall" + Counter() +
113 "<typename FunctionObject::result_type, FunctionObject" +
114 argumentTypes + ">::type(functionObject" + arguments + "))->start(" + startArg + ");") +
115 Line("}");
116 functionObjectsPointer.setRepeatCount(repeats);
117
118 // member functions by value
119 Repeater memberFunction = Line ("template <typename T, typename Class" + typenameTypes + ">") +
120 Line ("QFuture<T> run(" + pool + "const Class &object, T (Class::*fn)(" + parameterTypesNoPrefix + ")" + functionParameters + ")") +
121 Line("{") +
122 Line(" return (new typename SelectStoredMemberFunctionCall" + Counter() +
123 "<T, Class" +
124 types + ">::type(fn, object" + arguments + "))->start(" + startArg + ");") +
125 Line("}");
126 memberFunction.setRepeatCount(repeats);
127
128 // const member functions by value
129 Repeater constMemberFunction = Line ("template <typename T, typename Class" + typenameTypes + ">") +
130 Line ("QFuture<T> run(" + pool + "const Class &object, T (Class::*fn)(" + parameterTypesNoPrefix + ") const" + functionParameters + ")") +
131 Line("{") +
132 Line(" return (new typename SelectStoredConstMemberFunctionCall" + Counter() +
133 "<T, Class" +
134 types + ">::type(fn, object" + arguments + "))->start(" + startArg + ");") +
135 Line("}");
136 constMemberFunction.setRepeatCount(repeats);
137
138 // member functions by class pointer
139 Repeater memberFunctionPointer = Line ("template <typename T, typename Class" + typenameTypes + ">") +
140 Line ("QFuture<T> run(" + pool + "Class *object, T (Class::*fn)(" + parameterTypesNoPrefix + ")" + functionParameters + ")") +
141 Line("{") +
142 Line(" return (new typename SelectStoredMemberFunctionPointerCall" + Counter() +
143 "<T, Class" +
144 types + ">::type(fn, object" + arguments + "))->start(" + startArg + ");") +
145 Line("}");
146 memberFunctionPointer.setRepeatCount(repeats);
147
148 // const member functions by class pointer
149 Repeater constMemberFunctionPointer = Line ("template <typename T, typename Class" + typenameTypes + ">") +
150 Line ("QFuture<T> run(" + pool + "const Class *object, T (Class::*fn)(" + parameterTypesNoPrefix + ") const" + functionParameters + ")") +
151 Line("{") +
152 Line(" return (new typename SelectStoredConstMemberFunctionPointerCall" + Counter() +
153 "<T, Class" +
154 types + ">::type(fn, object" + arguments + "))->start(" + startArg + ");") +
155 Line("}");
156 constMemberFunctionPointer.setRepeatCount(repeats);
157
158
159 Item interfaceFunctionPointerType = "void (*)(QFutureInterface<T> &" + argumentTypes + ")";
160 Item interfaceFunctionPointerParameter = "void (*functionPointer)(QFutureInterface<T> &" + argumentTypes + ")";
161 /*
162 // QFutureInterface functions
163 Repeater interfaceFunctions = Line ("template <typename T" + typenameTypes + ">") +
164 Line ("QFuture<T> run(" + pool + interfaceFunctionPointerParameter + functionParameters + ")") +
165 Line("{") +
166 Line(" return (new StoredInterfaceFunctionCall" + Counter() + "<T, " +
167 interfaceFunctionPointerType + typenameArgumentTypes + ">(functionPointer" + arguments + "))->start(" + startArg + ");") +
168 Line("}");
169 functions.setRepeatCount(repeats);
170 interfaceFunctions.setRepeatCount(repeats);
171
172 // member functions by class pointer
173 Repeater interfaceMemberFunction = Line ("template <typename Class, typename T" + typenameTypes + ">") +
174 Line ("QFuture<T> run(" + pool + "void (Class::*fn)(QFutureInterface<T> &), Class *object" + functionParameters + ")") +
175 Line("{") +
176 Line(" return (new StoredInterfaceMemberFunctionCall" + Counter() +
177 "<T, void (Class::*)(QFutureInterface<T> &), Class" +
178 typenameArgumentTypes + ">(fn, object" + arguments + "))->start(" + startArg + ");") +
179 Line("}");
180 memberFunctionPointer.setRepeatCount(repeats);
181 */
182 return functions + Line("") + functionObjects + Line("") + functionObjectsPointer + Line("")
183 + memberFunction + Line("") + constMemberFunction + Line("")
184 + memberFunctionPointer + Line("") + constMemberFunctionPointer + Line("")
185 /* + interfaceFunctions + Line("") + interfaceMemberFunction + Line("")*/
186 ;
187 }
188
189
functions(Item className,Item functorType,Item callLine)190 Item functions(Item className, Item functorType, Item callLine)
191 {
192 return
193 Line("template <typename T, typename FunctionPointer" + typenameArgumentTypes + ">") +
194 Line("struct " + className + Counter() +": public RunFunctionTask<T>") +
195 Line("{") +
196 Line(" inline " + className + Counter() + "(" + functorType + " function" + functionParameters +")") +
197 Line(" : function(function)" + initializers + " {}") +
198 Line(" void runFunctor() {" + callLine + argumentsNoPrefix + "); }") +
199 Line(" " + functorType + " function;") +
200 Line( classData) +
201 Line("};") +
202 Line("");
203 }
204
functionSelector(Item classNameBase)205 Item functionSelector(Item classNameBase)
206 {
207 return
208 Line("template <typename T, typename FunctionPointer" + typenameArgumentTypes + ">") +
209 Line("struct Select" + classNameBase + Counter()) +
210 Line("{") +
211 Line(" typedef typename SelectSpecialization<T>::template") +
212 Line(" Type<" + classNameBase + Counter() + " <T, FunctionPointer" + argumentTypes + ">,") +
213 Line(" Void" + classNameBase + Counter() + "<T, FunctionPointer" + argumentTypes + "> >::type type;") +
214 Line("};");
215 }
216
memberFunctions(Item className,Item constFunction,Item objectArgument,Item objectMember,Item callLine)217 Item memberFunctions(Item className, Item constFunction, Item objectArgument, Item objectMember, Item callLine)
218 {
219 return
220 Line("template <typename T, typename Class" + typenameTypes + ">") +
221 Line("class " + className + Counter() + " : public RunFunctionTask<T>") +
222 Line("{") +
223 Line("public:")+
224 Line(" " + className + Counter() + "(T (Class::*fn)(" + parameterTypesNoPrefix + ") " + constFunction + ", " + objectArgument + functionParameters + ")") +
225 Line(" : fn(fn), object(object)" + initializers + "{ }" ) +
226 Line("")+
227 Line(" void runFunctor()")+
228 Line(" {")+
229 Line(" " + callLine + argumentsNoPrefix + ");")+
230 Line(" }")+
231 Line("private:")+
232 Line(" T (Class::*fn)(" + parameterTypesNoPrefix + ")" + constFunction + ";")+
233 Line(" " + objectMember + ";") +
234 Line( classData) +
235 Line("};");
236 }
237
memberFunctionSelector(Item classNameBase)238 Item memberFunctionSelector(Item classNameBase)
239 {
240 return
241 Line("template <typename T, typename Class" + typenameTypes + ">") +
242 Line("struct Select" + classNameBase + Counter()) +
243 Line("{") +
244 Line(" typedef typename SelectSpecialization<T>::template") +
245 Line(" Type<" + classNameBase + Counter() + " <T, Class" + types + ">,") +
246 Line(" Void" + classNameBase + Counter() + "<T, Class" + types + "> >::type type;") +
247 Line("};");
248 }
249
generateSFCs(int repeats)250 Item generateSFCs(int repeats)
251 {
252
253 Item functionPointerTypedef = "typedef void (*FunctionPointer)(" + argumentTypesNoPrefix + ");";
254
255 Repeater dataStructures =
256
257 // Function objects by value
258 functions(Item("StoredFunctorCall"), Item("FunctionPointer"), Item(" this->result = function(")) +
259 functions(Item("VoidStoredFunctorCall"), Item("FunctionPointer"), Item(" function(")) +
260 functionSelector(Item("StoredFunctorCall")) +
261
262 // Function objects by pointer
263 functions(Item("StoredFunctorPointerCall"), Item("FunctionPointer *"), Item(" this->result =(*function)(")) +
264 functions(Item("VoidStoredFunctorPointerCall"), Item("FunctionPointer *"), Item("(*function)(")) +
265 functionSelector(Item("StoredFunctorPointerCall")) +
266
267 // Member functions by value
268 memberFunctions(Item("StoredMemberFunctionCall"), Item(""), Item("const Class &object"), Item("Class object"), Item("this->result = (object.*fn)(")) +
269 memberFunctions(Item("VoidStoredMemberFunctionCall"), Item(""), Item("const Class &object"), Item("Class object"), Item("(object.*fn)(")) +
270 memberFunctionSelector(Item("StoredMemberFunctionCall")) +
271
272 // Const Member functions by value
273 memberFunctions(Item("StoredConstMemberFunctionCall"), Item("const"), Item("const Class &object"), Item("const Class object"), Item("this->result = (object.*fn)(")) +
274 memberFunctions(Item("VoidStoredConstMemberFunctionCall"), Item("const"), Item("const Class &object"), Item("const Class object"), Item("(object.*fn)(")) +
275 memberFunctionSelector(Item("StoredConstMemberFunctionCall")) +
276
277 // Member functions by pointer
278 memberFunctions(Item("StoredMemberFunctionPointerCall"), Item(""), Item("Class *object"), Item("Class *object"), Item("this->result = (object->*fn)(")) +
279 memberFunctions(Item("VoidStoredMemberFunctionPointerCall"), Item(""), Item("Class *object"), Item("Class *object"), Item("(object->*fn)(")) +
280 memberFunctionSelector(Item("StoredMemberFunctionPointerCall")) +
281
282 // const member functions by pointer
283 memberFunctions(Item("StoredConstMemberFunctionPointerCall"), Item("const"), Item("Class const *object"), Item("Class const *object"), Item("this->result = (object->*fn)(")) +
284 memberFunctions(Item("VoidStoredConstMemberFunctionPointerCall"), Item("const"), Item("Class const *object"), Item("Class const *object"), Item("(object->*fn)(")) +
285 memberFunctionSelector(Item("StoredConstMemberFunctionPointerCall"));
286
287 dataStructures.setRepeatCount(repeats);
288 return dataStructures;
289 }
290
writeFile(QString fileName,QByteArray contents)291 void writeFile(QString fileName, QByteArray contents)
292 {
293 QFile runFile(fileName);
294 if (runFile.open(QIODevice::WriteOnly) == false) {
295 qDebug() << "Write to" << fileName << "failed";
296 return;
297 }
298
299 runFile.write(contents);
300 runFile.close();
301 qDebug() << "Write to" << fileName << "Ok";
302 }
303
dollarQuote(Item item)304 Item dollarQuote(Item item)
305 {
306 return Item("$") + item + Item("$");
307 }
308
usage(const char * executable)309 static int usage(const char *executable)
310 {
311 qDebug("Usage: %s path/to/qtconcurrent", executable);
312 return EXIT_FAILURE;
313 }
314
main(int argc,char * argv[])315 int main(int argc, char *argv[])
316 {
317 if (argc !=2)
318 return usage(argv[0]);
319
320 const QDir outdir(QFile::decodeName(argv[1]));
321
322 const int repeats = 6;
323 init();
324 Item run = (
325 Line("/****************************************************************************") +
326 Line("**") +
327 Line("** Copyright (C) 2015 The Qt Company Ltd.") +
328 Line("** Contact: http://www.qt.io/licensing/") +
329 Line("**") +
330 Line("** This file is part of the Qt Toolkit.") +
331 Line("**") +
332 Line("****************************************************************************/") +
333 Line("") +
334 Line("// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/") +
335 Line("#ifndef QTCONCURRENT_RUN_H") +
336 Line("#define QTCONCURRENT_RUN_H") +
337 Line("") +
338 Line("#include <QtConcurrent/qtconcurrentcompilertest.h>") +
339 Line("") +
340 Line("#ifndef QT_NO_CONCURRENT") +
341 Line("") +
342 Line("#include <QtConcurrent/qtconcurrentrunbase.h>") +
343 Line("#include <QtConcurrent/qtconcurrentstoredfunctioncall.h>") +
344 Line("") +
345 Line("QT_BEGIN_NAMESPACE") +
346 Line("") +
347 Line("") +
348 Line("#ifdef Q_QDOC") +
349 Line("") +
350 Line("namespace QtConcurrent {") +
351 Line("") +
352 Line(" template <typename T>") +
353 Line(" QFuture<T> run(Function function, ...);") +
354 Line("") +
355 Line(" template <typename T>") +
356 Line(" QFuture<T> run(QThreadPool *pool, Function function, ...);") +
357 Line("") +
358 Line("} // namespace QtConcurrent") +
359 Line("") +
360 Line("#else") +
361 Line("") +
362 Line("namespace QtConcurrent {") +
363 Line("") +
364 generateRunFunctions(repeats, false) +
365 Line("") +
366 generateRunFunctions(repeats, true) +
367 Line("} //namespace QtConcurrent") +
368 Line("") +
369 Line("#endif // Q_QDOC") +
370 Line("") +
371 Line("QT_END_NAMESPACE") +
372 Line("") +
373 Line("#endif // QT_NO_CONCURRENT") +
374 Line("") +
375 Line("#endif")
376 );
377
378 writeFile(outdir.filePath("qtconcurrentrun.h"), run.generate());
379
380 Item storedFunctionCall = (
381 Line("/****************************************************************************") +
382 Line("**") +
383 Line("** Copyright (C) 2015 The Qt Company Ltd.") +
384 Line("** Contact: http://www.qt.io/licensing/") +
385 Line("**") +
386 Line("** This file is part of the Qt Toolkit.") +
387 Line("**") +
388 Line("****************************************************************************/") +
389 Line("") +
390 Line("// Generated code, do not edit! Use generator at tools/qtconcurrent/generaterun/") +
391 Line("#ifndef QTCONCURRENT_STOREDFUNCTIONCALL_H") +
392 Line("#define QTCONCURRENT_STOREDFUNCTIONCALL_H") +
393 Line("") +
394 Line("#include <QtCore/qglobal.h>") +
395 Line("") +
396 Line("#ifndef QT_NO_CONCURRENT") +
397 Line("#include <QtConcurrent/qtconcurrentrunbase.h>") +
398 Line("") +
399 Line("QT_BEGIN_NAMESPACE") +
400 Line("") +
401 Line("#ifndef Q_QDOC") +
402 Line("") +
403 Line("namespace QtConcurrent {") +
404 generateSFCs(repeats) +
405 Line("} //namespace QtConcurrent") +
406 Line("") +
407 Line("#endif // Q_QDOC") +
408 Line("") +
409 Line("QT_END_NAMESPACE") +
410 Line("") +
411 Line("#endif // QT_NO_CONCURRENT") +
412 Line("") +
413 Line("#endif")
414 );
415
416 writeFile(outdir.filePath("qtconcurrentstoredfunctioncall.h"), storedFunctionCall.generate());
417 }
418
419
420