QMAP :: Const_iterator НЕДВИЖИМОЕ СравнениеC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 QMAP :: Const_iterator НЕДВИЖИМОЕ Сравнение

Сообщение Anonymous »

У меня есть собственный класс шаблона TTThreadSafeMap, который является оболочкой для Qt QMap.

Код: Выделить всё

TTThreadSafeMap
имеет функцию члена, CBEGIN , которая возвращает новый экземпляр в класс члена TtthreadSafeMap :: const_iterator .

Код: Выделить всё

const_iterator
имеет переменную-член пользовательского блокировщика чтения/записи, TTReadWriteLocker, который он использует для реализации потокобезопасного итератора: идея состоит в том, что блокировка получается для чтения на время жизни итератора, полученного с помощью cbegin.

Код: Выделить всё

template 
class TRADETOOLS_EXPORT TTThreadSafeMap
{
protected:
mutable QReadWriteLock lock;
QMap data;

public:
class const_iterator
{
private:
TTReadWriteLocker locker;
const QMap *data;  // Pointer to the underlying data
typename QMap::const_iterator it;
friend TTThreadSafeMap;

public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = W;
using difference_type = std::ptrdiff_t;
using pointer = const W*;
using reference = const W&;

public:
const_iterator(QReadWriteLock *lock, const QMap &data, typename QMap::const_iterator start) : data(&data), it(start)
{
if(lock)
locker.reset(lock, LockType::READ);
}

// Equality operator
bool operator==(const const_iterator &other) const
{
return this->it == other.it;
}

// Inequality operator
bool operator!=(const const_iterator &other) const
{
return this->it != other.it;
}

// Increment operator (pre-increment)
const_iterator & operator++(void)
{
if(!this->data || this->it == this->data->cend()) // Crashes on this comparison
return *this;

// Unexecuted code here
}
};

// Begin iterator
const_iterator cbegin(const bool obtainLock = true) const
{
TTReadWriteLocker locker;

if(obtainLock)
locker.reset(&this->lock, LockType::READ);

return const_iterator(obtainLock ? &this->lock : Q_NULLPTR, this->data, this->data.cbegin());
}
};
Ниже приведена моя реализация ttreadwritelocker :

Код: Выделить всё

TTReadWriteLocker::TTReadWriteLocker(QReadWriteLock *lock, const LockType lockType, const qint64 timeoutMS) : lock(lock), timeoutMS(timeoutMS), lockType(lockType)
{
this->obtainLock();
}

TTReadWriteLocker::TTReadWriteLocker(TTReadWriteLocker &&other) noexcept
{
*this = std::move(other);
}

TTReadWriteLocker::~TTReadWriteLocker(void)
{
this->releaseLock();
}

QReadWriteLock * TTReadWriteLocker::getLock(void) const noexcept
{
return this->lock;
}

void TTReadWriteLocker::obtainLock(void)
{
if(!this->lock)
return;

if(this->lockType == LockType::READ)
{
if(!this->lock->tryLockForRead(this->timeoutMS))
throw TTException(ERROR_TEXT(LOCATION, "Lock failed (read): see which lock and debug the blocking location"));
}
else if(this->lockType == LockType::WRITE)
{
if(!this->lock->tryLockForWrite(this->timeoutMS))
throw TTException(ERROR_TEXT(LOCATION, "Lock failed (write): see which lock and debug the blocking location"));
}
else
throw TTException(ERROR_TEXT(LOCATION, "Invalid LockType: LockType::NOT_SET"));
}

void TTReadWriteLocker::releaseLock(void)
{
if(this->lock)
this->lock->unlock();
}

void TTReadWriteLocker::reset(QReadWriteLock *lock, const LockType lockType)
{
this->releaseLock();
this->lock = lock;
this->lockType = lockType;
this->obtainLock();
}

TTReadWriteLocker &  TTReadWriteLocker::operator=(TTReadWriteLocker &&other) noexcept
{
this->lock                          = std::move(other.lock);
this->timeoutMS                     = std::move(other.timeoutMS);
this->lockType                      = std::move(other.lockType);

other.lock                          = Q_NULLPTR;
other.lockType                      = LockType::NOT_SET;

return *this;
}
У меня есть класс Barinfo , который имеет член Bar MAP, определяемый как QsharedPointer , который назван ' '. Поток 1 обновления панели перед изданием сигнала, который поднимается слотом на потоке 2. Поток 2 пытается итераторный список с помощью:

Код: Выделить всё

for(TTThreadSafeMap::const_iterator itBar=bar->cbegin(),endBar=bar->cend(); itBar!=endBar; ++itBar)
{
// Do some stuff
}
< /code>
Цикл входит, делает кое -что, затем пытается увеличить итератор. При сравнении this-> it == this-> data-> cend () 
, в операторе ++ библиотека QT выбрасывает ошибку «Карта/установленные итераторы несовместимы».

Код: Выделить всё

TTThreadSafeMap::dataРасположение 
в памяти остается прежним от допуска сигнала, к вызову оператора ++ . Шкафчик работает и предотвращает обновления, поэтому такое же количество элементов находится в списке, список не перемещается в памяти, участники карты остаются неизменными и в одних и тех же адресах памяти. < /P>
Я в недоумении за то, почему возникает ошибка. Следующая функция, проверка функциональности, работает нормально: < /p>

Код: Выделить всё

void testThreadSafeMap(void)
{
QSharedPointer bars = QSharedPointer::create();
QSharedPointer bars2 = Q_NULLPTR;
TTThreadSafeMap::const_iterator itBar,endBar,tBar;
QSharedPointer bar1(new Bar), bar2(new Bar), bar3(new Bar);

bar1->timestamp = 1;
bar2->timestamp = 2;
bar3->timestamp = 3;

bars->insert(bar1->timestamp, bar1);
bars->insert(bar2->timestamp, bar2);
bars->insert(bar3->timestamp, bar3);
itBar=bars->cbegin();
endBar=bars->cend();

tBar = bars->cfind(2);
bars2 = bars->sharedCopy(true,false);

for(; itBar!=endBar; ++itBar)
{
qDebug() timestamp;
}
}
Полученное сообщение об ошибке «Map/Set Итераторы несовместимы», во время сравнения this-> it == this-> data-> cend () в операторе ++ < /code>.
Когда я создаю копию списка для итерации, сбой не происходит на итерации копии версии того же списка. < /p>
< /p>
Вы можете увидеть недостаток, который я не могу? Любое направление в движении вперед с этим? Заранее спасибо.

Подробнее здесь: https://stackoverflow.com/questions/793 ... comparison
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»