
Coroutines are now in Clang trunk, libc++ - davedx
https://twitter.com/eric01/status/867473461836263424
======
Cieplak
Modern C++ can be very pythonic. Still not as easy as writing Java in IntelliJ
but CLion is becoming quite good (if you succumb to CMake). People write shit
code in every language; C++ has my favorite abstraction to performance ratio.

[http://preshing.com/20141202/cpp-has-become-more-
pythonic](http://preshing.com/20141202/cpp-has-become-more-pythonic)

~~~
oblio
As a non-C++ coder there are two things that "scare" me about C++ (ok, maybe
not scare, but are definitely big turn offs):

\- lack of a proper, cross platform, package manager: I know the history, I
know that C/C++ are basically embedded in the system and they use the system
package manager, but in this age it just doesn't fell right... I've been
spoiled by many years of using Maven and other similar tools

\- template meta-programming plus the C++ legacy features which are probably
lurking in many third-party libraries (simpler languages have fewer features
to abuse and even when for whatever reason you have to use a relatively
subpart third-party library, you know they can't do that much damage)

There's also the compilation speed, but as far as I know there are workarounds
for that.

These things are, if not unsolvable in C++, at least many years away from
being available.

Maybe an experienced C++ coder can destroy my preconceptions :)

~~~
humanrebar
> Maybe an experienced C++ coder can destroy my preconceptions :)

\- Generally C++ uses the OS-level package manager, like rpm or dpkg. It's not
cross-platform and it doesn't have a nice interface in the source code
(#include is... unfortunate), but there is a nice solution here if your
organization has the discipline and tooling expertise to make it work.

\- Template metaprogramming isn't bad to use at all. Everyone uses it every
time they construct a vector<>. It takes a lot of skill to write, though, and
unfortunately even users of TMP can end up with nasty and bloated compiler
errors. _Hopefully_ this will be addressed by "concepts" in forthcoming
versions of C++, but it might be a while before that filters down to stable
C++ compilers and libraries.

\- The real issue that _should_ scare you is something called "undefined
behavior". It's very easy to do subtle things that cause you programs to break
in weird and hard to debug ways. Nasty side effects that could theoretically
include _any_ side effect. Like saving garbage to your production database. By
doing something as innocuous as overrunning an array.

[https://kukuruku.co/post/undefined-behavior-and-fermats-
last...](https://kukuruku.co/post/undefined-behavior-and-fermats-last-
theorem/)

[https://stackoverflow.com/questions/367633/what-are-all-
the-...](https://stackoverflow.com/questions/367633/what-are-all-the-common-
undefined-behaviours-that-a-c-programmer-should-know-a)

There are tricks and tools to avoid undefined behavior, but I find that most
C++ engineering orgs don't prioritize the tooling (linters, UB sanitizers,
etc.) needed to let engineers do this productively. Consequently, a lot of
writing good C++ involves detailed coding standards and/or very detail-
oriented gurus poring over code reviews.

~~~
missblit
And array over-runs are just the beginning! (friends don't let friends use
idices over iterators)

Had a fun bug at work once where we somehow accidentally built against two
subtly incompatible versions of the same library.

This actually mostly worked until some random virtual function call sometimes
called the wrong function silently...

~~~
petters
Yes, C++ without a monorepo is very difficult.

------
nickbauman
This is how I understand the two approaches to concurrency:

1) Use preemptive system threads that can execute in parallel. A task
requiring simultaneous waiting is given an operating system thread of its own
so it can block without stopping the entire program. But threads require
significant memory and other resources per thread. Also, the operating system
can arbitrarily interleave the execution of system threads, requiring the
programmer to carefully protect shared resources with locks and condition
variables, which is exceedingly error-prone.

2) Have a single-threaded program, where that single thread runs an event loop
whose job is to react to external events by invoking a callback function that
has been registered. While it doesn't require the same kind of complex
synchronization that preemptive threads do, the inverted control structure of
this approach requires your own control flow to thread awkwardly through the
system's event loop, leading to a maze of event callbacks.

Coroutines work with the latter style in an attempt to tame its complexity.
They are themselves complex, however, and, in my opinion, that complexity
doesn't pull its weight when you consider in the end you only have one thread.

Can anyone tell me what I'm missing or how these problems with these
approaches have been solved in places?

~~~
strictfp
Or 3) you do like golang and erlang and build really lightweight green threads
so you get the programming model of approach 1 and nearly the same speed as
number 2.

This of course requires extra effort to prevent blocking of OS threads and in
the case where the OS expects thread locality. But IMHO it's the superior
approach.

The best solution would be if OSes themselves would provide really lightweight
threads. And I suspect that they will, eventually.

~~~
nickbauman
I haven't done Erlang, but in my experience Golang has much the same problems
as 1) so I'm not sure I'd agree. +1 to lightweight threads, tho.

~~~
simplify
Phoenix/Elixir can handle 2 million websocket connections on a single box. I
would agree myself :)

[http://www.phoenixframework.org/blog/the-road-
to-2-million-w...](http://www.phoenixframework.org/blog/the-road-to-2-million-
websocket-connections)

~~~
grogenaut
Wouldn't you need something like 40 NICs to do that?

~~~
phamilton
I believe you are referring to running out of ports, as 65k available ports *
40 ~= 2M.

The limitation is actually on a quad tuple: {src_ip, src_port, dest_ip,
dest_port}

As such, the actual limit is outrageously high and isn't really a problem.
Interestingly enough, the referenced Phoenix benchmark overlooked the dest
component and hit a limit as they had only 40 or so machines to use in the
test. Had they used multiple ips on the server it would have given them a lot
more breathing room.

EDIT: Multiple IPs != Multiple NICs. You can assign multiple IPs to a single
physical interface. Also, they could have used multiple ports to accomplish
the same effect.

~~~
grogenaut
Good to know. I thought you were always limited by the outgoing port range to
65k - (used ports) good to know.

So they were limited by the testing cluster or the tested server?

~~~
phamilton
They were limited by the testing cluster, but it was pointed out to them after
the fact that they could have used multiple IPs or multiple ports on the
tested server to go even higher.

------
throwaway-1209
I wish Google would open source / standardize their implementation of green
threads ("fibers" as they're called internally). You basically write linear
programs with those (with proper stack traces etc) and they're cooperatively
concurrent in user space, possibly over a fixed size preemptively concurrent
kernel thread pool. Very nifty and simplifies things a lot. Never seen
anything like it on the outside.

~~~
anon78539737567
I assume that you are trolling. Anyway, be aware that performance of Go
programs are still behind of C++, so it is not a real replacement

~~~
throwaway-1209
I'm not talking about Go. Google fibers are C++.

------
pedrow
Does anyone know, if coroutines are implemented by the compiler, will they
also be available for C? Specifically, I'm thinking about the brilliant Io
language which uses its own cross-platform C coroutine library. If this could
be done 'natively' I wonder if it would simplify the code?

~~~
leeter
They are, however I'm not sure the machinery of a coroutine will translate
well to C. Gor does a pretty good breakdown of what's actually happening in
this video
[https://www.youtube.com/watch?v=8C8NnE1Dg4A](https://www.youtube.com/watch?v=8C8NnE1Dg4A)
which I would suggest watching.

Not sure it can't be done, but it would require a good design. Personally I
think that a libdispatch approach works better for C, particularly with the
blocks extension.

------
iheartmemcache
Some resources for those who aren't too active in keeping up with C++, these
slides are a good quick summary[0]. The talks linked on this page[1] are
particularly good, especially the CppCon16 Gor Nishanov talk[2]. Paulo[3] has
some interesting things to say (though I think some semantics may have changed
since, so grain of salt and all).

[0] [https://www.slideshare.net/SergeyPlatonov/gor-nishanov-c-
cor...](https://www.slideshare.net/SergeyPlatonov/gor-nishanov-c-coroutines-a-
negative-overhead-) Interesting to note, slide #11 uses a tokenizer to
demonstrate the usefulness of coroutines. IIRC, Rob Pike used a very similar
(maybe his was a lexer/parser?) example in '14 re: Go.

[1] [http://luncliff.postach.io/post/exploring-msvc-
coroutine](http://luncliff.postach.io/post/exploring-msvc-coroutine)

[2]
[https://channel9.msdn.com/events/CPP/CppCon-2016/CppCon-2016...](https://channel9.msdn.com/events/CPP/CppCon-2016/CppCon-2016-Gor-
Nishanov-C-Coroutines-Under-the-covers)

[3][https://paoloseverini.wordpress.com/2015/03/06/stackless-
cor...](https://paoloseverini.wordpress.com/2015/03/06/stackless-coroutines-
with-vs2015/)

\--

Side-note : Love it or hate it, the C++ community is certainly moving at a
vibrant pace. I don't write production C++ code anymore (and haven't for a
long time) but I still go out of my way to watch the CppCon talks. IMO, they
consistently produce best quality talks just because you have so many
excellent programmers from various industries using select subsets of C++ in
all sorts of different ways. The people writing games are focused on making
sure they're portable 'enough' to hit all the major platforms, without getting
too tied to platform-specific low-level calls, while retaining the necessary
performance to get satisfactory models/meshes/lighting/collision
detection/raytracing/dozens-of-other-things completed within that tiny 16.33
millisecond gap to complete the framebuffer and swap in the next frame. The
academics who are doing vast numerical computations will be talking about
their new MPI utilizations (and undoubtedly, next years talk will be re: a
boatload of RDMA/NUMA optimizations). People complain that C++ is a mishmash
of too many concepts (pun not intended). I.e., you can write it in the "C with
Objects" style, or the "I use TMP so much my code is basically Haskell", and
anywhere in between - but it's that heterogeneity that ends up yielding such
high caliber talks.

~~~
Cyph0n
> People complain that C++ is a mishmash of too many concepts [...] but it's
> that heterogeneity that ends up yielding such high caliber talks.

I agree. Scala gets the same kind of criticism, but just like with C++, you
can easily limit Scala to whatever subset suits you (e.g., pure OOP or pure
FP). C++ and Scala are among my favorite languages to work with, so I might be
slightly biased :P

~~~
pjmlp
Also if one looks at any successful programming language in the market that
began by fighting complexity, it is easy to observe that they had to
eventually embrace complexity to adapt and survive in the market of
programming languages.

Even if they kept the core simple, the complexity was shovelled into the
libraries instead.

For example, I doubt there is anyone able to know the complete Python 3.6.1
documentation by heart, plus all major libraries, tools and implementations.
Yet it is touted as a simple language.

~~~
w_t_payne
It seems to me that the engineering trade-off is found in how we distribute
complexity between:

(1). The language itself. (2). The tooling (IDE, build system, linters
etc...). (3). The standard library. (4). The ecosystem of third-party
libraries. (5). The developer's application code.

Moving complexity away from (5) might make applications smaller and easier to
maintain, but it is done at the risk of increasing the training / learning
burden on the development team.

If too much complexity ends up in (1), then we create a barrier to entry for
new developers and hiring becomes harder.

If too much complexity ends up in (4), then we end up with endemic not-
invented-here syndrome, because it becomes too hard to learn new libraries.

It seems to me that a lot of this is driven by learning and learnability --
any educational specialists around who want to wade in on this discussion?

~~~
pjmlp
A good example is music.

Yes knowing how to play scales and reading notes might seem easy, but
mastering an instrument and its variations (e.g. string instruments) takes a
whole life.

------
softwarelimits
What would be the best learning path to take for young people wanting to learn
C++ today, especially with a focus on free software? Thanks for your
attention!

~~~
pjmlp
First of all, and most important one, learn C++ idioms, not C.

This means making use of library types for memory allocation, vectors and
strings.

There is a place for old C style low level features, but those should come
later, after the safer concepts are already ingrained.

Kate Gregory's “Stop Teaching C" talk at CppCon 2015 explains better than me.

[https://www.youtube.com/watch?v=YnWhqhNdYyk](https://www.youtube.com/watch?v=YnWhqhNdYyk)

Get a nice IDE, QtCreator, Clion, VC++ Community, KDevelop, XCode.

Besides the "Tour of C++", check Stephan T. Lavavej talks at Channel 9.

"Core C++ Lectures"

[https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-
Lavav...](https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-
Core-C-)

"Advanced STL", these ones only when you already have a good understanding of
STL as user

[https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-
Lavav...](https://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-
Advanced-STL)

Also check video presentations from NDC, ACCU, CppCon, CppNow and C9 Going
Native.

~~~
microcolonel
I agree with you for everything except this one statement:

> First of all, and most important one, learn C++ idioms, not C.

I think it would be better to learn both. C programming really has its place,
and it gives you a model to understand how the sausage is really made. I know
lots of C++ programmers who couldn't even begin to understand how half the
things in their language work, this leads to completely needless performance
loss (like using vectors for statically-sized arrays of data, which I recently
replaced with a C array in a piece of game modelling software for a 20-30%
improvement in runtime).

The fact that you consider this _the most important one_ is outlandish. I
think it's easily more important to teach the tradeoffs and models involved in
things like unique_ptr, rather than creating a cargo cult for abstractions
that turn out to be useless half the time.

C++ programmers really need to learn C, at least after their first year of
blissful ignorance. Don't stop teaching C.

~~~
smelterdemon
>using vectors for statically-sized arrays of data, which I recently replaced
with a C array

See the idea is you can use std::array, so you can use modern idioms (and at()
for bounds checked access).

------
crudbug
I think with all the async / await noise, the simplicity of co-routines is
usually forgotten.

IMHO, they are the right abstraction on top of event-loops. Every major server
platform, especially - JVM, CLR, should support them.

I would be very much interested in context-switch data of server applications
for Threads vs. Coroutines loads.

~~~
tobz
I'd say that this is roughly the case with .NET, in terms of async/await.

IIRC, you're using a thread pool under the hood, and you sort of have to opt-
in: if you're trying to write your own async code, for example, you need to
schedule it in a way that's slightly more complicated than just saying `go
myFunc()`, but it's possible.

As for the JVM, libraries like Akka and Quasar already provide this, although
possibly not as performantly as if the runtime itself provided it?

~~~
int_19h
Strictly speaking, whether you're using the thread pool under the hood or not
depends on the task scheduler, which is pluggable. The default one that new
threads get is indeed going to dispatch to the thread pool (on _different_
threads at that, not the same one). But it can be pretty much anything.
Async/await doesn't really care about any of that, it just creates
continuations for you, and hands them over to the scheduler.

------
dis-sys
Can't wait to see the libc++ coroutines to be declared as production ready.
Now I am wondering whether they will be providing some channel implementation
similar to the one in Golang in the future.

Interesting time for all we C++ fans.

~~~
EricWF
Libc++ coroutines are production ready!

But seriously, the library implementation for coroutines is just a shallow
wrapper around compiler builtins.

Therefore libc++ is probably bug free, but Clang certainly isn't.

EDIT: "probably bug free" == famous last words.

------
nosefouratyou
I found this to be a good article about the importance of coroutines compared
to continuation-passing style: [http://orthecreedence.github.io/cl-
async/2012/11/07/missing-...](http://orthecreedence.github.io/cl-
async/2012/11/07/missing-coroutines-in-common-lisp.html)

------
colejohnson66
At the moment, they are still listed as a WIP[0], but the commit history shows
a lot of effort done recently[1] (Ctrl-F "coroutine")

[0]:
[https://clang.llvm.org/cxx_status.html#ts](https://clang.llvm.org/cxx_status.html#ts)
[1]: [http://lists.llvm.org/pipermail/cfe-commits/Week-of-
Mon-2017...](http://lists.llvm.org/pipermail/cfe-commits/Week-of-
Mon-20170522/thread.html)

~~~
EricWF
The changes literally landed in the past three days; The implementation is
_theoretically_ perfect, but once it's (seriously) observed by users it will
decay into bugs. That's just basic quantum CS. :-)

------
Findeton
Where can I see some examples or documentation on using coroutines in C++?

------
kitd
Simon Tatham can finally breathe easily.

