Как я могу удалить QSharedPointer

Я написал обертку вокруг QTextEdit, чтобы использовать его как QIODevice. Я хочу иметь возможность использовать несколько оболочек с одним и тем же QTextEdit, поэтому я могу использовать разные цвета текста с каждой оболочкой.

Чтобы сделать эту оболочку потокобезопасной, я добавил QMutex для защиты использования QTextEdit. Но я думал, что должен использовать только один мьютекс для защиты одного QTextEdit.

В итоге я получил следующую реализацию, используя QSharedPointer для защиты QTextEdit.

texteditidevice.h

class TextEditIODevice : public QIODevice
{
    Q_OBJECT

public:
    TextEditIODevice(QTextEdit * qTextEdit, QColor color, QObject * parent);

    virtual ~TextEditIODevice();

protected:
    qint64 readData(char *data, qint64 maxlen);

    qint64 writeData(const char *data, qint64 len);

private:
    /**
     * @brief Pointer to QTextEdit
     */
    QPointer<QTextEdit> textEdit;

    /**
     * @brief Text color
     */
    QColor color;

    /**
     * @brief Shared pointer to QTextEdit associated mutex
     */
    QSharedPointer<QMutex> mutex;

    /**
     * @brief Storage for QTextEdit associated mutexes
     */
    static QMap<QPointer<QTextEdit>, QSharedPointer<QMutex>> mutexes;
};

texteditidevice.cpp

QMap<QPointer<QTextEdit>, QSharedPointer<QMutex>> TextEditIODevice::mutexes;

TextEditIODevice::TextEditIODevice(QTextEdit * qTextEdit, QColor color, QObject * parent) :
    QIODevice(parent),
    textEdit(qTextEdit),
    color(color)
{
    open(QIODevice::WriteOnly | QIODevice::Text);

    qRegisterMetaType<QTextCharFormat>("QTextCharFormat");
    qRegisterMetaType<QTextBlock>("QTextBlock");
    qRegisterMetaType<QTextCursor>("QTextCursor");

    if(mutexes.contains(textEdit))
        mutex = mutexes[textEdit];
    else
    {
        mutex = QSharedPointer<QMutex>(new QMutex());
        mutexes.insert(textEdit, mutex);
    }
}

TextEditIODevice::~TextEditIODevice()
{
}

qint64 TextEditIODevice::readData(char *data, qint64 maxlen)
{
    Q_UNUSED(data);
    Q_UNUSED(maxlen);
    return 0;
}



qint64 TextEditIODevice::writeData(const char *data, qint64 len)
{
    if(textEdit)
    {
        mutex->lock();
        const QColor lastColor = textEdit->textColor();
        textEdit->setTextColor(color);
        textEdit->append(QString(data));
        textEdit->setTextColor(lastColor);
        mutex->unlock();
    }

    return len;
}

Я хочу знать, где я могу удалить экземпляр QSharedPointer из сопоставления mutexes, чтобы QMutex был удален.

Спасибо за вашу помощь


person AMDG    schedule 04.07.2016    source источник
comment
Вы должны переосмыслить свою архитектуру, потому что вы не можете этого сделать. QWidget не допускает повторного входа и должен использоваться только из основного потока. Как только вы исправите это, вам больше не понадобятся мьютексы (только один поток), поэтому проблема будет решена!   -  person dydil    schedule 04.07.2016
comment
Запись данных вызывается в слоте, поэтому она вызывается из потока GUI. Но что, если два сигнала испускаются одновременно?   -  person AMDG    schedule 04.07.2016
comment
Если ваш объект находится в основном потоке, а сигнал испускается из другого потока, то сигнал ставится в очередь для последующей обработки циклом событий основного потока, поэтому не нужно возиться с мьютексом :). Однако это возможно только в том случае, если вы подключили свой сигнал, используя автоматическое (по умолчанию) или соединение в очереди. Вы можете посмотреть раздел «Сигналы и слоты в разных потоках» по ссылке, которую я дал выше, для получения дополнительной информации.   -  person dydil    schedule 04.07.2016


Ответы (1)


Пока общий указатель находится в статической карте mutexes, он никогда не будет освобожден, а время жизни mutexes равно времени жизни программы.

Если вы действительно хотите удалить мьютекс, вы должны удалить его из отображения mutexes.

person Some programmer dude    schedule 04.07.2016
comment
Или используйте QWeakPointer на карте mutexes. Но я думаю, что QWeakPointer в null все равно останется на карте, даже после удаления объекта вам придется очистить нулевые указатели. - person Anže; 04.07.2016
comment
Я понимаю вашу точку зрения. Я думаю, что не ясно выразился, мне нужен совет о том, когда я должен/могу удалить мьютекс из сопоставления мьютексов. - person AMDG; 04.07.2016