Потоки QThread, передача данных,

264
05 мая 2018, 16:35

у меня много вопросов по поводу QThread и потоков. У меня есть класс ClassData, который в конструкторе принимает два массива данных, затем передает эти данные классу ClassDataWorker, который в отдельном потоке обрабатывает данные и возвращает их обратно. При этом во время работы ClassDataWorker к ClassData могут обращаться другие обьекты с помощью getData(). В общем хочу сделать подгрузку данных в потоке чтобы не фризить интрефейс.

class ClassData: public QObject
{
    Q_OBJECT
public:
    explicit ClassData(QSharedPointer<QVarLengthArray<uint8_t> > data,
                               QSharedPointer<QVarLengthArray<uint64_t> > dataF,
                               uint8_t unitsize, QObject *parent=0);
    ~ClassData();
    void getData(std::vector<std::pair<uint64_t,uint8_t>> *data,...);
    ClassDataWorker* worker;
private:
    struct MipMapLevel
    {
        QSharedPointer<QVarLengthArray<uint8_t> > _data;
        QSharedPointer<QVarLengthArray<uint64_t> > _dataF;
    };
    QSharedPointer<QVarLengthArray<uint8_t> > _data;
    QSharedPointer<QVarLengthArray<uint64_t> > _dataF;
    QSharedPointer<QVarLengthArray<uint8_t>> _curData;
    QSharedPointer<QVarLengthArray<uint64_t> > _curDataF;
    QThread thread_a;
    struct MipMapLevel mip_map_[10];
public slots:
    void recvData(QSharedPointer<QVector<ClassDataWorker::MipMapLevel>>  data);
    void lastDataAppend();
};

ClassData::ClassData(QSharedPointer<QVarLengthArray<uint8_t> > data, QSharedPointer<QVarLengthArray<uint64_t> > dataF, QObject 
*parent)
    : QObject(parent),
      _data(data),
      _dataF(dataF)
{
    memset(mip_map_, 0, sizeof(mip_map_));
    mip_map_[0]._data = _data;
    mip_map_[0]._dataF = dataF;
    _curData = mip_map_[0]._data;
    _curDataF = mip_map_[0]._dataF;
    for(uint8_t i=1;i<ScaleStepCount;++i){
        mip_map_[i]._data = QSharedPointer<QVarLengthArray<uint8_t>>(new QVarLengthArray<uint8_t> );
        mip_map_[i]._dataF = QSharedPointer<QVarLengthArray<uint64_t> >(new QVarLengthArray<uint64_t> );
    }
    qRegisterMetaType< QSharedPointer<QVector<ClassDataWorker::MipMapLevel>> 
>("QSharedPointer<QVector<ClassDataWorker::MipMapLevel>>");

    worker = new ClassDataWorker(_data,_dataF,_unitsize);
    connect(worker, &ClassDataWorker::newData,
            this, &ClassData::recvData,Qt::QueuedConnection);
    connect(worker, &ClassDataWorker::dataEnded,
            this, &ClassData::lastDataAppend,Qt::QueuedConnection);
    connect(&thread_a, &QThread::started, worker, &ClassDataWorker::run);
    worker->moveToThread(&thread_a);
    thread_a.start();
}
void ClassData::lastDataAppend(){
    thread_a.quit();
//    thread_a.wait();
    delete worker;
}
void ClassData::recvData(QSharedPointer<QVector<ClassDataWorker::MipMapLevel> > data){
    for(uint8_t level = 1; level < 10;++level){
        auto data_ = (data->begin()+level)->_data;
        auto dataF_ = (data->begin()+level)->_dataF;
//        mip_map_[level]._data->reserve(mip_map_[level]._data->size() + data_.size());
//        mip_map_[level]._dataF->reserve(mip_map_[level]._dataF->size() + dataF_.size());
        for(int i=0;i<dataF_.size();++i){
            mip_map_[level].dataF_->append(*(dataF_.begin()+i));
        }
        for(int i=0;i<data_.size();++i){
            mip_map_[level]._data->append(*(data_.begin()+i));
        }
    }
}
void ClassData::getData(std::vector<std::pair<uint64_t,uint8_t> > *dataP, ...){
    _curData = mip_map_[level]._data;
    _curDataF = mip_map_[level]._dataF;
    int ind = 0;
    while(_curData.size()){
        dataP->append({_curData[ind],_curDataF[ind]});
        ++ind;
    }
}

ClassDataWorker:

class ClassDataWorker: public QObject{
    Q_OBJECT
public:
    explicit ClassDataWorker(QSharedPointer<QVarLengthArray<uint8_t> > data,
                               QSharedPointer<QVarLengthArray<uint64_t> > dataF,
                               QObject *parent=0);
    ~ClassDataWorker();
    struct MipMapLevel
    {
        QVarLengthArray<uint8_t> _data;
        QVarLengthArray<uint64_t> _dataF;
    };
signals:
    void newData(QSharedPointer<QVector<ClassDataWorker::MipMapLevel>>  data);
    void dataEnded();
public slots:
    void run();
};
void ClassDataWorker::run(){
    QSharedPointer<QVector<MipMapLevel>> mip_map_ = QSharedPointer<QVector<MipMapLevel>>(new QVector<MipMapLevel>);
    mip_map_->fill(MipMapLevel(),10);
    _curData = &(_data);
    _curDataF = &(_dataF);
    //чтение _data и _dataF, запись в mip_map_
    emit newData(mip_map_);
    if(/*все данные обработаны*/)
        emit dataEnded();
    // чтбы обработать все данные и eventLoop работал правильно
    QMetaObject::invokeMethod(this, "run", Qt::QueuedConnection);
}

Правильно ли я использую потоки? Будут ли утечки?

В функции ClassData::recvData() если использовать reserve() при уcловии что приходят данные примерно одинаковой длинны, время копирования увеличивается после каждого вызова recvData почему так происходит?

При этом если не использовать reserve() копирование проходит быстро и за константное время но вызов getData() приводит к ошибке и закрытию программы, наверное надо разделять доступ к mip_map_? Как правильно это сделать?

Любые комментарии, вопросы и критику приветствую, спасибо тем кто дочитал.

READ ALSO
Linux segmentation fault не на всех пользователях

Linux segmentation fault не на всех пользователях

На VDS лежит самописная программка (на С++), при запуске исполняемого бинарника из под root - работает корректноСтоит зайти за другого пользователя...

212
Реализация БПФ на с++ из Mathcad

Реализация БПФ на с++ из Mathcad

Пытаюсь реализовать БПФ из Mathcad в проекте на Qt c++ Неполучается интерпретировать данную формулу

286
Помещение структур в QVector

Помещение структур в QVector

Как происходит помещение структур в вектор? Допустим я задал некую структуру

223
React удалить элемент li из списка ul

React удалить элемент li из списка ul

У меня есть компонент для реакта, который описывает элемент <li> спискаЛогика работы компонента такая: он рендерит текст и <span> с крестиком...

201