<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 5, 2016 at 5:45 PM, Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">2016-07-05 23:30 GMT+02:00 Shawn Waldon <span dir="ltr"><<a href="mailto:shawn.waldon@kitware.com" target="_blank">shawn.waldon@kitware.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Hi Elvis,<br><br></div>I've done something fairly similar in one of my applications, returning a vtkSmartPointer<vtkImageData> via a Qt signal/slot from a background thread. And as far as I know the reference counting should work fine since the reference count is an atomic integer. It has worked fine for me so far and VTK_DEBUG_LEAKS doesn't complain so the reference counts are working somehow.<br><br>My guess about your reference count question: You are returning the smart pointer by value. The QFuture must be storing the smart pointer so that it can return it from the result() function. And when you return it that way it creates a second smart pointer, which would increment the reference count to 2.<br></div></div></blockquote><div><br></div></span><div>Ah, of course. Thanks! So then it's not a problem, my QFuture will be destroyed shortly thereafter as well.<br><br></div><div>And thanks for also bringing up VTK_DEBUG_LEAKS, I didn't know about.<br><br></div><div>But, so I can assume that both approaches (raw pointer, return a shallow copy) and returning a vtkSmartPointer are safe ways of doing this in this case? Nothing in the VTK ref counting machinery that could go wrong?<br></div></div></div></div></blockquote><div><br></div><div>The main thing to avoid is the reference count of the vtk object going to 0. So I think the safest way to do this is to pass the vtkSmartPointer around. You could probably pass the raw pointer if you tweaked the reference count manually, but the whole point of smart pointers is to avoid having to do that. I don't really see a reason to do a shallow copy. If the background thread was going to hang onto the object to do further changes to it, you would want a deep copy since most vtk objects are not threadsafe. Keep in mind that if the filter that produced it is re-executed then the data object will get overwritten (most filters reuse output objects when re-executed). But it sounds like you are letting the pipeline that produced it be deleted while just keeping the object itself.<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>Do you know if there are any things/gotchas or parts of VTK to watch out for when putting parts of a pipeline in a separate thread like this?<span class="HOEnZb"><font color="#888888"><br></font></span></div></div></div></div></blockquote><div><br></div><div>The only thing I know of is that rendering and associated things (mappers, actors, etc) have to be done in the foreground thread. If others on the list know about more, I would be glad to learn about them too.<br><br></div><div>HTH,<br></div><div>Shawn<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><span class="HOEnZb"><font color="#888888"></font></span></div><span class="HOEnZb"><font color="#888888"><div>Elvis<br></div></font></span><div><div class="h5"><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>HTH,<br></div>Shawn<br></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On Tue, Jul 5, 2016 at 5:11 PM, Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><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>
<br></div></div>_______________________________________________<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Please keep messages on-topic and check the VTK FAQ at: <a href="http://www.vtk.org/Wiki/VTK_FAQ" rel="noreferrer" target="_blank">http://www.vtk.org/Wiki/VTK_FAQ</a><br>
<br>
Search the list archives at: <a href="http://markmail.org/search/?q=vtkusers" rel="noreferrer" target="_blank">http://markmail.org/search/?q=vtkusers</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/vtkusers" rel="noreferrer" target="_blank">http://public.kitware.com/mailman/listinfo/vtkusers</a><br>
<br></blockquote></div><br></div>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>