16

I'm encountering something very weird when using packaged tasks. When reading ~packaged_task I get the impression that if a std::packaged_task is destroyed before it is executed, the promise will be broken and an attempt to get the result from the future should throw std::future_error.

However, on Visual Studio 2013 this doesn't seem to be the case. Take this following code:

#include <iostream>
#include <future>
#include <functional>

int main() {
    std::future<int> f;
    {
        std::packaged_task<int()> task([](){return 3; });
        f = task.get_future();
    }
    std::cout<<f.get()<<std::endl;
    return 0;
}

I'm expecting to get an std::future_error on f.get() but instead it blocks, waiting for the packaged task to be executed.

Trying another compiler: http://ideone.com/Wt0WOc does indeed throw a std::future_error("Broken promise")...

Am I seeing a bug in Visual Studio 2013 or have I missed something?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Emily L.
  • 5,673
  • 2
  • 40
  • 60

2 Answers2

11

You are correct. ~packaged_task() abandons the shared state (§30.6.9.1 [futures.task.members]/p9), which means, if the shared state is not ready, storing an exception object of type future_error with error condition of broken_promise, then making the shared state ready; and then releasing the shared state (§30.6.4 [futures.state]/p7).

This is a known bug that will be fixed in the next version of Visual Studio, which is likely to come out some time in 2015. It's also fixed in the CTP, but it's a pretty bad idea to use that for production code...

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • So did I read those links correctly, this will not be fixed in VS 2013? – Emily L. Sep 10 '14 at 10:46
  • @EmilyL. I'd say very unlikely. According to [Q5 in the FAQ section of this page](http://blogs.msdn.com/b/vcblog/archive/2013/06/28/c-11-14-stl-features-fixes-and-breaking-changes-in-vs-2013.aspx), they backport bugfixes only rarely. – T.C. Sep 10 '14 at 10:46
  • 2
    Great, the studio we bought is barely a year old and they are already leaving us in a pinch. *sigh* Thanks for the confirmation. Accepting this answer as the links put the final confirmation on my suspicions. – Emily L. Sep 10 '14 at 10:48
7

I think it's a bug, the standard says ~packaged_task abandons the shared state, which means that if it isn't ready yet it should store a broken_promise exception and make the state ready, just as you expect.

Full disclosure: your ideone.com test uses GCC and I implemented GCC's <future> so I might be biased when I say its behaviour is correct ... but I think it is still correct ;-)

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Fully agreed. An abandoned `future` (i.e. the return value in this case) is *the* situation for a `broken_promise`. – starturtle Jun 14 '16 at 07:17