A promise is actually not broken by never setting the value into the promise. This will just make the child wait forever inside f.get(). The broken_promise exception gets thrown when the promise variable is destroyed by going out of scope.
pitfall that should have been mentioned: one must always assign the return value of the call to std::async(std::launch::async,...) to a variable (and not just call it without assigning the return value), otherwise the call still blocks until execution of the thread finishes (because if not assigned, the return value can be destroyed immediately, and the destructor of that future waits for the task to finish).
9:50 f.get() will block the thread until the promis value is not set. By putting p.set_exception in main thread you are actually making child thread to throw an exception, otherwise it will be blocked forever. That's how it on g++ works.
What if you want the child thread to asynchronously return data to the main thread e.g. main thread creates child to load a file, main thread continues handling event loop without waiting on future::get or thread::join. When the file is loaded, the main thread is signaled so it can take the data and display it
Even when I use a simple line like std::future<int> f2 = std::async(std::launch::async, [](){ return 8; }); in Dev C++ (5.4.1) or Code Blocks (12.11) I get this error message: main.cpp|16|error: variable 'std::future<int> fu' has initializer but incomplete type| Whice IDE are you using? Please advise.
your issue is that a future is a template, not a type this means it`s not a future it`s a future of an int (std::future) or a string (std::future) hope that helps, even if i am 6 years late
In the last example with std::shared_future, please do not forget that all these spawned threads share std::cout, which needs to be synchronized as well!
One question.The std::async and std::thread fulfils the same purpose of threading , then how to differentiate b/w them.Is there any performance related factor or when to use which mechanism
Thanks for this instructive video! I don't understand why we can't just move the p.get_future() to the task, and why we have to store it locally and give the task a _reference_ to the future. It looks error prone to me: this way we can (easily) pass out multiple references to the same future.
What is the harm in making the variable int x global so as to not pass it by reference to the thread? Such as this: mutex mu; int x; // now global void factorial(int N) { mu.lock(); int res = 1; for (int i = N; i > 1; i--) res *= i; cout
I think its just easier to use it with these libraries. You can still achieve the same result but that means more variables and more mutexes which makes it harder avoiding deadlocks. For your code, dont use lock for the all the loop part. If N is big, the function would keep the lock too long. It is not needed in the loop in the code so you can lock it before changing the x at the last part. If you want to use lock for loop part do it like for(int i = N,i > 1;--i){ mu.lock(); // maybe another mutex if you want exclusive access for x. res *= i; mu.unlock(); }
Also, one other thing I realized here is that when using the async function there is way to join the thread. I suppose that instead we would have to rely upon the future's get() to unblock (fu.get() to return a value). Is that correct?
Hi all!! I am convinced that in this particular case: (exactly how the code is written) /* For threads to return values: future */ void factorial(int N, int & X) { int res = 1; for (int i = N; i > 1; i--) res *= i; X = res; } int main() { int X; std::thread t1(factorial, 4, std::ref(X)); t1.join(); cout
I know this is super old, but I can't help myself: The return type for the function you passed to std::async() is void, but it should be int... This error would have been hidden by using the 'auto' type for the future (a habit I have), but you would have had a similar error on future's get() method, since it would return a void (or nothing, to be accurate), and you would be trying to assign that void into an integer.
"The names Future and Promise are historical; please don´t blame me" - Section 5.3.5.1 - Pag 121, The C++ Programming Language 4th Edition... BJarne Stroustup
I guess it's just for the purpose of the tutorial. That's true, using namespace std implies you don't need to write out std:: He uses this namespace just to avoid making heavy the writing for basics instructions like std::cout and other beginning things that doesn't involve multithreading. Yet he wants to show us from which library the objects and function come the items he is using. Like maybe there are threads and mutex also in boost library or many other libraries. So he wants to emphasize that we are using items from the standard library. Also I have seen many tutorials that explicitly say avoid the statement using namespace std. In case other namespaces are involved the confusion will occur on the question whose library is this item. A good practice according to them is to write as much as possible std:: without using the namespace std at all. If I am not wrong, if we are using multiple namespaces (like std and boost and others), the compiler will have to guess randomly from which library an item comes from (since these libraries can have a large amount of items with the same names). Its guess might be different from our intent. In such a case, debugging might be a nightmare to find out that a mix had occured in the code. I guess usually Bo would not write using namespace std.
std:future and std:promise have been criticized as being slow, see for example this presentation ua-cam.com/video/tF-Nz4aRWAM/v-deo.html. The improvement ideas given in the presentation have been implemented as a header-only library which can be found in github.com/tirimatangi/Lazy. For example, factorials of numbers given in a vector can be calculated in parallel into the result vector like this: #include #include "Lazy.h" int factorial(int N) { if (N 1; --i) res *= i; return res; } int main() { try { auto vecOutput = Lazy::runForAll({10, 3, 6, 9}, factorial); std::cout
I do not know why so many say this is a nice video, I want to say this is really not a good tutorial video for beginners. The maker did not say why we need to use async, launch::defer, and so on. He just show us, used it, without any reasons, I also watched some former videos, some of modifications to the code, without show the result and differences with the fomer code. Anyway, this is really not good tutorial for beginners, entry levels .
A promise is actually not broken by never setting the value into the promise. This will just make the child wait forever inside f.get(). The broken_promise exception gets thrown when the promise variable is destroyed by going out of scope.
Thanks for clarifying this. I suspected this was the case.
So not getting a promise is more likely to a dead lock, I guess.
Sounds like a sad story
Why c++ has promise and future
Almost 6 years later and these very clear and concise videos are extremely helpful. THANK YOU!
10 years later and this is what saved my project
This is so...philosophical.
Thank you for this wonderful series of tutorials on C++ threading. You truly know your stuff. I have learned a lot! Thanks again!
Best tutorial on the concept of multi threading and async task. Love it. It clears up lots of confusion for me. Thanks
your videos are awesome, so underestimated. you explain everything so well and in an understandable manner, keep on the amazing work!
it is the best video I have seen about Future, Promise and async, and share_future . Thanks
Hi Bo, your videos so crisp and clean. Keep it up!
This was really good, Thank you Bo Qian.
std::broken_promise and std::shared_future sound so funny!
Thank you for your instructive classes!
pitfall that should have been mentioned: one must always assign the return value of the call to std::async(std::launch::async,...) to a variable (and not just call it without assigning the return value), otherwise the call still blocks until execution of the thread finishes (because if not assigned, the return value can be destroyed immediately, and the destructor of that future waits for the task to finish).
I just faced such a problem an hour ago...
Excellent tutorial, really helped understand this alternative technique of thread management.
Very nice , very futuristic. My favorite video.
Thank you so much for this. Been trying to find a clear example of this all afternoon.
Zank You, Master.
you are truly the best programming youtuber i`ve ever watched
edit: just realised i`m the 69th comment
@12:54 or you can simply have :
std::promise prms;
std::shared_future sfu = prms.get_future();
Thanks Bo this helped me a lot, your teaching method is very clear and easy to understand. Subscribed and thumbs up :)
9:50 f.get() will block the thread until the promis value is not set. By putting p.set_exception in main thread you are actually making child thread to throw an exception, otherwise it will be blocked forever. That's how it on g++ works.
"to err is human" Man I fucking love this guy.
C++ is just beautiful
Awesome. Thank you for this video.
Clang claims it has 100% support, but I haven't tried it.
What if you want the child thread to asynchronously return data to the main thread e.g. main thread creates child to load a file, main thread continues handling event loop without waiting on future::get or thread::join. When the file is loaded, the main thread is signaled so it can take the data and display it
Thanks - I work a lot with threads and enjoyed this excellent example -
how to create vector of unique_ptr of 2 employees and also how to display
Even when I use a simple line like
std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });
in Dev C++ (5.4.1) or Code Blocks (12.11)
I get this error message:
main.cpp|16|error: variable 'std::future<int> fu' has initializer but incomplete type|
Whice IDE are you using? Please advise.
your issue is that a future is a template, not a type
this means it`s not a future it`s a future of an int (std::future) or a string (std::future)
hope that helps, even if i am 6 years late
Thank you shi fu!
The only Indian accent tutorial that's worth watching.
Thank you very much!! Your videos are really good!
Really a good explanation in easy way
In the last example with std::shared_future, please do not forget that all these spawned threads share std::cout, which needs to be synchronized as well!
Best tutorial on this topic
awesome material! just a bit funny every time we have the future variable name fu lmao
You are an amazing programmer
You are superb man...
One question.The std::async and std::thread fulfils the same purpose of threading , then how to differentiate b/w them.Is there any performance related factor or when to use which mechanism
Just became a software engineer. This video is very clear and helpful. Thank you very much!
awesome! only one thing, if you don't set the promise, nothing happens, but the child thread just will sleep forever in the f.get().
apart from your wonderful videos , i love your phrases :) ... "to err is human ", "beauty is skin deep" :))
Thanks for this instructive video!
I don't understand why we can't just move the p.get_future() to the task, and why we have to store it locally and give the task a _reference_ to the future.
It looks error prone to me: this way we can (easily) pass out multiple references to the same future.
What is the harm in making the variable int x global so as to not pass it by reference to the thread? Such as this:
mutex mu;
int x; // now global
void factorial(int N) {
mu.lock();
int res = 1;
for (int i = N; i > 1; i--)
res *= i;
cout
I think its just easier to use it with these libraries. You can still achieve the same result but that means more variables and more mutexes which makes it harder avoiding deadlocks.
For your code, dont use lock for the all the loop part. If N is big, the function would keep the lock too long. It is not needed in the loop in the code so you can lock it before changing the x at the last part. If you want to use lock for loop part do it like
for(int i = N,i > 1;--i){
mu.lock(); // maybe another mutex if you want exclusive access for x.
res *= i;
mu.unlock();
}
Also, one other thing I realized here is that when using the async function there is way to join the thread. I suppose that instead we would have to rely upon the future's get() to unblock (fu.get() to return a value). Is that correct?
Is it right that we need two future objects,
first to get associated with promise and set value (f)
second to get value from child thread (fu)
Hi,
In your knowledge is there a compiler which completely (100%) supports C++11 even now.
After 9 years they all do 😁
Thank you! Pround of you as Chinese.
Great language .. Funny way to teach great concepts.
Hi,could you make some videos about co_routine on visual studio?Thanks
Hi all!!
I am convinced that in this particular case: (exactly how the code is written)
/* For threads to return values: future */
void factorial(int N, int & X) {
int res = 1;
for (int i = N; i > 1; i--)
res *= i;
X = res;
}
int main() {
int X;
std::thread t1(factorial, 4, std::ref(X));
t1.join();
cout
Not sure if I understand, so does the program halt at ( int N = f.get() ) until the promise is set to a value later in the program?
What IDE are you using?
thank you Bo Qian!!!
GCC and TDM MinGW 4.8.1 both have full C++11 support, too.
Still lacking std::regex functionality, but other than that fairly complete I think. Can't wait for GCC *4.9*!
You sir rock! thank you for the beautiful summary.
Very clear & useful, thank you!
Very good video!
Does p.get_future() create new thread?
error: conversion from 'std::future' to non-scalar type 'std::future' requested
What is this>?
I know this is super old, but I can't help myself:
The return type for the function you passed to std::async() is void, but it should be int...
This error would have been hidden by using the 'auto' type for the future (a habit I have), but you would have had a similar error on future's get() method, since it would return a void (or nothing, to be accurate), and you would be trying to assign that void into an integer.
It says something about C++ that this 10 year old video is still pretty much the latest info regarding C++ concurrency patterns
Hell, and here I thought this C++ threading stuff was going to be hard...
"The names Future and Promise are historical; please don´t blame me" - Section 5.3.5.1 - Pag 121, The C++ Programming Language 4th Edition... BJarne Stroustup
Thanks! It's awesome!
very nice explanation :)
why do you "using namespace std;" but still use "std::"
I guess it's just for the purpose of the tutorial.
That's true, using namespace std implies you don't need to write out std::
He uses this namespace just to avoid making heavy the writing for basics instructions like std::cout and other beginning things that doesn't involve multithreading.
Yet he wants to show us from which library the objects and function come the items he is using. Like maybe there are threads and mutex also in boost library or many other libraries. So he wants to emphasize that we are using items from the standard library.
Also I have seen many tutorials that explicitly say avoid the statement using namespace std. In case other namespaces are involved the confusion will occur on the question whose library is this item.
A good practice according to them is to write as much as possible std:: without using the namespace std at all.
If I am not wrong, if we are using multiple namespaces (like std and boost and others), the compiler will have to guess randomly from which library an item comes from (since these libraries can have a large amount of items with the same names). Its guess might be different from our intent.
In such a case, debugging might be a nightmare to find out that a mix had occured in the code.
I guess usually Bo would not write using namespace std.
thanks for this tutorial playlist
Thanks a lot, very helpful
Use Visual Studio 2012. The express version is free.
Thanks! Keep up the good work :)
不错👍 厉害
Awesome class
Future software engineering parents: no need to take parenting class...just take this concurrency series.
I am using < and > for less_than and greater_than because youtube is not allowing those symbols in comment. The syntax is othewise correct.
Amazing thx❤
promise is a promise !!!
Great video and easy to follow, thank you!
std:future and std:promise have been criticized as being slow, see for example this presentation ua-cam.com/video/tF-Nz4aRWAM/v-deo.html.
The improvement ideas given in the presentation have been implemented as a header-only library which can be found in github.com/tirimatangi/Lazy.
For example, factorials of numbers given in a vector can be calculated in parallel into the result vector like this:
#include
#include "Lazy.h"
int factorial(int N)
{
if (N 1; --i)
res *= i;
return res;
}
int main()
{
try {
auto vecOutput = Lazy::runForAll({10, 3, 6, 9}, factorial);
std::cout
❤❤❤❤
Nice
Seriously, "promise" why so childish (*_*). BTW this tutorials helps a lot.
I do not know why so many say this is a nice video, I want to say this is really not a good tutorial video for beginners. The maker did not say why we need to use async, launch::defer, and so on. He just show us, used it, without any reasons, I also watched some former videos, some of modifications to the code, without show the result and differences with the fomer code. Anyway, this is really not good tutorial for beginners, entry levels
.
multi-threading is definitely not for beginners, its a good tutorial for me.
Ot dushi
std::future fu
Great explanations, thanks! :)
Nice