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.
@sirmoonslosthismind5 жыл бұрын
he doesn't say it's an illogical expectation, only that the standards haven't always guaranteed that expectation.
@movax20h4 жыл бұрын
Love the real time updating on the slide 5 at 1:50 :) ISO 8601 for the win.
@alfred2g5 жыл бұрын
at time 14:34 *vp, it clears the register on some hardware when you just read from it
@Bourg4 жыл бұрын
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 Жыл бұрын
@@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? :)
@DrGreenGiant3 жыл бұрын
Volatile is very useful in embedded debugging, or at least I've found it to be
@kamilziemian995 Жыл бұрын
You have very interesting perspective.
@Elavid2 жыл бұрын
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 Жыл бұрын
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. Жыл бұрын
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-peter19545 жыл бұрын
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
@pazdziochowaty5 жыл бұрын
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
@movax20h4 жыл бұрын
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.
@movax20h4 жыл бұрын
Just implement it on your own using assembler. Easy. It doesn't need to be in the C++ standard.
@Bourg4 жыл бұрын
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.
@josealvim15564 жыл бұрын
the best part of C++ is mutable const
@origamibulldoser1618 Жыл бұрын
No, the best part of C++ is how much we cry and whine about the language, but still don't move on. :D
@WilhelmDrake2 ай бұрын
@@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-v5m7 ай бұрын
There are many frameworks that provides the user with move ops policies to control the relocation for small buffer enhanced containers containers
@lunakid124 ай бұрын
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?)
@AykevanLaethem4 жыл бұрын
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.
@Runoratsu4 жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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.
@josemonge460411 ай бұрын
I also got so annoyed by this talk. Jesus...
@kiroma05 жыл бұрын
9:52, compare_exchange_strong must by standard never fail spuriously, compare_exchange_weak is allowed to.
@robinLambertz5 жыл бұрын
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.
@Bourg5 жыл бұрын
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? 🤷♂️
@IsaacClancy5 жыл бұрын
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.
@ComicSansMS5 жыл бұрын
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.
@movax20h4 жыл бұрын
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.
@3zdayz8 күн бұрын
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 Жыл бұрын
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.
@movax20h4 жыл бұрын
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.
@ArjanvanVught4 жыл бұрын
@JF Bastien Deprecating volatile will break all ISR code ........
@Bourg4 жыл бұрын
Which part of the deprecation explained in the talk is undesirable?
@movax20h4 жыл бұрын
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).
@3zdayz8 күн бұрын
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.!?
@jgmccabe3 жыл бұрын
"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!