Hmm,
ich fange am besten von vorne an
Meine Absicht ist es die Einstellungen die ein User an einer oder mehrerer QTableWidget vornimmt persistent zu machen. D.h. wenn der User Rows oder Columns ändert, oder Farben und Schrift ändert, will ich das in einer XML-Datei persistent machen, damit der Zustand einer Tabelle jederzeit reproduzierbar ist. Die Tücke des Objects ist dabei aber, dass der User mehrere Zellen markiert haben könnte - oder manche Aktionen eben mehrere Zellen betreffen. In diesem Fall wird die Angelegenheit faktisch im Hintergrund via Threads bearbeitet, damit der User auf seiner Tabelle weiterarbeiten kann - ohne vom dem Speicherprozess etwas zu merken, was durchaus Zeitintensiv sein könnte.
Genau dann wenn mehrere Zellen hintereinander gespeichert werden laufe ich in eine race condition hinein, weil mein Proggie bislang nicht threadsafe beproggt wurde - das soll es noch werden

.
Momentan baue ich meine Klassen threadsafe um. Damit die Threads wirklich auf wohl definierten Zuständen laufen, verwende ich nun doch QThreadStorage (TLS) und sichere soweit es geht mit Mutex.
So habe ich nun bei der Klasse begonnen, die am Ende der Kette liegt: Die eben das XML-File versorgt. Sie ist kein Thread, aber wird hauptsächlich von Threads gefahren:
Code: Alles auswählen
#include "xmldom.h"
#include <QApplication>
#include <QString>
#include <QMutex>
#include <QStringList>
#include <QTextStream>
#include <QColor>
#include <QFile>
#include <QDomElement>
void XmlDom::saveDOM(){
mx.lock();
QFile fil(ActXmlFile);
if(!fil.open(QIODevice::WriteOnly)) {
mx.unlock();
return;
}
QTextStream out(&fil);
save(out, 1);
fil.close();
mx.unlock();
};
bool XmlDom::DelTable(QString sTabName){
QDomElement t = findElement(sTabName,"", "", 0);
mx.lock();
if(!t.isNull()){
mainE.removeChild(t);
mx.unlock();
return true;
}
mx.unlock();
return false;
};
bool XmlDom::DelRow(QString sTabName, int nRow){
QDomElement t= findElement(sTabName, "", "", 0);
if(!t.isNull()){
QDomElement r = findElement(sTabName,GetRowName(nRow), "", 1);
mx.lock();
if(!r.isNull()){
t.removeChild(r);
mx.unlock();
return true;
}
mx.unlock();
}
return false;
};
bool XmlDom::DelCol(QString sTabName, int nRow, int nCol){
QDomElement r = findElement(sTabName, GetRowName(nRow), "", 1);
if(!r.isNull()){
QDomElement c = findElement(sTabName, GetRowName(nRow), GetColName(nCol), 2);
mx.lock();
if(!c.isNull()){
r.removeChild(c);
mx.unlock();
return true;
}
mx.unlock();
}
return false;
};
bool XmlDom::RenameTable(QString sOldName, QString sNewName){
QDomElement t = findElement(sOldName, "", "", 0);
mx.lock();
if(!t.isNull()){
t.setTagName(sNewName);
mx.unlock();
return true;
}
mx.unlock();
return false;
};
bool XmlDom::isTableExist(QString sTab){
mx.lock();
bool b = false;
QDomElement t = mainE.firstChildElement(sTab);
if(!t.isNull())b = true;
mx.unlock();
return b;
};
bool XmlDom::isRowExist(QString sTab, int nRow){
mx.lock();
bool b = false;
QString tn = GetRowName(nRow);
QDomElement t = mainE.firstChildElement(sTab);
if(!t.isNull()){
QDomElement r = t.firstChildElement(tn);
if(!r.isNull()) b = true;
}
mx.unlock();
return b;
};
bool XmlDom::isColExist(QString sTab, int nRow, int nCol){
mx.lock();
bool b = false;
QString tn = GetRowName(nRow);
QString cn = GetColName(nCol);
QDomElement t = mainE.firstChildElement(sTab);
if(!t.isNull()){
QDomElement r = t.firstChildElement(tn);
if(!r.isNull()){
QDomElement c = r.firstChildElement(cn);
if(!c.isNull()) b = true;
}
}
mx.unlock();
return b;
};
void XmlDom::insertIntoCache(QString id, QString s){
if(!cache.hasLocalData()) cache.setLocalData(new QMap<QString, QString>);
cache.localData()->insert(id, s);
};
void XmlDom::removeFromCache(QString id){
if(cache.hasLocalData()) cache.localData()->remove(id);
};
QString XmlDom::readFromCache(QString id){
if(cache.hasLocalData())
return cache.localData()->value(id);
else
return "";
};
void XmlDom::setRowID(int nRowID){
mx.lock();
QString t;
t.setNum(nRowID);
insertIntoCache("RowID", t);
mx.unlock();
};
void XmlDom::setRowPos(int nPos){
mx.lock();
QString t;
t.setNum(nPos);
insertIntoCache("RowPos",t);
mx.unlock();
};
void XmlDom::setRowHeight(int nHeight){
mx.lock();
QString t;
t.setNum(nHeight);
insertIntoCache("RowHeight", t);
mx.unlock();
};
void XmlDom::setAlign(int nAlign){
mx.lock();
QString t;
t.setNum(nAlign);
insertIntoCache("Align", t);
mx.unlock();
};
void XmlDom::setWidth(int n){
mx.lock();
QString t;
t.setNum(n);
insertIntoCache("Width",t);
mx.unlock();
};
void XmlDom::setSize(int n){
mx.lock();
QString t;
t.setNum(n);
insertIntoCache("Size", t);
mx.unlock();
};
void XmlDom::setFont(QString s){
mx.lock();
insertIntoCache("Size", s);
mx.unlock();
};
void XmlDom::setBold(bool b){
mx.lock();
QString t;
t.setNum((int)b);
insertIntoCache("Bold", t);
mx.unlock();
};
void XmlDom::setItalic(bool b){
mx.lock();
QString t;
t.setNum((int)b);
insertIntoCache("Italic", t);
mx.unlock();
};
void XmlDom::setUnderline(bool b){
mx.lock();
QString t;
t.setNum((int)b);
insertIntoCache("Underl", t);
mx.unlock();
};
void XmlDom::setStrikeout(bool b){
mx.lock();
QString t;
t.setNum((int)b);
insertIntoCache("Strike", t);
mx.unlock();
};
void XmlDom::setBackcolor(QColor c){
mx.lock();
QString r;
QString g;
QString b;
r.setNum(c.red()) + ",";
g.setNum(c.green()) +",";
b.setNum(c.blue());
insertIntoCache("Backcolor",r+g+b);
mx.unlock();
};
void XmlDom::setForecolor(QColor c){
mx.lock();
QString r;
QString g;
QString b;
r.setNum(c.red()) + ",";
g.setNum(c.green()) +",";
b.setNum(c.blue());
insertIntoCache("Forecolor",r+g+b);
mx.unlock();
};
void XmlDom::setFramecolor(QColor c){
mx.lock();
QString r;
QString g;
QString b;
r.setNum(c.red()) + ",";
g.setNum(c.green()) +",";
b.setNum(c.blue());
insertIntoCache("Framecolor",r+g+b);
mx.unlock();
};
void XmlDom::setColID(int n){
mx.lock();
QString t;
t.setNum(n);
insertIntoCache("ID", t);
mx.unlock();
};
void XmlDom::AddColAttribute(QDomElement c){
c.setAttribute("ID", readFromCache("ID"));
c.setAttribute("Align", readFromCache("Align"));
c.setAttribute("Font", readFromCache("Font"));
c.setAttribute("Size", readFromCache("Size"));
c.setAttribute("Bold", readFromCache("Bold"));
c.setAttribute("Italic", readFromCache("Italic"));
c.setAttribute("Underl", readFromCache("Underl"));
c.setAttribute("Strike", readFromCache("Strike"));
c.setAttribute("Backcolor", readFromCache("Backcolor"));
c.setAttribute("Forecolor", readFromCache("Forecolor"));
c.setAttribute("Framecolor", readFromCache("Framcecolor"));
c.setAttribute("Width", readFromCache("Width"));
};
void XmlDom::AddRowAttribute(QDomElement r){
r.setAttribute("Height", readFromCache("RowHeight"));
r.setAttribute("ID", readFromCache("RowID"));
r.setAttribute("Pos", readFromCache("RowPos"));
};
bool XmlDom::AddTable(QString sTabName){
if(findElement(sTabName, "", "", 0).isNull()){
mx.lock();
QDomElement e = createElement(sTabName);
mainE.appendChild(e);
mx.unlock();
return true;
}
return false;
};
bool XmlDom::AddRow(QString sTabName, int nRowID){
QDomElement t = findElement(sTabName, "","", 0);
mx.lock();
QString rn = GetRowName(nRowID);
if(t.isNull()){
t = createElement(sTabName);
AddRowAttribute(t);
mainE.appendChild(t);
}
mx.unlock();
QDomElement r = findElement(sTabName, rn, "", 1);
mx.lock();
if(r.isNull()){
r = createElement(rn);
t.appendChild(r);
mx.unlock();
return true;
}
mx.unlock();
return false;
};
bool XmlDom::AddCol(QString sTabName, int nRowID, int nColID){
QDomElement t = findElement(sTabName, "", "", 0);
mx.lock();
QString rn = GetRowName(nRowID);
QString cn = GetColName(nColID);
if(t.isNull()){
t = createElement(sTabName);
mainE.appendChild(t);
}
mx.unlock();
QDomElement r = findElement(sTabName, rn, "", 1);
mx.lock();
if(r.isNull()){
r = createElement(rn);
AddRowAttribute(r);
t.appendChild(r);
}
mx.unlock();
QDomElement c = findElement(sTabName, rn, cn, 2);
mx.lock();
if(c.isNull()){
c = createElement(cn);
AddColAttribute(c);
r.appendChild(c);
mx.unlock();
return true;
}
mx.unlock();
return false;
};
QString XmlDom::GetRowName(int nRowID){
QString t;
t.setNum(nRowID);
return "Row" + t;
};
QString XmlDom::GetColName(int nColID){
QString t;
t.setNum(nColID);
return "Col" + t;
};
//Range: 0 -> Table
//Range: 1 -> Row
//Range: 2 -> Column
QDomElement XmlDom::findElement(QString sTab, QString sRow, QString sColumn, int Range){
mx.lock();
QDomElement res;
if(Range == 0){
mx.unlock();
return mainE.firstChildElement(sTab);
}
if(Range == 1){
QDomElement t = mainE.firstChildElement(sTab);
if(t.isNull()){
mx.unlock();
return res;
}
mx.unlock();
return t.firstChildElement(sRow);
}
if(Range == 2){
QDomElement t = mainE.firstChildElement(sTab);
if(t.isNull()){
mx.unlock();
return res;
}
QDomElement r = t.firstChildElement(sRow);
if(r.isNull()){
mx.unlock();
return res;
}
mx.unlock();
return r.firstChildElement(sColumn);
}
mx.unlock();
return res;
};
XmlDom::XmlDom(QApplication *papp, QString sActFile, QString sApplication){
mx.lock();
app = papp;
ActXmlFile = app->applicationDirPath();
QStringList ls = sActFile.split("/");
ActXmlFile += "/" + ls[ls.count()-1] + ".xml";
QFile fil(ActXmlFile);
if(!fil.exists()){
fil.open(QIODevice::WriteOnly);
QTextStream out(&fil);
out.setCodec("UTF-8");
out << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
<< "<!DOCTYPE TEdit32>\n"
<< "<TEdit32 version=\"1.0\" >\n</TEdit32>";
fil.close();
}
fil.open(QIODevice::ReadOnly);
setContent(&fil);
fil.close();
mainE = firstChildElement(sApplication);
mx.unlock();
};
Auf diese Weise taste ich mich nach vorne, und hoffe, dass am Ende kein Thread den Anderen anfrisst

[/code]
So mal meine Zwischenlösung.