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