Changeset 1056
- Timestamp:
- Oct 30, 2016, 12:52:03 AM (8 years ago)
- Location:
- XmlTools2/trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
XmlTools2/trunk/XmlTools.pro
r1055 r1056 7 7 #QT += qml #for use new google v8 qtscript engine 8 8 QT += script #for use old qtscript engine 9 QMAKE_CXXFLAGS+= -fopenmp10 QMAKE_LFLAGS += -fopenmp #OpenMP (multithreading) support11 9 12 10 # More optimization 13 11 QMAKE_CFLAGS_RELEASE += -O3 14 12 QMAKE_CXXFLAGS_RELEASE += -O3 15 16 17 13 18 14 -
XmlTools2/trunk/readme.txt
r1055 r1056 62 62 Change Log: 63 63 ---------------------------------- 64 2.0c, 28-10-201664 2.0c, 30-10-2016 65 65 -Fixed bug in --update-elements operation 66 66 -Added some exception handling 67 67 -Started migrating some of the source code to C++14 68 68 -Upgraded pugixml to latest 1.7 version 69 -Dropped openmp since apple clang doesn't support it, using Qt threads mechanisms now 69 70 ---------------------------------- 70 71 2.0b, 13-06-2014 -
XmlTools2/trunk/xmlcustomcode.cpp
r980 r1056 10 10 } 11 11 12 XmlCustomCode::XmlCustomCode(): numThreads( omp_get_num_procs()*2)12 XmlCustomCode::XmlCustomCode(): numThreads(QThread::idealThreadCount()) 13 13 { 14 myThreadPool.setMaxThreadCount(numThreads); 15 myThreadPool.setExpiryTimeout(-1); // don't let threads expire 16 14 17 // create individual thread script engines 15 this->scriptEngines.reserve(this->numThreads); 16 this->jsFunctions.reserve(this->numThreads); 17 this->getXmlDataFunctions.reserve(this->numThreads); 18 this->setXmlDataFunctions.reserve(this->numThreads); 18 this->jsScriptEngines.reserve(this->numThreads); 19 19 20 20 QString jsxmlString; … … 26 26 27 27 for(int i=0; i<this->numThreads; i++){ 28 this->scriptEngines.append(new QScriptEngine()); 29 this->jsFunctions.append(new QScriptValue()); 28 29 jsCustomCodeEngine e; 30 31 e.scriptEngine = new QScriptEngine(); 32 e.jsFunction = new QScriptValue(); 30 33 31 34 // main needs to be called so the user code is evaluated 32 35 // alternatively you can do: myFunc=engine.evaluate('(function main(){})'); myFunc.call(); 33 36 // Note the () around the function 34 this->getXmlDataFunctions.append(new QScriptValue(this->scriptEngines.at(i)->evaluate("(function getXmlData() { return $xmlData; })"))); 35 this->setXmlDataFunctions.append(new QScriptValue(this->scriptEngines.at(i)->evaluate("(function setXmlData(newXmlData) { $xmlData=newXmlData; })"))); 37 e.getXmlDataFunction = new QScriptValue(e.scriptEngine->evaluate("(function getXmlData() { return $xmlData; })")); 38 e.setXmlDataFunction = new QScriptValue(e.scriptEngine->evaluate("(function setXmlData(newXmlData) { $xmlData=newXmlData; })")); 39 e.isAvailable = true; 36 40 37 41 // Add echo function so user can debug the code 38 QScriptValue echoFunction = this->scriptEngines.at(i)->newFunction(echo);39 this->scriptEngines.at(i)->globalObject().setProperty("echo", echoFunction);42 QScriptValue echoFunction = e.scriptEngine->newFunction(echo); 43 e.scriptEngine->globalObject().setProperty("echo", echoFunction); 40 44 41 45 // Add the js library for XmlEditing 42 this->scriptEngines.at(i)->evaluate(jsxmlString); 46 e.scriptEngine->evaluate(jsxmlString); 47 48 this->jsScriptEngines.append(e); 43 49 } 44 50 } … … 57 63 // Reconstruct script functions 58 64 for(int i=0; i<this->numThreads; i++){ 59 * this->jsFunctions[i]=this->scriptEngines.at(i)->evaluate("(function main() {"+jsString+"})");65 *(jsScriptEngines[i].jsFunction) = jsScriptEngines.at(i).scriptEngine->evaluate("(function main() {"+jsString+"})"); 60 66 } 61 67 … … 66 72 clock_t begin; // seconds that a script started 67 73 68 // Single tread if small number of files 69 if(filesToProcess.size()<CUSTOM_FILES_PER_THREAD){ 74 // Single tread if small number of files or number of threads = 1 75 if(filesToProcess.size()<=CUSTOM_FILES_PER_THREAD || numThreads == 1){ 76 77 jsCustomCodeEngine &jsEngine = getAvailableJsEngine(); 78 70 79 // Process all XmlFiles 71 80 for(int i=0; i<filesToProcess.size(); i++){ 72 73 customCodeUnwinding(filesToProcess.at(i),currXmlFileString,*this->scriptEngines.at(0),begin,elapsed_secs,engineResult, 74 *this->jsFunctions.at(0),*this->getXmlDataFunctions.at(0),*this->setXmlDataFunctions.at(0),backupsEnabled,verboseEnabled); 81 customCodeUnwinding(filesToProcess.at(i),currXmlFileString,*jsEngine.scriptEngine,begin,elapsed_secs,engineResult, 82 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 75 83 } 76 84 } 77 85 else{ // Multithread if there are many files 78 86 // Process all XmlFiles 79 #pragma omp parallel for num_threads(this->numThreads) schedule(dynamic) 87 88 QVector<QFuture<void>> executingThreads; 89 80 90 for(int i=0; i<filesToProcess.size()-CUSTOM_FILES_PER_THREAD; i+=CUSTOM_FILES_PER_THREAD){ 81 91 82 const int tid=omp_get_thread_num(); 92 executingThreads << 93 QtConcurrent::run(&this->myThreadPool, [=]() 94 { 95 mutexIsAvailable.lock(); 96 jsCustomCodeEngine &jsEngine = getAvailableJsEngine(); 97 jsEngine.isAvailable = false; 98 mutexIsAvailable.unlock(); 83 99 84 QString currXmlFileStringThread;100 QString currXmlFileStringThread; 85 101 86 QScriptValue engineResultThread; // variable to check for js_errors87 double elapsedSecsThread=0; // elapsed seconds that a user script took88 clock_t beginThread; // seconds that a script started102 QScriptValue engineResultThread; // variable to check for js_errors 103 double elapsedSecsThread=0; // elapsed seconds that a user script took 104 clock_t beginThread; // seconds that a script started 89 105 90 customCodeUnwinding(filesToProcess.at(i),currXmlFileStringThread,*this->scriptEngines.at(tid),beginThread,elapsedSecsThread,engineResultThread,91 *this->jsFunctions.at(tid),*this->getXmlDataFunctions.at(tid),*this->setXmlDataFunctions.at(tid),backupsEnabled,verboseEnabled);106 customCodeUnwinding(filesToProcess.at(i),currXmlFileStringThread,*jsEngine.scriptEngine,beginThread,elapsedSecsThread,engineResultThread, 107 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 92 108 93 customCodeUnwinding(filesToProcess.at(i+1),currXmlFileStringThread,*this->scriptEngines.at(tid),beginThread,elapsedSecsThread,engineResultThread, 94 *this->jsFunctions.at(tid),*this->getXmlDataFunctions.at(tid),*this->setXmlDataFunctions.at(tid),backupsEnabled,verboseEnabled); 109 customCodeUnwinding(filesToProcess.at(i+1),currXmlFileStringThread,*jsEngine.scriptEngine,beginThread,elapsedSecsThread,engineResultThread, 110 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 111 112 customCodeUnwinding(filesToProcess.at(i+2),currXmlFileStringThread,*jsEngine.scriptEngine,beginThread,elapsedSecsThread,engineResultThread, 113 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 114 115 customCodeUnwinding(filesToProcess.at(i+3),currXmlFileStringThread,*jsEngine.scriptEngine,beginThread,elapsedSecsThread,engineResultThread, 116 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 117 118 mutexIsAvailable.lock(); 119 jsEngine.isAvailable = true; 120 mutexIsAvailable.unlock(); 121 }); 122 } 123 124 // Wait for all threads to finish 125 for(QFuture<void> &f :executingThreads){ 126 f.waitForFinished(); 95 127 } 96 128 … … 99 131 int alreadyProcessedFiles=(filesToProcess.size()/CUSTOM_FILES_PER_THREAD)*CUSTOM_FILES_PER_THREAD; 100 132 133 jsCustomCodeEngine &jsEngine = getAvailableJsEngine(); 134 101 135 for(int i=alreadyProcessedFiles; i<filesToProcess.size(); i++){ 102 136 103 customCodeUnwinding(filesToProcess.at(i),currXmlFileString,* this->scriptEngines.at(0),begin,elapsed_secs,engineResult,104 * this->jsFunctions.at(0),*this->getXmlDataFunctions.at(0),*this->setXmlDataFunctions.at(0),backupsEnabled,verboseEnabled);137 customCodeUnwinding(filesToProcess.at(i),currXmlFileString,*jsEngine.scriptEngine,begin,elapsed_secs,engineResult, 138 *jsEngine.jsFunction,*jsEngine.getXmlDataFunction,*jsEngine.setXmlDataFunction,backupsEnabled,verboseEnabled); 105 139 } 106 140 } … … 113 147 } 114 148 } 149 150 XmlCustomCode::jsCustomCodeEngine& XmlCustomCode::getAvailableJsEngine(){ 151 for(jsCustomCodeEngine &e : this->jsScriptEngines){ 152 if(e.isAvailable){ 153 return e; 154 } 155 } 156 157 throw std::runtime_error("Could't find an available js engine for custom command."); 158 } -
XmlTools2/trunk/xmlcustomcode.h
r980 r1056 10 10 #include <QCoreApplication> 11 11 12 #include <QThreadPool> 13 #include <QtConcurrent/QtConcurrent> 14 12 15 #define SLOW_SCRIPT_TIME 0.1 // if a user script takes more than 0.1 seconds to execute give a warning. 13 #define CUSTOM_FILES_PER_THREAD 216 #define CUSTOM_FILES_PER_THREAD 4 14 17 15 18 // Uses a singleton implementation (based on here: http://www.yolinux.com/TUTORIALS/C++Singleton.html) … … 22 25 private: 23 26 static XmlCustomCode* uniqueInstance; 27 24 28 const int numThreads; 25 QVector<QScriptEngine*> scriptEngines; 26 QVector<QScriptValue*> jsFunctions; 27 QVector<QScriptValue*> getXmlDataFunctions; 28 QVector<QScriptValue*> setXmlDataFunctions; 29 QThreadPool myThreadPool; 30 QMutex mutexIsAvailable; 31 32 struct jsCustomCodeEngine{ 33 QScriptEngine* scriptEngine; 34 QScriptValue* jsFunction; 35 QScriptValue* getXmlDataFunction; 36 QScriptValue* setXmlDataFunction; 37 bool isAvailable; 38 }; 39 40 QVector<jsCustomCodeEngine> jsScriptEngines; 29 41 30 42 XmlCustomCode(); // constructor is private (use getInstance) … … 33 45 34 46 void displayJsException(QScriptEngine &engine, QScriptValue &engineResult); 47 jsCustomCodeEngine& getAvailableJsEngine(); 35 48 36 49 __attribute__((always_inline)) inline void customCodeUnwinding(const QString &fileName, QString &currXmlFileString,
Note:
See TracChangeset
for help on using the changeset viewer.