<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">2016-07-06 8:50 GMT+02:00 Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.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 class="gmail_extra"><div class="gmail_quote"><span class="">2016-07-05 23:57 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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span>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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span>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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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></span><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></div></div></div></div></blockquote><div><br></div></span><div>Yes, that seemed like the safest thing to do. To have it as a one-off thread which just produces a result, not one that is reused.<br></div></div></div></div></blockquote><div><br></div><div>I realize now that one thing that I do lose with the approach I took is requests for subextents (e.g. using vtkExtractVOI), which my reader is ready to handle. I always have to read the entire volume as it is now.<br><br></div><div>What would be the best thing to do if I want to keep support for requesting subextents? To make a vtkExtractVOI work downstream, would I have to make a special "source" filter that spins of a thread to do the reading? That wouldn't work anyway I think, because then I'd block in the RequestData of the filter that is one down from that special source filter, while the thread is doing its work... not sure there is a solution for this..?<br><br></div><div>Elvis<br></div><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 class="gmail_extra"><div class="gmail_quote"><div><br></div><div>The shallow copying is something I found from Berk in this old thread (no pun intended) from 2014:<br><br>    <a href="http://public.kitware.com/pipermail/vtkusers/2014-March/083477.html" target="_blank">http://public.kitware.com/pipermail/vtkusers/2014-March/083477.html</a><br><br></div><div>In his example there he passes by raw pointer across threads, and use double shallow copying (shallow copying both in the producer and consumer thread).<br><br></div><div>But maybe that was just something that had to be done in the past, when the refcounting machinery was more susceptible to corruption in a multi-thread scenario?<br><br>Berk, do you remember the reason for the shallow copying? Because like Shawn above, I don't quite see the reason for it either, now that I think about it.<br></div><span class=""><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> <br></div><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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><font color="#888888"><br></font></span></div></div></div></div></blockquote><div><br></div></span><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></div></div></div></div></blockquote><div><br></div></span><div>Alright, yes that I've gathered as well.<br><br></div><div>Another thing I've seen warned against is having pipeline connections across threads. That is, a filter must not have its input connection set to the output port of a filter living in another thread. Is that also still generally true?<span class="HOEnZb"><font color="#888888"><br><br></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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>HTH,<br></div><div>Shawn<br></div><div><div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><span><font color="#888888"></font></span></div><span><font color="#888888"><div>Elvis<br></div></font></span><div><div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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></div></div><br></div></div>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>