14 ms·
C++ Core Coroutines Proposal [pdf]
- jitl 8y agotl;dr
- cjhanks 8y agoThe rapid change in C++ syntax may destabilize it. For example; `auto OpenFile(const string& filename) using future_coroutine<File> [filename]`. Okay, I get it. Or the operator `[<-]`. But as the idioms find their way into production code - an entire important segment of the C++ developer base is going to no longer be capable of reading the language. And that might be worse than not having features.
- snarfy 8y agoThey are adding more syntax to reduce syntax. Have you seen the spaceship operator? C++ has jumped the shark. I just want an ABI. Can we get an ABI already?
- maxxxxx 8y agoYes, an ABI would be great. I am always amazed how easy it is to use libraries in C# or Java whereas C++ is just a PITA.
- pjmlp 8y agoIt is easy as well, when you use a compiler that generates bytecode like C++/CLI.
- aaaaaaaaaab 8y agoUmmmm... Try running java 8 bytecode on an older JVM.
- gpderetta 8y agoThat's possible because all C# and Java compilers only really target a single platform (their respective VM).
- pjmlp 8y agoIt is called COM/UWP on Windows. A C++ ABI requires an OS written in C++, likewise there is no such thing as C ABI per se, rather UNIX ABI, Win32 ABI and so forth.
- eridius 8y agoA C++ ABI does not require an OS written in C++. It just requires all compiler implementations to agree to standardize on a single ABI and enshrine it in a spec that any future implementations must abide by.
- pjmlp 8y agoA C++ compiler that needs to support multiple distinct ABIs? One per each platform, plus an additional one, agreed by all these guys? And the list is not 100% compliant, e.g. TI is missing. https://en.m.wikipedia.org/wiki/List_of_compilers#C++_compilers https://en.m.wikipedia.org/wiki/List_of_compilers#C++_compil... Not even C has managed to do it, what people conventionally refer as C ABI is actually the OS ABI. I still remember having to deal with multiple C ABI on MS-DOS and Windows static libraries.
- gpderetta 8y agoI'm really interested to know how a standard ABI would cover both little endian 32 bit x86 and big endian 64 bit POWER.
- eridius 8y agoCompilers already have ABIs, they're just compiler-specific and not documented. If they didn't have an ABI, then you couldn't link 2 C++ libraries together. In terms of having one spec that handles arbitrary architectures, maybe it could be defined relative to the C ABI? I don't actually know how what the internal ABIs used by the current crop of C++ compilers looks like, so I don't know if they could be expressed relative to the C ABI or not. Alternatively, one could come up with a set of configurable values that define what makes one architecture different from another (such as word size, long/pointer size (if different than word size), endianness, etc). You know, the stuff that the compiler already has to know about in order to compile for an architecture (and I'm pretty sure clang at the least already has a way to even define new target triples in terms of a set of configurable values for this sort of thing). I assume existing compilers don't invent entirely brand new ABIs for each new architecture but instead just adapt an internal standard C++ ABI to the new architecture using a similar process already. The same could be done for a public standard C++ ABI.
- deleted 8y ago[deleted]
- hfdgiutdryg 8y agoPardon the dumb question, but is the term ABI new (or experiencing a recent increase in usage)? I've seen it twice in the last 24 hours, and never before in my life. And that's despite being entirely too familiar with COM.
- Retra 8y agoNo, it is an old term.
- Elv13 8y ago> but is the term ABI new No, it is age old. The thing is that it is only "a thing" to embedded native developers and library authors. The general concept is that the programming language "API" doesn't define how the dll/o/a/la/lib/so/dylib "loader" look for "symbols" in the file. If you example, I do: enum {FOO, BAR}; and next month I change it to enum {BAZ, FOO, BAR}; then everything will still compile, but if I execute an older program with my library, it still thinks FOO is 0 and BAR is 1 while it's no longer the case. It gets worst for function and type definition. Then when you get into C++, it gets an order of magnitude more complex because almost every code change will somewhat break one or many symbols. This is why there is often "proxies" called PIMPL or d_ptr between the library symbols and the actual implementation code. C++ has no officially standardized way to serialize the object to their symbol names. This is often a pain point and Apple wants to fix this for a decade for has so far failed to get everybody to agree on something. For embedded devs, more problem arise from the fact that the instruction set and C library themselves are not the same for all devices and this also break pre-compilled code. Many platform will often favor "static binaries" over dynamic ones to avoid the consequences of breaking the ABI.
- Gibbon1 8y agoI think you see it because there has be a resurgence in interest in C/C++. probably because people are giving up on the idea that all new languages will run on the JVM. ABI is ancient since it defines the underlying structure that allows you to link compiled object files and liberals together (the latter both statically and dynamically). Allowing code generated in one module to successfully call functions in another.
- 01100011 8y agoIf I understand things correctly, the C++ people are attempting to modernize the language and add a bunch of new stuff with the intention of deprecating the old stuff. They're constrained by legacy cruft so the new features end up with rather ugly syntax. I applaud their efforts but frankly I'd rather see a new language done right. I'm currently trying to modernize my C++ skills and while I love some of the new features I think they're creating an inconsistent, ugly, beast of a language.
- wvenable 8y agoC++ will always have a place because it's a language that literally has (or will have) everything. I've used features of C++ that have no analogy in other languages. If I designed a language tomorrow, I wouldn't put that feature in. Too obscure. But I needed this random feature for a project on a constrained device to do C callback trampolines to C++ object methods. When it comes to C++, there is no magic alternative that is "done right". I think that Rust may be the closest C++ alternative that will get in our lifetime and it's syntax isn't exactly non-ugly either.
- mschuetz 8y agoIt has far from "literally" everything. It doesn't have async/await, doesn't have a sane way to create simple web servers, doesn't have map/find/filter/etc on collections, at least not a version that won't span multiple lines or the whole screen because they require mandatory arguments (begin, end) that are useless 99% of the time because you want to operate on the whole collection anyway, etc.
- geezerjay 8y ago> It doesn't have async/await, That's just a C# idiom, and far from being the right or sane way to handle concurrency. Meanwhile C++ has active objects and futures and other concurrency design patterns. > doesn't have a sane way to create simple web servers Check POCO. > doesn't have map/find/filter/etc on collections, at least not a version that won't span multiple lines or the whole screen because they require mandatory arguments (begin, end) that are useless 99% of the time because you want to operate on the whole collection anyway, etc. That's a very silly complaint. You acknowledge that C++ does have map/find/filter (which at this stage is rather obvious to anyone who ever used C++) but somehow you're complaining that C++'s interfaces require programmers to specify where the collections should start and finnish.
- hfdgiutdryg 8y agoI spent a decade watching C++ painfully slowly add more advanced template support and... well, that's about it. After a million iterations of "for (mylisttype::const_iterator i ..." they finally added ranged for loops. The rate of change seems to be increasing. This is initially a bit shocking until I remember that every single job I had was like using a completely different language because, even ten years ago, every shop used a different subset of C++ and STL! Add all you want to the language, it's all going to devolve into code-review infighting the same way it did in 2008.
- pjmlp 8y agoThis is a common complaint about C++, as if the other languages were any better in this regard. Java 11, C# 8, Python 3.7, Fortran 2018, F# 4.5,.... try to write in a way that everyone will agree with, or do language quiz to see what which one gets right. Sure there is C that looks so simple, who gets right all the ISO C changes between C89, C90, C11, C17, UB and compiler specific extensions/issues without having to look into the books?
- eecc 8y agoHah, those code reviews must be fun. At least as much as a Scala one ;)
- gpderetta 8y ago> I spent a decade watching C++ painfully slowly add more advanced template support and... well, that's about it. After a million iterations of "for (mylisttype::const_iterator i ..." they finally added ranged for loops. C++ was first standardized in '98. Nothing happened for more 10 year (in particular no new advanced template support) unless you count the very minor bug fixes in C++03. The next revision, C++11, added ranged for loops.
- hfdgiutdryg 8y agoCompilers don't strictly adhere to standards, and I'm far more concerned with things like whether my compiler crashes, how godawful the error messages are, and whether the bundled STL even functions reliably.
- pcwalton 8y agoIt seems that the main issue that the authors of this proposal have with the current coroutines proposal in the committee is that that proposal effectively requires allocation for all coroutines, while offering promises that the optimizer will be able to avoid the allocation in common cases. This competing proposal makes allocation opt-in for various reasons, not the least of which is skepticism about how well the optimization will perform. (See "Implicit allocation violates the zero-overhead principle" in this document [1]). [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0973r0.pdf http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p097...
- RcouF1uZ4gsC 8y agohttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0981r0.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p098... The people that actually implement coroutines in the compilers actually think that eliding the allocation is very doable.
- pcwalton 8y agoRichard Smith, quoted in the document I linked as saying "I do not have any confidence this optimization would ever become reliable in the way that, say, certain forms of NRVO are," is the code owner of the clang frontend.
- simias 8y agoIt's also true that relying on the compiler to optimize some stuff away (instead of making the overhead explicitly opt-in) is not very C++-ish in nature.
- Chabs 8y agoI'd like to introduce you to the wonderful world of templates.
- bergesenha 8y ago
- 0xFFC 8y agoI don't understand the point of co_*. Why should you have something as ugly as this? Just use std::coroutine?
- palotasb 8y agoThey are supposed to be keywords like return or throw. Those cannot be namespaced either.
- quickben 8y ago[<-] "Our proposed spelling is intended to suggest unwrapping" I'd argue co_unwrap() has spelling that suggests unwrapping.
- dmoreno 8y agoI still have to read it through, but why does it require new syntax and not just new standard library additions like boost::coroutine? I just fell in love with boost::fiber so i hope there will be also something like it in the future std.
- mattbierner 8y agoThis could be completely off-base but: - Clarity and establishing convention. Boost coroutine2 uses a lot of boostyness to make using coroutines in c++ less painful, but they still require boilerplate and can be quite difficult to write. Understanding code that uses coroutine2 also requires understanding how the coroutine2 library works and how it uses normal c++ syntax in unique ways. Having a dedicated operator like [<-] arguably produces more familiar looking and clearer user code. (Take a look at the generator example in the appendix of this proposal; the implementation of the 'generator' type is horrific but the 'Traverse' function is pretty easy to read.) - Generalization. Boost::coroutine2 targets coroutines. This proposal tries to generalize aspects of the coroutines proposal such as the unwrap operator [<-] to support use cases like linear monads.
- kbwt 8y agoAnd yet this proposal still doesn't let you implement zero-overhead objects-as-coroutines. I'd like to be able to create a coroutine that initializes some state ("constructor"), yields back to the caller, and lets you call alternate re-entry points ("member functions") that manipulate the state and yield back, or the final entry point that cleans up the state ("destructor"). If the initialization fails for whatever reason, the yield will simply be skipped. Crucially, I want to be able to do all of this without indirect jumps other than returns.
- AndyKelley 8y agoSerious question, what's the difference between this and a class?
- BeeOnRope 8y agoI guess when you call an entry point the second time it restores the existing context at the point of the previous yield. So you have mix of shared state (class members) and local state between the various entry point. Just a guess though.
- AndyKelley 8y agoIf the local state was accessed across a suspend point that would be undefined behavior. So it would have to be spilled into the coroutine frame. So it would be the same as a class.
- kbwt 8y agoIf you try to implement a class in C, you always end up with duplicated cleanup code between your "constructor" and your "destructor". Being able to jump from the constructor to the corresponding part of the destructor when the construction of a subobject fails would get rid of this often buggy/untested secondary code path. Some idioms have been developed over time, such as first initializing in a failsafe manner all the object's fields to a value that prevents deinitialization, but they add complexity to the code where it is not needed.
- kristiandupont 8y agoIt seems there's a weird fetish in C++ land where non-letter characters seem more "pure" than words. I remember suffering from it myself, implementing atrocities like a subtraction opeartor on a path class which would give you the relative path between two paths. It made me feel very clever but I feel sorry for anyone who would have to look at my code now and try to figure out what the hell was going on.
- Sharlin 8y agoOften the reason is not wanting to introduce new keywords for backwards compatibility reasons. And when keywords are introduced, often they have to be awkward (like `co_await`) to minimize conflicts with existing code. Context-sensitive keywords are one solution but can make parsing even more complicated in places where arbitrary lookahead might be needed.
- stochastic_monk 8y agoThat’s also why the sizeof... operator was chosen. It’s an abuse of notation, because it returns a count of elements rather than the sum of sizeof applied to each, but ... and sizeof were already reserved.
- deleted 8y ago[deleted]
- pjmlp 8y agoC++ land is actually quite conservative. You should try Lisp, ML, Haskell Julia lands regarding that matter. Developers with math background on languages with symbols as identifiers can get quite creative.
- lallysingh 8y agoAt least with Haskell (I can't speak for the others), you don't redefine existing operators, you add new ones. Which is less confusing in some ways
- beojan 8y agoThis doesn't seem to be a coroutines proposal so much as an attempt to sneak (Haskell's) `do` notation into C++. Which I applaud, it's a brilliant feature.
- deleted 8y ago[deleted]
- anqurvanillapy 8y agoBikeshedding alert: If a linear monad use case is considered and a do-notation-like syntax is proposed, why isn’t a left-bind =<< operator introduced by nature.