2013-12-11 3 views
0

Я пишу трассировщик путей и хотел бы сделать его распараллеленным по потокам. У меня вопрос проектирования многопоточных объектов в QT, особенно в классе QRunnable.QThreadPool & QRunnable & static functions

В моем (псевдокоде) ниже у меня есть класс PathTracer, который запускает экземпляры PTRunnable, который расширяет QRunnable.

Уместно ли передавать объекты QRunnable указателю на класс, который создает их, чтобы каждый QRunnable мог получить доступ к статическим методам, предоставляемым классом (doWork)? Мое рассуждение состоит в том, что если по какой-то причине я хочу отключить многопоточность, экземпляр PathTracer будет по-прежнему иметь необходимые методы без избыточности.

Или есть лучший дизайн? Что произойдет с переменной private экземпляра m_data? будут ли qrunnable объекты работать в общих файлах m_data или будет сделана копия данных указателя?

#include <QThreadPool> 
#include <vector> 

class PathTracer 
{ 
public: 
    static void doWork(PathTracer * pt, Pixel pix); 
protected: 
    void renderImage(); 
    void modifyData(); 
private: 
    int m_data; 
}; 

PathTracer::renderImage() 
{ 
    for (int x=0; x<width; x++) 
    { 
     for (int y=0; y<height; y++) 
     { 
      pixelblock.push_back(Pixel(x,y)); 
     } 
    } 
    // pass instance of self to each worker 
    PTRunnable ptworker(this, pixelblock); 
    QThreadPool::globalInstance()->start(ptworker); 
}; 

void modifyData() 
{ 
    m_data++; 
} 

static void PathTracer::doWork(PathTracer * pt, Point p) 
{ 
    pt->modifyData(); 
} 

////////////////////////////// 

class PTRunnable : public QRunnable 
{ 
    Q_OBJECT 
public: 
    explicit PTRunnable(QObject *parent = 0); 
    PTRunnable(PathTracer * pt, PixelList pixels); 
    void run(); // runnable implementation goes here 
signals: 

public slots: 

private: 
    PathTracer * m_pt; // owns pointer to pathtracer that spawned this 
protected: 

}; 


PTRunnable::PTRunnable(PathTracer * pt, PixelBlock block) 
{ 
    m_pt = pt; 
} 
void PTRunnable::run() 
{ 
    pt->doWork(this, block[0]); 
} 

ответ

0

Лучше подход должен был бы сделать эти статические методы слотами и испускать сигналы QRunnable случаев/посылают сигналы обратно в QRunnable объекты, если вы ожидаете какой-то возврат образуют функции.

Это будет потокобезопасным, и вам не нужно будет передавать/хранить какие-либо указатели, поскольку, передавая/сохраняя указатели, вы сталкиваетесь с потенциальным риском попыток доступа к удаленным объектам.

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

Смежные вопросы