mercredi 13 mai 2020

std::async blocks even with std::launch::async flag depending on whether the returned future is used or ignored [duplicate]

Description of the problem

std::async seems to block even with std::launch::async flag:

#include <iostream>
#include <future>
#include <chrono>

int main(void)
{
    using namespace std::chrono_literals;

    auto f = [](const char* s)
    {
        std::cout << s;
        std::this_thread::sleep_for(2s);
        std::cout << s;
    };

    std::cout << "start\n";
    (void)std::async(std::launch::async, f, "1\n");
    std::cout << "in between\n";
    (void)std::async(std::launch::async, f, "2\n");
    std::cout << "end\n";

    return 0;
}

output shows that the execution is serialized. Even with std::launch::async flag.

start
1
1
in between
2
2
end

But if I use returned std::future, it suddenly starts to not block!

The only change I made is removing (void) and adding auto r1 = instead:

#include <iostream>
#include <future>
#include <chrono>

int main(void)
{
    using namespace std::chrono_literals;

    auto f = [](const char* s)
    {
        std::cout << s;
        std::this_thread::sleep_for(2s);
        std::cout << s;
    };

    std::cout << "start\n";
    auto r1 = std::async(std::launch::async, f, "1\n");
    std::cout << "in between\n";
    auto r2 = std::async(std::launch::async, f, "2\n");
    std::cout << "end\n";

    return 0;
}

And, the result is quite different. It definitely shows that the execution is in parallel.

start
in between
1
end
2
1
2

I used gcc for CentOS devtoolset-7.

gcc (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

My Makefile is:

.PHONY: all clean

all: foo

SRCS := $(shell find . -name '*.cpp')
OBJS := $(SRCS:.cpp=.o)

foo: $(OBJS)
        gcc -o $@ $^ -lstdc++ -pthread

%.o: %.cpp
        gcc -std=c++17 -c -g -Wall -O0 -pthread -o $@ $<

clean:
        rm -rf foo *.o

Question

Is this behaviour in the specification?

Or is it a gcc implementation bug?

Why does this happen?

Can someone explain this to me, please?

Aucun commentaire:

Enregistrer un commentaire