6:00 Interesting to see the clover-leaf interchange used as an analogue to lock-free programming, and I have frequently said to other devs that playing with the train signalling systems in Transport Tycoon Deluxe taught me more about the concepts behind concurrent programming than many other things.
For the mailbox example, there needs to be another semaphore that the producer can sleep on if all of the mailboxes are full, otherwise it can end up busy-waiting. (In the producer, might be implemented by keeping a counter of how many boxes it's checked and sleeping if it's checked more than K boxes in a row.) In a preemptive multitasking environment it might not be a big deal, but you can't always assume there's a kernel that'll eventually stop you and schedule another thread unless you cooperatively yield in some way -- making busy-waiting on another thread not just lost performance, but an actual correctness bug.
The part 1 of the 3 hours speech has 400+ likes, the part 2 has no more than 200 lieks. I just came back from there, it's super hard but super informative and helpful.
In his example of lock-free producer/consumer implementation, isn't there a possibility that after consumer checks for null and right before he goes into waiting state, the producer sets task and sends signal? This way task would never be completed
Ohhhhhhhh, I guess this is partly why the containers in stl specify the behavior when they throw exceptions.. Oh my god. List is almost the most exception friendly container. When I learnt that I've had abs no idea about the purpose...
Lock-free programming sucks because the queue has to be polled. A usual mutex-/condvar-pair has very little kernel-participation under load conditions when the producer constantly procuces and the consumer constantly consumes. If the producer is faster than the consumer there's no kernel-participation.
59:40 destroying is not that easy. If there is no acquire relevant semantics/no mutual exclusivity, how do you know that what you are destroying isn't being used by some other thread. If you're interested, read about memory reclamation in lock-free contexts.
Why is there a '=' inside capture list of a lambda at 27:00 (std::call_once example)? At first I thought that we capture instance by value, not by a reference, and that this is an error in the slide. But after that I remembered that static variables are captured by reference anyway, so '=' does not affect it. Then, why "[=]" and not just "[]"? Also, shouldn't instance be dereferenced in the return statement? It's a unique pointer, and we're returning a reference...
There's nothing related to reference collapsing on that slide at 27:00. And if we write "return instance;", we attempt to return a reference to unique_ptr, not to the widget object itself. If we want to return a reference to the widget, we should write "return *instance;" instead (in order to dereference the unique_ptr). Or did I misunderstand something?
I know what reference collapsing is, and I have listened to Meyers' talks too. No, this case has nothing to do with either reference collapsing or RVO. Reference collapsing is about transforming a "reference to reference" into a single reference in some cases. RVO is about returning objects by value, not about returning references. So, that's not the case for both of these features. And the type "std::unique_ptr &" (type of expression "widget::instance") cannot be implicitly converted to "widget &" without an explicit dereferencing statement.
You seem to have no idea what you're talking about :( Just typin' some random words, meaning of which you don't understand. Please go read about RVO and NRVO. I've already explained why (N)RVO has nothing to do with this case: we are returning a reference, not an object by value. And of course you are right that a static object of type "unique_ptr" can be returned from function by reference. But what will be the type of that reference? It will be "unqie_ptr &"! Not "widget &". To obtain a "widget &" from such unique_ptr, we must dereference it (using operator *). If you don't believe me, test this code yourself. I have already done this. Here's the link: ideone[dot]com[slash]wKJDCx Just see what compiler tells about the "return instance;" statement: prog.cpp: In static member function 'static widget& widget::get_instance()': prog.cpp:19:9: error: invalid initialization of reference of type 'widget&' from expression of type 'std::unique_ptr' return instance; // works fine with "*", fails to compile without it
I have read Effective Modern C++ and seen a lot of talks. Still have no idea what "rule" are you talking about. Maybe you have misunderstood something? I've provided a link to ideone in my previous comment. Please see it. They use gcc-5.1. Do you think it is a compiler bug?
6:00 Interesting to see the clover-leaf interchange used as an analogue to lock-free programming, and I have frequently said to other devs that playing with the train signalling systems in Transport Tycoon Deluxe taught me more about the concepts behind concurrent programming than many other things.
I would have thought a roundabout more apt.
Doesn't the word "semaphore" originate from railway tech/scheduling as well
For the mailbox example, there needs to be another semaphore that the producer can sleep on if all of the mailboxes are full, otherwise it can end up busy-waiting. (In the producer, might be implemented by keeping a counter of how many boxes it's checked and sleeping if it's checked more than K boxes in a row.) In a preemptive multitasking environment it might not be a big deal, but you can't always assume there's a kernel that'll eventually stop you and schedule another thread unless you cooperatively yield in some way -- making busy-waiting on another thread not just lost performance, but an actual correctness bug.
The part 1 of the 3 hours speech has 400+ likes, the part 2 has no more than 200 lieks. I just came back from there, it's super hard but super informative and helpful.
In his example of lock-free producer/consumer implementation, isn't there a possibility that after consumer checks for null and right before he goes into waiting state, the producer sets task and sends signal? This way task would never be completed
18:00 Double-Checked Locking Pattern
Staring at 56:25 out of 1:00:23 and hearing "if we get to the bonus slides"
Somehow i doubt i'm gonna get to see those bonus slides :(
There is a part two, search for:
CppCon 2014: Herb Sutter "Lock-Free Programming (or, Juggling Razor Blades), Part II"
Ohhhhhhhh, I guess this is partly why the containers in stl specify the behavior when they throw exceptions.. Oh my god. List is almost the most exception friendly container. When I learnt that I've had abs no idea about the purpose...
This is a great talk!
Lock-free programming sucks because the queue has to be polled. A usual mutex-/condvar-pair has very little kernel-participation under load conditions when the producer constantly procuces and the consumer constantly consumes. If the producer is faster than the consumer there's no kernel-participation.
59:40 destroying is not that easy. If there is no acquire relevant semantics/no mutual exclusivity, how do you know that what you are destroying isn't being used by some other thread. If you're interested, read about memory reclamation in lock-free contexts.
The chase: 39:29
Why is there a '=' inside capture list of a lambda at 27:00 (std::call_once example)? At first I thought that we capture instance by value, not by a reference, and that this is an error in the slide. But after that I remembered that static variables are captured by reference anyway, so '=' does not affect it. Then, why "[=]" and not just "[]"?
Also, shouldn't instance be dereferenced in the return statement? It's a unique pointer, and we're returning a reference...
There's nothing related to reference collapsing on that slide at 27:00.
And if we write "return instance;", we attempt to return a reference to unique_ptr, not to the widget object itself.
If we want to return a reference to the widget, we should write "return *instance;" instead (in order to dereference the unique_ptr).
Or did I misunderstand something?
I know what reference collapsing is, and I have listened to Meyers' talks too. No, this case has nothing to do with either reference collapsing or RVO. Reference collapsing is about transforming a "reference to reference" into a single reference in some cases. RVO is about returning objects by value, not about returning references. So, that's not the case for both of these features.
And the type "std::unique_ptr &" (type of expression "widget::instance") cannot be implicitly converted to "widget &" without an explicit dereferencing statement.
You seem to have no idea what you're talking about :(
Just typin' some random words, meaning of which you don't understand. Please go read about RVO and NRVO.
I've already explained why (N)RVO has nothing to do with this case: we are returning a reference, not an object by value.
And of course you are right that a static object of type "unique_ptr" can be returned from function by reference.
But what will be the type of that reference?
It will be "unqie_ptr &"! Not "widget &".
To obtain a "widget &" from such unique_ptr, we must dereference it (using operator *).
If you don't believe me, test this code yourself.
I have already done this. Here's the link:
ideone[dot]com[slash]wKJDCx
Just see what compiler tells about the "return instance;" statement:
prog.cpp: In static member function 'static widget& widget::get_instance()':
prog.cpp:19:9: error: invalid initialization of reference of type 'widget&' from expression of type 'std::unique_ptr'
return instance; // works fine with "*", fails to compile without it
I have read Effective Modern C++ and seen a lot of talks. Still have no idea what "rule" are you talking about. Maybe you have misunderstood something?
I've provided a link to ideone in my previous comment. Please see it. They use gcc-5.1.
Do you think it is a compiler bug?
I'm sure this is just a typo on the slide, it should be return *instance of course. [=] is also not needed (it captures nothing) and could be [].