C++11 thread, dziwna składnia na pierwszy rzut oka

0

Mam takie pytanie, może trochę głupie. Dlaczego w C++ składnia funkcji std::async wygląda tak:

X x;
auto f1=std::async(&X::foo,&x, 42, "witaj");

Przecież (błędny) zapis poniżej wydaje się bardziej naturalny, ale kompilator protestuje - Non common syntax

auto f1=std::async(x.foo, 42, "witaj"); 
6

Jeśli dobrze rozumiem - bo brak kontekstu całego kodu: w niestatycznych funkcjach składowych obiekt klasy na której funkcja ma być wywołana jest niejawnie przekazywany jako pierwszy parametr do funkcji. Konkretnie jest to wskaźnik na ów obiekt. Skąd w auto f1=std::async(&X::foo,&x, 42, "witaj"); pojawia się &x. &X::foo - & na początku - jest konieczne, ponieważ chcemy mieć wskaźnik na funkcje.

Dlaczego x.foo nie działa? Właściwie to nie wiem, nie jest to obsługiwane i już. Tutaj masz commit na forku gcc od @adrian17 który to naprawia: https://github.com/adrian17/gcc/commit/47ac8c45f89db7a5da686e757b595116f9dba1cc

Bardziej naturalna - jak dla mnie - konstrukcja:
auto f1 = std::async([&x] { return x.foo(42, "witaj"); });

7

std::async w formie w jakiej zostało dodane w C++11 to pomyłka. Zgodnie ze standardem

string x;
async(std::launch::async, [&x]{ x = "foo"; });
async(std::launch::async, [&x]{ cout << x; });

jest w pełni zdefiniowane i wykonuje się sekwencyjnie. Dlatego też korzystaj z czegoś innego.

0

@kq
http://www.cplusplus.com/reference/future/launch/
http://www.cplusplus.com/reference/future/async/

version (1) uses automatic selection, as if calling (2) with launch::async|launch::deferred as policy

||launch::async|launch::deferred||Automatic: The function chooses the policy automatically (at some point). This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.

clang 3.9: http://melpon.org/wandbox/permlink/j8X59rgsIMPvtzOd
gcc 7: http://melpon.org/wandbox/permlink/ICmTxszy8Eb20CEb
gcc 5.3: http://melpon.org/wandbox/permlink/IbDzcRtmPrs92EIW

1

Rzecz w tym, że std::future zwrócone przez std::async jest takie magiczne (w przeciwieństwie np. do takiego od std::packaged_task), że jest blokujące.

http://scottmeyers.blogspot.com/2013/03/stdfutures-from-stdasync-arent-special.html

edit: poprawiłem oryginalny post.

2

Przy zapisie
std::async([] {});
funkcja ta zwraca std::future które jest niszczone od razu. std::future ma natomiast w środku std::thread. W destruktorze ów std::future jest wywoływane .join() na tym wątku. I tyle.

1 użytkowników online, w tym zalogowanych: 0, gości: 1