14

Consider following code

void printPromised(std::future<int> f)
{
    std::cout << f.get() << std::endl;
}

int main()
{
    printPromised(std::async(std::launch::async, [](){ return 8; })); // This works

    auto f = std::async(std::launch::async, [](){ return 8; });
    printPromised(f); // This won't work
}

It says "It is a deleted function". Why is that? Further I need to pass (share) the same promised result which std::async generated to multiple users. That means when someone calls the get() function, I need to pass the same result (I don't need to re generate the result using std::async if it is already generated) and also I need the blocking mechanism which std::future::get has.

Simon
  • 241
  • 2
  • 13
Amith Chinthaka
  • 1,015
  • 1
  • 17
  • 24

2 Answers2

23

There can be only one future. You cannot have multiple copies of the same future. So you need to transfer ownership of the future to the function:

printPromised(std::move(f));
//            ^^^^^^^^^^^^

If you genuinely need shared access to a future, you can construct a shared_future from an ordinary future by calling the share() member function; this behaves similarly to a shared pointer:

auto sf = std::async(std::launch::async, [](){ return 8; }).share();

Now sf can be copied, and all copies wait for the same result, i.e. the wait() calls on all copies may block and will synchronize with the becoming-ready of the result.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • So in that case multiple users cannot use the results at the same time. Am I right? – Amith Chinthaka Nov 28 '14 at 10:11
  • 5
    @AmithChinthaka: Right; that's what the `shared_future` is for. – Kerrek SB Nov 28 '14 at 10:12
  • 4
    @KerrekSB, in my implementation there is no added cost to `shared_future`, and I'd think that's fairly typical. The shared state already has to be shared by at least two objects (the asynchronous provider and the asynchronous result) so I always manage it with `shared_ptr` anyway, going to N=2 to N>=2 doesn't cost anything. – Jonathan Wakely Nov 28 '14 at 10:18
  • @JonathanWakely: Thanks, I'll remove the mention of costs then. – Kerrek SB Nov 28 '14 at 10:21
  • Another thing. We know that object can pass by reference and by value. With std::future how these concepts work. (I don't know this question is not relevant to the thread) – Amith Chinthaka Nov 28 '14 at 10:25
  • @AmithChinthaka, what do you mean "how these concepts work"? They work just like they do for other C++ types. If you pass by reference you get a reference, if you pass by value you get a new object. `std::future` is a move-only type so you can't copy it to pass by value, you need to move it. Look up "move-only type". – Jonathan Wakely Nov 28 '14 at 10:58
  • @JonathanWakely Yeah that's what I need to know. – Amith Chinthaka Nov 28 '14 at 11:22
1

This is what I came up after this discussion.

#include <future>

typedef std::shared_future<int> SharedFutureInt;

struct Object 
{
    SharedFutureInt m_promised;
    bool isAssigned;

    Object() : isAssigned(false)
    {

    }

    SharedFutureInt getObjects()
    {
        if (isAssigned)
        {
            return m_promised;
        }

        m_promised = std::async(std::launch::async, [](){ return 8; });
        isAssigned = true;
        return m_promised;
    }
};

int main()
{
    Object obj;
    int a = obj.getObjects().get();
    int b = obj.getObjects().get();
    int c = obj.getObjects().get();

    return 0;
}
Amith Chinthaka
  • 1,015
  • 1
  • 17
  • 24