<div dir="ltr"><div><div>Just as I was going to ask a threading question on this list, someone else did :) Oh well here's another one:<br><br></div>I'm rendering a compressed volume, and I've noticed that a big chunk of the time-to-first-render for me is the initial reading of the volume. To keep the UI responsive while the reading takes place, I decided to give QtConcurrent::run + QFuture + QFutureWatcher a try as a mechanism to put the reading in a different thread.<br><br></div>Here's a shortened version of what I did:<br><div><br>    auto future = QtConcurrent::run([&]() -> vtkImageData * {<br>        auto reader = vtkSmartPointer<HDF5ImageReader>::New();<br>        reader->setFileName("big_compressed_volume.hdf5");<br>        reader->Update();<br><br>        auto output = reader->GetOutput();<br>        auto result = output->NewInstance();<br>        result->ShallowCopy(output);<br><br>        return result;<br>    });<br><br>    auto futureWatcher = new QFutureWatcher<vtkImageData *>(this);<br><br>    connect(futureWatcher, &QFutureWatcher<vtkImageData *>::finished, [=]() {<br>        auto imageData = futureWatcher->result();<br><br></div><div>        // ... Create the rendering part of the pipeline<br><br>        GetRenderWindow()->Render();<br>    });<br><br>    futureWatcher->setFuture(future);<br><br></div><div>This works great. Using QtConcurrent::run, I spin up a thread in which the reading takes place. When the resulting vtkImageData is ready, I return a shallow copy of it, which in turn causes the QFutureWatcher I set up to emit the finished signal, upon which I construct the remaining (rendering) part of the pipeline (which doesn't take much time compared to the reading, about ~1/6 of the time).<br></div><div><br>Now to my questions:<br><br>1. Is this safe? Since the reader is destroyed by the time the rest of the pipeline takes over (courtesy of using Qt signal delivery as a synchronization point), there's no risk of concurrent access to VTK objects here, right?<br><br></div><div>2. Can I always use this approach for segments of my pipeline up until the rendering parts (up to the mapper?), or are there non-rendering parts of VTK which simply cannot run in a separate thread?<br></div><div><br>3. Regarding the shallow copying, I first tried to return just<br><br>        return vtkSmartPointer<vtkImageData>(reader->GetOutput());<br><br></div><div>from the reader function. My thinking with this was that<br><br>   * I create a smart pointer, which should raise the ref count of the object to 2, since the reader itself is still alive at that point and also holds a reference,<br>   * a copy is then made of the smart pointer (for the return value of the function), raising the refcount to 3,<br></div><div>   * when the function finally returns, the vtkSmartPointer I created, as well as the vtkSmartPointer holding the reader goes out of scope and destructs, which means the ref count goes down to 1.<br><br></div><div>But that's not what happens, I had a look at the ref count of the image data I finally got in my slot (from futureWatcher->result()), and it was 2, not 1 like I expected.<br><br></div><div>I'm obviously misunderstanding something here, anyone care to enlighten me? Does the ref counting mechanism not work across thread boundaries?<br><br></div><div>Many thanks in advance,<br><br></div><div>Elvis</div></div>