[vtkusers] Returning filter output from thread using shallow copying vs smart pointer
Elvis Stansvik
elvis.stansvik at orexplore.com
Tue Jul 5 17:11:23 EDT 2016
Just as I was going to ask a threading question on this list, someone else
did :) Oh well here's another one:
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.
Here's a shortened version of what I did:
auto future = QtConcurrent::run([&]() -> vtkImageData * {
auto reader = vtkSmartPointer<HDF5ImageReader>::New();
reader->setFileName("big_compressed_volume.hdf5");
reader->Update();
auto output = reader->GetOutput();
auto result = output->NewInstance();
result->ShallowCopy(output);
return result;
});
auto futureWatcher = new QFutureWatcher<vtkImageData *>(this);
connect(futureWatcher, &QFutureWatcher<vtkImageData *>::finished, [=]()
{
auto imageData = futureWatcher->result();
// ... Create the rendering part of the pipeline
GetRenderWindow()->Render();
});
futureWatcher->setFuture(future);
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).
Now to my questions:
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?
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?
3. Regarding the shallow copying, I first tried to return just
return vtkSmartPointer<vtkImageData>(reader->GetOutput());
from the reader function. My thinking with this was that
* 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,
* a copy is then made of the smart pointer (for the return value of the
function), raising the refcount to 3,
* 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.
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.
I'm obviously misunderstanding something here, anyone care to enlighten me?
Does the ref counting mechanism not work across thread boundaries?
Many thanks in advance,
Elvis
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160705/12430d7e/attachment.html>
More information about the vtkusers
mailing list