Merge branch 'threadfix'

celladd
Marc Zinnschlag 10 years ago
commit 55bd0c728e

@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp
opencs_units (. editor) opencs_units (. editor)
opencs_units (model/doc opencs_units (model/doc
document operation saving documentmanager loader runner document operation saving documentmanager loader runner operationholder
) )
opencs_units_noqt (model/doc opencs_units_noqt (model/doc

@ -2254,7 +2254,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
mTools (*this), mResDir(resDir), mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation),
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()) mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>())
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())

@ -20,6 +20,7 @@
#include "saving.hpp" #include "saving.hpp"
#include "blacklist.hpp" #include "blacklist.hpp"
#include "runner.hpp" #include "runner.hpp"
#include "operationholder.hpp"
class QAbstractItemModel; class QAbstractItemModel;
@ -59,7 +60,8 @@ namespace CSMDoc
CSMWorld::Data mData; CSMWorld::Data mData;
CSMTools::Tools mTools; CSMTools::Tools mTools;
boost::filesystem::path mProjectPath; boost::filesystem::path mProjectPath;
Saving mSaving; Saving mSavingOperation;
OperationHolder mSaving;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;

@ -29,9 +29,9 @@ void CSMDoc::Operation::prepareStages()
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()), : mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
mFinalAlways (finalAlways), mError(false) mFinalAlways (finalAlways), mError(false), mConnected (false)
{ {
connect (this, SIGNAL (finished()), this, SLOT (operationDone())); mTimer = new QTimer (this);
} }
CSMDoc::Operation::~Operation() CSMDoc::Operation::~Operation()
@ -42,15 +42,17 @@ CSMDoc::Operation::~Operation()
void CSMDoc::Operation::run() void CSMDoc::Operation::run()
{ {
mTimer->stop();
if (!mConnected)
{
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
mConnected = true;
}
prepareStages(); prepareStages();
QTimer timer; mTimer->start (0);
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
timer.start (0);
exec();
} }
void CSMDoc::Operation::appendStage (Stage *stage) void CSMDoc::Operation::appendStage (Stage *stage)
@ -65,7 +67,7 @@ bool CSMDoc::Operation::hasError() const
void CSMDoc::Operation::abort() void CSMDoc::Operation::abort()
{ {
if (!isRunning()) if (!mTimer->isActive())
return; return;
mError = true; mError = true;
@ -116,10 +118,11 @@ void CSMDoc::Operation::executeStage()
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
if (mCurrentStage==mStages.end()) if (mCurrentStage==mStages.end())
exit(); operationDone();
} }
void CSMDoc::Operation::operationDone() void CSMDoc::Operation::operationDone()
{ {
mTimer->stop();
emit done (mType, mError); emit done (mType, mError);
} }

@ -3,7 +3,8 @@
#include <vector> #include <vector>
#include <QThread> #include <QObject>
#include <QTimer>
namespace CSMWorld namespace CSMWorld
{ {
@ -14,7 +15,7 @@ namespace CSMDoc
{ {
class Stage; class Stage;
class Operation : public QThread class Operation : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +28,8 @@ namespace CSMDoc
int mOrdered; int mOrdered;
bool mFinalAlways; bool mFinalAlways;
bool mError; bool mError;
bool mConnected;
QTimer *mTimer;
void prepareStages(); void prepareStages();
@ -38,8 +41,6 @@ namespace CSMDoc
virtual ~Operation(); virtual ~Operation();
virtual void run();
void appendStage (Stage *stage); void appendStage (Stage *stage);
///< The ownership of \a stage is transferred to *this. ///< The ownership of \a stage is transferred to *this.
/// ///
@ -60,6 +61,8 @@ namespace CSMDoc
void abort(); void abort();
void run();
private slots: private slots:
void executeStage(); void executeStage();

@ -0,0 +1,65 @@
#include "operationholder.hpp"
#include "operation.hpp"
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
{
if (operation)
setOperation (operation);
}
void CSMDoc::OperationHolder::setOperation (Operation *operation)
{
mOperation = operation;
mOperation->moveToThread (&mThread);
connect (
mOperation, SIGNAL (progress (int, int, int)),
this, SIGNAL (progress (int, int, int)));
connect (
mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
connect (
mOperation, SIGNAL (done (int, bool)),
this, SLOT (doneSlot (int, bool)));
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
}
bool CSMDoc::OperationHolder::isRunning() const
{
return mRunning;
}
void CSMDoc::OperationHolder::start()
{
mRunning = true;
mThread.start();
}
void CSMDoc::OperationHolder::abort()
{
mRunning = false;
emit abortSignal();
}
void CSMDoc::OperationHolder::abortAndWait()
{
if (mRunning)
{
mThread.quit();
mThread.wait();
}
}
void CSMDoc::OperationHolder::doneSlot (int type, bool failed)
{
mRunning = false;
mThread.quit();
emit done (type, failed);
}

@ -0,0 +1,56 @@
#ifndef CSM_DOC_OPERATIONHOLDER_H
#define CSM_DOC_OPERATIONHOLDER_H
#include <QObject>
#include <QThread>
namespace CSMWorld
{
class UniversalId;
}
namespace CSMDoc
{
class Operation;
class OperationHolder : public QObject
{
Q_OBJECT
QThread mThread;
Operation *mOperation;
bool mRunning;
public:
OperationHolder (Operation *operation = 0);
void setOperation (Operation *operation);
bool isRunning() const;
void start();
void abort();
// Abort and wait until thread has finished.
void abortAndWait();
private slots:
void doneSlot (int type, bool failed);
signals:
void progress (int current, int max, int type);
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
const std::string& hint, int type);
void done (int type, bool failed);
void abortSignal();
};
}
#endif

@ -6,7 +6,7 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
#include "operation.hpp" #include "operationholder.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath) CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath) : mRunning (false), mStartup (0), mProjectPath (projectPath)
@ -145,7 +145,7 @@ void CSMDoc::Runner::readyReadStandardOutput()
} }
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation) CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, OperationHolder *operation)
: QObject (runner), mRunner (runner) : QObject (runner), mRunner (runner)
{ {
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool))); connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));

@ -16,6 +16,8 @@ class QTemporaryFile;
namespace CSMDoc namespace CSMDoc
{ {
class OperationHolder;
class Runner : public QObject class Runner : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -74,7 +76,7 @@ namespace CSMDoc
public: public:
/// *this attaches itself to runner /// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation); SaveWatcher (Runner *runner, OperationHolder *operation);
private slots: private slots:

@ -26,30 +26,30 @@
#include "referencecheck.hpp" #include "referencecheck.hpp"
#include "startscriptcheck.hpp" #include "startscriptcheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type) CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{ {
switch (type) switch (type)
{ {
case CSMDoc::State_Verifying: return mVerifier; case CSMDoc::State_Verifying: return &mVerifier;
} }
return 0; return 0;
} }
const CSMDoc::Operation *CSMTools::Tools::get (int type) const const CSMDoc::OperationHolder *CSMTools::Tools::get (int type) const
{ {
return const_cast<Tools *> (this)->get (type); return const_cast<Tools *> (this)->get (type);
} }
CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
{ {
if (!mVerifier) if (!mVerifierOperation)
{ {
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false); mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier, connect (&mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
@ -60,46 +60,48 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mandatoryIds.push_back ("Month"); mandatoryIds.push_back ("Month");
mandatoryIds.push_back ("PCRace"); mandatoryIds.push_back ("PCRace");
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); mVerifierOperation->appendStage (new SkillCheckStage (mData.getSkills()));
mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); mVerifierOperation->appendStage (new ClassCheckStage (mData.getClasses()));
mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); mVerifierOperation->appendStage (new FactionCheckStage (mData.getFactions()));
mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); mVerifierOperation->appendStage (new RaceCheckStage (mData.getRaces()));
mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); mVerifierOperation->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); mVerifierOperation->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); mVerifierOperation->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); mVerifierOperation->appendStage (new SpellCheckStage (mData.getSpells()));
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions())); mVerifierOperation->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mDocument)); mVerifierOperation->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage (new StartScriptCheckStage (mData.getStartScripts(), mData.getScripts())); mVerifierOperation->appendStage (new StartScriptCheckStage (mData.getStartScripts(), mData.getScripts()));
mVerifier->appendStage( mVerifierOperation->appendStage(
new BodyPartCheckStage( new BodyPartCheckStage(
mData.getBodyParts(), mData.getBodyParts(),
mData.getResources( mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() )); mData.getRaces() ));
mVerifier.setOperation (mVerifierOperation);
} }
return mVerifier; return &mVerifier;
} }
CSMTools::Tools::Tools (CSMDoc::Document& document) CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) : mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0)
{ {
// index 0: load error log // index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
@ -108,7 +110,11 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
CSMTools::Tools::~Tools() CSMTools::Tools::~Tools()
{ {
delete mVerifier; if (mVerifierOperation)
{
mVerifier.abortAndWait();
delete mVerifierOperation;
}
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
delete iter->second; delete iter->second;
@ -126,7 +132,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::abortOperation (int type)
{ {
if (CSMDoc::Operation *operation = get (type)) if (CSMDoc::OperationHolder *operation = get (type))
operation->abort(); operation->abort();
} }
@ -141,7 +147,7 @@ int CSMTools::Tools::getRunningOperations() const
int result = 0; int result = 0;
for (int i=0; sOperations[i]!=-1; ++i) for (int i=0; sOperations[i]!=-1; ++i)
if (const CSMDoc::Operation *operation = get (sOperations[i])) if (const CSMDoc::OperationHolder *operation = get (sOperations[i]))
if (operation->isRunning()) if (operation->isRunning())
result |= sOperations[i]; result |= sOperations[i];

@ -5,6 +5,8 @@
#include <map> #include <map>
#include "../doc/operationholder.hpp"
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
@ -27,7 +29,8 @@ namespace CSMTools
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier; CSMDoc::Operation *mVerifierOperation;
CSMDoc::OperationHolder mVerifier;
std::map<int, ReportModel *> mReports; std::map<int, ReportModel *> mReports;
int mNextReportNumber; int mNextReportNumber;
std::map<int, int> mActiveReports; // type, report number std::map<int, int> mActiveReports; // type, report number
@ -36,12 +39,12 @@ namespace CSMTools
Tools (const Tools&); Tools (const Tools&);
Tools& operator= (const Tools&); Tools& operator= (const Tools&);
CSMDoc::Operation *getVerifier(); CSMDoc::OperationHolder *getVerifier();
CSMDoc::Operation *get (int type); CSMDoc::OperationHolder *get (int type);
///< Returns a 0-pointer, if operation hasn't been used yet. ///< Returns a 0-pointer, if operation hasn't been used yet.
const CSMDoc::Operation *get (int type) const; const CSMDoc::OperationHolder *get (int type) const;
///< Returns a 0-pointer, if operation hasn't been used yet. ///< Returns a 0-pointer, if operation hasn't been used yet.
public: public:

Loading…
Cancel
Save