Boost C++ Libraries: Ticket #9711: future continuation called twice https://svn.boost.org/trac10/ticket/9711 <p> I know it is still experimental, but I found a trivial bug in future::then(). </p> <p> If used with the deferred launch policy the continuation is called twice: </p> <p> The first time it is called in promise::set_XXX() or future::then() as it should be, but it is called again in the get() method of the future returned by the then() method. </p> <p> You can reproduce the problem by running the attached code. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9711 Trac 1.4.3 ikispal@… Tue, 25 Feb 2014 12:51:53 GMT attachment set https://svn.boost.org/trac10/ticket/9711 https://svn.boost.org/trac10/ticket/9711 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_future.cpp</span> </li> </ul> Ticket ikispal@… Tue, 25 Feb 2014 12:53:13 GMT cc set https://svn.boost.org/trac10/ticket/9711#comment:1 https://svn.boost.org/trac10/ticket/9711#comment:1 <ul> <li><strong>cc</strong> <span class="trac-author">ikispal@…</span> added </li> </ul> Ticket ikispal@… Tue, 25 Feb 2014 13:14:32 GMT <link>https://svn.boost.org/trac10/ticket/9711#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:2</guid> <description> <p> The second time the continuation is called an empty (invalid) future is passed to it. (I suppose the guts of the future was stolen by move() during the previous call.) </p> </description> <category>Ticket</category> </item> <item> <author>ikispal@…</author> <pubDate>Tue, 25 Feb 2014 14:46:54 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:3</guid> <description> <p> What is even worse: if the future returned by then() is not void, then: </p> <ul><li> the first call of its get() will call the continuation a second time (as described above) and will return with the result of this erroneous second invocation! </li></ul><ul><li>the second call of its get() will return with an empty (default constructed?) value! </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Tue, 25 Feb 2014 22:37:02 GMT</pubDate> <title>owner, status changed https://svn.boost.org/trac10/ticket/9711#comment:4 https://svn.boost.org/trac10/ticket/9711#comment:4 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Anthony Williams</span> to <span class="trac-author">viboes</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> <p> Thanks for catching this issue. I have not tested enough deferred futures with continuations. </p> Ticket viboes Wed, 26 Feb 2014 05:53:03 GMT <link>https://svn.boost.org/trac10/ticket/9711#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:5</guid> <description> <p> After reading more carefully the ticket and the example code, the single call must be on the call to </p> <pre class="wiki">futr2.get(); </pre><p> as the then has been called with a deferred policy, and not on the promise set_value(). </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 26 Feb 2014 06:37:56 GMT</pubDate> <title>component, milestone changed https://svn.boost.org/trac10/ticket/9711#comment:6 https://svn.boost.org/trac10/ticket/9711#comment:6 <ul> <li><strong>component</strong> <span class="trac-field-old">threads</span> → <span class="trac-field-new">thread</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.56.0</span> </li> </ul> <p> Just commenting the call to execute in future_deferred_continuation_shared_state should fix the issue. </p> <pre class="wiki"> virtual void launch_continuation(boost::unique_lock&lt;boost::mutex&gt;&amp; ) { //execute(lk); } </pre> Ticket anonymous Wed, 26 Feb 2014 09:27:19 GMT <link>https://svn.boost.org/trac10/ticket/9711#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:7</guid> <description> <p> If you want to start the continuation in the get() of futr2 that would mean that this will not start the continuation at all: </p> <pre class="wiki">auto futr1 = promise1.get_future(); auto futr2 = futr1.then({}); promise1.set_value(); </pre><p> Is this intended? (Please note that the only get() call here is inside the continuation itself.) What about this: </p> <pre class="wiki">auto futr1 = promise1.get_future(); auto futrLast = futr1.then({}).then({}).then({}); promise1.set_value(); </pre><p> Do I always have to keep track which future is at the end of the line and call its get()? My main use-case would be to not block at all, but this way I am forced to call get() and thus block in it. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 26 Feb 2014 17:59:07 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:8</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/9711#comment:7" title="Comment 7">anonymous</a>: </p> <blockquote class="citation"> <p> If you want to start the continuation in the get() of futr2 that would mean that this will not start the continuation at all: </p> <pre class="wiki">auto futr1 = promise1.get_future(); auto futr2 = futr1.then({}); promise1.set_value(); </pre></blockquote> <p> Here you create a continuation that is asynchronously called when the futr1 is ready and so it will be called independently of whether you get the value of futr2 or not. You example used deferred </p> <pre class="wiki">auto futr2 = futr.then(boost::launch::deferred, ...); </pre><p> so that the continuation should be called only when you call futr2.get(). </p> <blockquote class="citation"> <p> Is this intended? </p> </blockquote> <p> This is how I understand it. Maybe you can disagree. </p> <blockquote class="citation"> <p> (Please note that the only get() call here is inside the continuation itself.) What about this: </p> <pre class="wiki">auto futr1 = promise1.get_future(); auto futrLast = futr1.then({}).then({}).then({}); promise1.set_value(); </pre><p> Do I always have to keep track which future is at the end of the line and call its get()? </p> </blockquote> <p> The last one is stored in futrLast. What i sthe problem? </p> <blockquote class="citation"> <p> My main use-case would be to not block at all, but this way I am forced to call get() and thus block in it. </p> </blockquote> <p> Then you must use launch::async. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 26 Feb 2014 21:13:12 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:9</guid> <description> <p> <a class="ext-link" href="https://github.com/boostorg/thread/commit/d2a65d242751cece17e28b7cc6d7bfb395e900e8"><span class="icon">​</span>https://github.com/boostorg/thread/commit/d2a65d242751cece17e28b7cc6d7bfb395e900e8</a> <a class="ext-link" href="https://github.com/boostorg/thread/commit/a7400061c6a2851f65edbf5e536e31e7a2a62918"><span class="icon">​</span>https://github.com/boostorg/thread/commit/a7400061c6a2851f65edbf5e536e31e7a2a62918</a> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 12 Mar 2014 22:45:09 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/9711#comment:10 https://svn.boost.org/trac10/ticket/9711#comment:10 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> Ticket anton.matosov@… Fri, 10 Oct 2014 11:55:12 GMT <link>https://svn.boost.org/trac10/ticket/9711#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:11</guid> <description> <p> Commit d2a65d242751cece17e28b7cc6d7bfb395e900e8 completely disables functionality of the .then(launch::deferred, ...) continuation... </p> <p> I will open a separate ticket with the test code to reproduce the issue. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 12 Oct 2014 13:51:43 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:12</guid> <description> <p> I have added test for deferred then and every thing is OK <a class="ext-link" href="https://github.com/boostorg/thread/commit/3e28ea806c412c697f134fdaacbccc9b64213426"><span class="icon">​</span>https://github.com/boostorg/thread/commit/3e28ea806c412c697f134fdaacbccc9b64213426</a> </p> </description> <category>Ticket</category> </item> <item> <author>anton.matosov@…</author> <pubDate>Mon, 13 Oct 2014 09:15:52 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:13</guid> <description> <p> Ok. I see now that I was using it differently and possibly wrong way. In the old implementation 'deferred' continuation was called synchronously from the thread that sets satisfies the future. And I am relying on this functionality. However deferred means that it should be called when feature value is retrieved, which now looks correct, but it is not that obvious when you start with future continuations as it is not described anywhere. </p> <p> Is there any way to achieve the functionality of the sync call from the 'satisfier' side? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 17 Oct 2014 06:43:50 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9711#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9711#comment:14</guid> <description> <p> You have the extension promise::set_wait_callback </p> <p> <a href="http://www.boost.org/doc/libs/1_56_0/doc/html/thread/synchronization.html#thread.synchronization.futures.reference.promise.set_wait_callback">http://www.boost.org/doc/libs/1_56_0/doc/html/thread/synchronization.html#thread.synchronization.futures.reference.promise.set_wait_callback</a> </p> </description> <category>Ticket</category> </item> </channel> </rss>