Deprecating volatile - JF Bastien - CppCon 2019

  Рет қаралды 29,221

CppCon

CppCon

Күн бұрын

Пікірлер: 40
@trolololo510
@trolololo510 5 жыл бұрын
Great talk! Correct me if I'm wrong but the expectation mentioned at 14:21 seems quite logical to me. There exist hardware registers that clear counters when the register is read. So if we want to clears those counters we can do so by writing *vp; it is the perfect solution since we don't need to create a temporary.
@sirmoonslosthismind
@sirmoonslosthismind 5 жыл бұрын
he doesn't say it's an illogical expectation, only that the standards haven't always guaranteed that expectation.
@movax20h
@movax20h 4 жыл бұрын
Love the real time updating on the slide 5 at 1:50 :) ISO 8601 for the win.
@alfred2g
@alfred2g 5 жыл бұрын
at time 14:34 *vp, it clears the register on some hardware when you just read from it
@Bourg
@Bourg 4 жыл бұрын
It's not guaranteed to do a read by all versions of the standard, and isn't clearly a read for folks reading the code. Yes in some versions it's been a read, and some might feel good about knowing this, but I'd much rather have easy to understand code where I can.
@sanderbos4243
@sanderbos4243 Жыл бұрын
​@@Bourg I wasn't 100% confident when first seeing the slide in this video whether it'd emit any code. Is the alternative you recommend in this case "int _ = *vp;", or is there an alternative that you find nicer, like maybe "(void)*vp;" or something? :)
@DrGreenGiant
@DrGreenGiant 3 жыл бұрын
Volatile is very useful in embedded debugging, or at least I've found it to be
@kamilziemian995
@kamilziemian995 Жыл бұрын
You have very interesting perspective.
@Elavid
@Elavid 2 жыл бұрын
Why exactly is "port |= 1;" being deprecated, where "port" is a volatile variable? At 44:58 JF Bastien says he is confused about what that does, but he is smart enough to read the "expr.ass" section of the standard which defines what "|=" means. He didn't give any examples of other people who were confused by this. And what's his vision for the large amount of AVR code that uses this to succinctly generate "sbi" instructions to set a single bit in an I/O register? Is inline assembly the new plan? (I guess that's OK, and it would be better than |= because the |= method sometimes becomes a multi-instruction operation that is not interrupt-safe if the left or right side is too complicated.)
@ChrisPVille
@ChrisPVille Жыл бұрын
Yeah most of the depreciated uses of volatile are usually wrong, but the arrogance with which he plunged into use-cases he did not understand is kinda startling. Proposal 2327 was accepted as a defect in C++20 and restores volatile compound operations in draft C++23.
@speedstyle.
@speedstyle. Жыл бұрын
If compound assignment was compilation error on platforms and objects which couldn't support this then it would make sense. That can't really be the case for standards-compliant C++ though, there isn't a consistent way to handle these hardware-dependent uses. Some compilers even emit locks or CASs to make these operations atomic, which is unintuitive.
@elektro-peter1954
@elektro-peter1954 5 жыл бұрын
Hm, The 6502 architecture has the instruction "inc {memory}". Some architectures, for exampele AVR, have set bit and clear bit instructions. those might be a valid reason to keep the ++, --, +=, &= and |= operators on volatile. At leas avr-gcc emits set bit and clear bit instructions when doing stuff like "*(volatile uint8_t*) io_reg |= (1
@pazdziochowaty
@pazdziochowaty 5 жыл бұрын
Even X86 has inc/dec ptr [mem] as well as add/sub/and/or/xor with memory destination which gives sense to all the volatile operators
@movax20h
@movax20h 4 жыл бұрын
All of the bit operators can be implemented as operators some predefined structs that takes memory address to operate on. There is no need for volatile in the language really.
@movax20h
@movax20h 4 жыл бұрын
Just implement it on your own using assembler. Easy. It doesn't need to be in the C++ standard.
@Bourg
@Bourg 4 жыл бұрын
They're not single-copy atomic unless you use the lock prefix. If you want the lock prefix on non-normal memory, then volatile atomic is the tool for the job, not straight up volatile.
@josealvim1556
@josealvim1556 4 жыл бұрын
the best part of C++ is mutable const
@origamibulldoser1618
@origamibulldoser1618 Жыл бұрын
No, the best part of C++ is how much we cry and whine about the language, but still don't move on. :D
@WilhelmDrake
@WilhelmDrake 2 ай бұрын
​@@origamibulldoser1618 As a wise man once said, "There are only two kinds of languages: the ones people complain about and the ones nobody uses".
@n-v5m
@n-v5m 7 ай бұрын
There are many frameworks that provides the user with move ops policies to control the relocation for small buffer enhanced containers containers
@lunakid12
@lunakid12 4 ай бұрын
Nice talk*, I just got distracted by all those mentions of the quirks of a mysterious "single handler"... ;) ---- * apart from a few shocking absurdities like the desire of standardizing `sizeof void* == 8`, or killing const return values altogether (-> how to help catching silent bugs of misusing non-member `const obj f()` as `f() = failed_update` then?)
@AykevanLaethem
@AykevanLaethem 4 жыл бұрын
Why not model volatile as function calls? A load is a getter and a store is a setter. At least on all the embedded architectures I've seen this is makes the most sense actually and it is how I implemented it in TinyGo for memory mapped I/O. An instruction qualifier does make sense but getters/setters are perhaps the closest you get to loads/stores.
@Runoratsu
@Runoratsu 4 жыл бұрын
Had to follow you on twitter for that joke and for introducing ponies and dinos into the standard. You‘re doing very valuable work there. 😁
@ABaumstumpf
@ABaumstumpf Жыл бұрын
I find this type of talk really strange: Somebody find something that they personally don't use - and then thinks "lets remove it cause i don't like it". Volatile means the value can be changed by the hardware - nothing more, nothing less, and has always been that way. So it is correct that we can expect that the compiler will respect every load and every store - cause that is the one guarantee that the standard makes about the volatile-qualifier (contrary to the guarantees of std:atomic ). This talk even is a great example why this should NOT be done under any circumstance: 1:50 - standardising "size(void*) )) 8" - you have successfully destroyed all backwards-compatibility, made portability impossible, locked C++ to a very specific hardware-architecture and prevented any further changes without yet again breaking changes. With the"bad" examples were you say you don't know what it does - if you don't know what it does then first you should try to understand what the language says about the volatile-qualifier, and then, if it is still not satisfactory, IMPROVE it, not remove the only qualifier that allows interacting with hardware. 13:25 it reads the value. by the standard it HAS to read the value (and that rule has never changed for C++). Now the funny thing - do you know what would happen if you used a std::atomic instead? It can and likely WILL be optimised away. std::atomic is not suitable in this case if you require an actual read to happen. Similar things can seriously break your code if you are using for example shared memory between processes. Volatile in no way says that it has to be done in a single instruction - and why would it? It seems like an intentional misrepresentation of what volatile or atmoic actually mean. This entire talk screams of running away instead of tackling the problem. Even worse - this is kinda hints at "atomic" being broken in C++, not volatile, as the language is talking in terms of volatile and atomic, but atomic is not part of the language and does not offer real guarantees either (even worse, the language mandates the use of valatile-atomic in certain situations ). atomic not being a qualifier but some magic library template magic - that is the problem. Also no, atomic does NOT guarantee a single read or a single assignment, it does not guarantee that a read/write happens in 1 step, it does not tell you anything about how often it is touched, it only says that a given access (be it read or write) is consistent with the given memory-ordering-qualifier. This means given 2 threads T1 and T2 and an atomic A1 - if T1 writes to A1 and later T2 reads from A1 it is NOT guaranteed to see the modification even after several seconds, depending on the given memory-order. And the deprecation of volatile - thankfully the Committee had at least some semblance of sanity and undid some of the damage they have done. It is sadly has still made many hardware-interaction impossible to express in valid C++ - so and active and intentional regressing for anybody writing code for microcontrollers or other down-to-the-metal situations.
@lunarjournal
@lunarjournal Жыл бұрын
Bingo, you nailed it! . /rant incoming from pure c guy Look what is going on here is nothing more than the c++ committee moving from confusion to utter insanity. BTW I think 'modern' C++20 is an ugly, verbose mess. At this point it is perfectly clear that the C++ ISO committee has lost touch with reality, churning out one bad design or idea after another, just look at modules... Everyone nowadays wants their own feature in the language.. Someone once mentioned to me that C++ templates (i.e poor man's text editor) are turing complete and that you could create classes by passing some ascii art image of your data. At that point I knew things were about to go from bad to worse. I'm not even going to try argue with C++ 'modernists' it's pointless... One thing though... leave C out of all this madness. It's the one language I adore for being simple, stable and predictable which is why it is the language of choice for embedded. I don't care about templates, constexpr, ranges, metaprogramming, operator overloading, etc.
@josemonge4604
@josemonge4604 11 ай бұрын
I also got so annoyed by this talk. Jesus...
@kiroma0
@kiroma0 5 жыл бұрын
9:52, compare_exchange_strong must by standard never fail spuriously, compare_exchange_weak is allowed to.
@robinLambertz
@robinLambertz 5 жыл бұрын
That's the point. compare_exchange_weak can fail spuriously, so will (probably) result in a single load/store pair. But compare_exchange_strong is basically a loop around compare_exchange_weak, so it can result in multiple accesses if the internal compare_exchange_weak fails spuriously.
@Bourg
@Bourg 5 жыл бұрын
The *implementation* can fail spuriously, unbeknownst to you, even if no other code is touching that memory location, leading your program actually touching that volatile atomic more than once. That's not observable for regular atomics, but for volatile? 🤷‍♂️
@IsaacClancy
@IsaacClancy 5 жыл бұрын
He's not saying that compare_exchange_strong can fail spuriously, but that it might be implemented as a loop containing a CPU compare exchange instruction that can fail spuriously.
@ComicSansMS
@ComicSansMS 5 жыл бұрын
Yes, but the underlying hardware might actually only provide spuriously failing compare exchange instructions in which case compare_exchange_strong will be implemented as a spin loop around such an instruction. That's the real issue here: the implementation will have to read the memory location more than once, because that's the only possible implementation on those architectures. Search for load-linked/store-conditional for an example of such an architecture.
@movax20h
@movax20h 4 жыл бұрын
compare_exchange_strong must not fail spuriously from the perspective of the caller. If the platform doesn't support strong compare_exchange in hardware, it will have a tight loop inside to make it succeed, on spurious fails. It doesn't tell you how many times it touches memory, maybe once, maybe 1000 times. Doh, it can probably even acquire some weird global or per-type spinlocks to do it. That is why JF shows on slide volatile compare_exchange_strong, because it is impossible to tell what it does. volatile compare_exchange_weak is easier to agree on and should be consistent with the intuition, but still is not fully specified, because it says "can fail", which means it could spin too really if it wants.
@3zdayz
@3zdayz 8 күн бұрын
Too bad this won't get back to the guy - if you don't know what it does - don't get rid of it. Volatile is only 'read always'. Never cache the result... if you need the values from that area, read them. Because somewhere they might change either hardware signals on a memory mapped device, or other threads that might update the value outside of the current thread. It's just that simple - it's a hint of 'do not cache this value' Now - how do I tell the compiler DO NOT REMOVE THIS CODE? ALWAYS read the mmeory.... voltaile int go = 1; while( !go ) ; // one thread sits here, and since it doesn't change the value - its 'obvious' to the compiler that the value go is a constant, and this gets optimized into a forever loop - or is read once into a register and depending on the state enterying the function controls whether it loops forever, because it doens'[t update. Yes Bit Fields are a compilication - sure deprecate voltailte that includes bit fields.
@unperrier5998
@unperrier5998 Жыл бұрын
The premises of the whole talk is plain wrong. He's taking volatile for what it's not. Garbage in --> garbage out. volatile means don't optimize the code that access this variable, it's for the compiler not for the programmer, to instruct (the compiler) not to make assumptions. Nothing more. But this guy has a different idea of what volatile means. He assumes that volatile specifies how the compiler should (or should not) access the memory, the width of those accesses, etc. With that idea in mind of course his conclusion is that volatile is not fit for purpose. But that conclusion is as wrong as his assumptions. He should not be allowed to talk about C/C++ and spread misconceptions (fake news), and he should even remove the C sticker from his laptop and maybe place a Java sticker instead, or Rust since he's not happy with the C language.
@movax20h
@movax20h 4 жыл бұрын
It is mostly implementation-defined, so compiler is free to actually reject uses it deems not worth accepting. big struct read via volatile? reject. vol+=2? reject. p = vol = x? reject. volatile class with non-trivial members or non-empty base class? reject. Perfectly conforming behavior. Standard suggests to accept such programs, but it is not a must. When you are utilizing implementation-defined behavior you CAN'T relay on portability and must special case for each compiler anyway. It just happens that often you do have some macros, or ways to access implementation defined stuff at compile, but not always. A lot of stuff of implementation defined behavior, is only in a manual, and there is no portable way to find it out at compile time, and sometimes impossible or costly to do at runtime. Failing compilation is fine. One would think, oh, 'sizeof(char)' is implementation-defined, but rejecting it would make compiler useless. But it will be still conforming compiler.
@ArjanvanVught
@ArjanvanVught 4 жыл бұрын
@JF Bastien Deprecating volatile will break all ISR code ........
@Bourg
@Bourg 4 жыл бұрын
Which part of the deprecation explained in the talk is undesirable?
@movax20h
@movax20h 4 жыл бұрын
Nice talk. Happy to see this work accepted into C++. And hope more volatile got removed (deprecated and later made illegal) even more in the future. Honestly the volatile structs/classes/bitfields should be removed. With proper metaprogramming and code generation techniques it can all be done without volatile in the language, any compiler help, and with perfectly defined semantic. For example in D programming language there is no volatile keyword, yet it is pretty easy to do everything that you want to do, including crazy weird things. In the recent versions of D, bitfield structs are basically deprecated, because they can be fully implemented in library (there is implementation in phobos, that does normal stuff). You could easily just take it or write on your own and sparkle there some atomic loads and store, or inline assembly (which is super easy in D).
@3zdayz
@3zdayz 8 күн бұрын
THis is just so wrong - one write to a voltile? No. Every time a write happens a write happens, just as normal, it's not caching the output... though it could if the value has already been written no reason to write it again? That's not really true either - becaseu another thread could change it. Not for locks, not for atomics,.... BGut now, if I want to change my type to 'everything that is this type is volatile' I can't return it - now I have to move the volatile to each and every usage of the type. (100's of thousands! ) Sorry, but this deserves a Whiskey Tango Foxtrot.!?
@jgmccabe
@jgmccabe 3 жыл бұрын
"Standardize better integer types"? You people really need to look at improving numeric type definitions and constraints in line with what has been in Ada for nearly 40 years!
The IMPOSSIBLE Puzzle..
00:55
Stokes Twins
Рет қаралды 194 МЛН
How To Choose Mac N Cheese Date Night.. 🧀
00:58
Jojo Sim
Рет қаралды 107 МЛН
快乐总是短暂的!😂 #搞笑夫妻 #爱美食爱生活 #搞笑达人
00:14
朱大帅and依美姐
Рет қаралды 14 МЛН
CppCon 2019: Jason Turner “The Best Parts of C++"
58:36
CppCon
Рет қаралды 92 М.
Keynote: Optimizing for Change - Ben Deane - CppNorth 2023
1:24:24
A const int is not a constant.
9:16
Jacob Sorber
Рет қаралды 69 М.
The IMPOSSIBLE Puzzle..
00:55
Stokes Twins
Рет қаралды 194 МЛН