別のクラスから呼び出される単純なデータ クラスがあります。
データクラス:
class Data
{
public:
QString getName() const
{
return this->mName;
}
void setName(AccessData* access, const QString& name)
{
this->mName = name;
access->emitNameChanged(this);
}
private:
QString mName;
QReadWriteLock mLock;
};
そして、ロックも処理する新しい名前を取得/設定するために使用しているクラスは次のとおりです。
class AccessData : public QObject
{
public:
QString getName(Data* data)
{
QReadLocker lock(&data->mLock);
return data->getName();
}
void setName(Data* data, const QString& name)
{
QWriteLocker lock(&data->mLock);
data->setName(this, name);
}
void emitNameChanged(Data* data)
{
emit this->nameChanged(data);
}
signals:
void nameChanged(AccessData* access, Data* data);
};
何が起こるか: AccessData クラスを使用して、Data インスタンスの名前を読み書きします。AccessData クラスは、読み取り/書き込みのロックを担当します。ただし、ご覧のとおり、Data クラスは setName() メソッドで AccessData インスタンスをコールバックして、変更に関するシグナルを適切に送信します。注: これは疑似コードにすぎません。実際にはもっと複雑なので、Data クラスは呼び出し元を介してシグナルを発信できる必要があります。
そして、ここに問題があります:
「d」という「Data」のインスタンスがあるとします。 Data* d; 「AccessData」インスタンス「a」を使用して名前を変更しています: a->setName(d, "new name"); 同時に、次のコードで nameChanged() シグナルに接続しています。
...
void nameChanged(AccessData* access, Data* data)
{
// Read the new name
QString newName = access->getName();
}
そして、ここに問題があります:
- a->setName(d, "新しい名前") の呼び出し
- "d" は "a" によってロックされるようになりました (書き込みロック)
- 「d」は、まだロックされているにもかかわらず、名前の変更に関する信号を発します
- nameChanged シグナルに接続されているメソッドが getName() にアクセスしようとしています
- これにより、別の QReadLock が発行され、デッドロックが発生します。
これを適切に処理するにはどうすればよいですか? 思いついたのは次の2つです。
信号を遅延させて(別名ノンブロッキング)発信して、ループに入れます。信号をすぐにプッシュしたいので、これは私が望むものではありません。
Data クラス内でロック/ロック解除のものを移動し、最初にロックを解除してから信号を送信します。これは私が望んでいるものではありません。なぜなら、Data クラスをロックから完全に解放したいからです。
何か案が?私は受胎不全ですか?
どうもありがとうアレックス