
Libmill: Go-Style Concurrency in C - Cieplak
http://libmill.org/index.html
======
kazinator
The macro should be called _select_ , since that's what Go calls it. (Of
course I know there is a POSIX function (not C) by that name; so what).

This "choose {" "end }" business is an awful way to design the macro. If you
need nesting that involves a block, with prolog and epilog material on either
or both ends, you just have to hide that into the macro:

    
    
      selbegin;
    
        out(ch, int, 42):
          foo();
        in(ch, int, i):
          bar(i);
        otherwise:
          baz();
        
      selend;
    

I don't understand the downvotes. I have 30 years of (continous!) C
experience. This is the best practice for doing a macro like this.

This "end }" business has improper nesting, visually. The _choose_ is outside
of the braces, the _end_ is within; it is scatter-brained. There is no error
checking for a forgotten _end_.

I'm looking at the implementation and it's looking quite weird! _choose_
simply expands into _mill_choose_init___ , and _end_ expands into
_mill_choose_end___. The definitions of these seem as if they should pair
together:

    
    
      #define mill_choose_init__ \
          {\
              mill_choose_init_(MILL_HERE_);\
              int mill_idx = -2;\
              while(1) {\
                  if(mill_idx != -2) {\
                      if(0)
    
    
      #define mill_choose_end__ \
                          break;\
                      }\
                  }\
                  mill_idx = mill_choose_wait_();\
              }
    
    

But, oops, look at the obvious lack of balance in the braces.

    
    
       mill_choose_init__ {
    
       mill_choose_end__ }
    

we are putting a brace after the if (0) which balances the one after break,
and the final missing brace that balances the one opened internally in
mill_choose_init__.

There are best practices to design this sort of macrology that don't require
the user put braces in weird places to balance the inconsistencies in macro
expansions.

Speaking as a professional, I would not pass this in a code review.

That we have to use a flaky preprocessor in order to get a half decent syntax
is already a significant regret. We must not compound the regret by allowing
the macrology to be less than as good as it can be.

~~~
microcolonel
It's pretty ludicrous to alias _select_ since it's the sort of thing you're
likely to be calling in a concurrent program.

~~~
kazinator
It's not really the sort of thing you'd use in a modern concurrent program.
There is no reason to use select on a system where you have _poll_. As of
2001, POSIX moved select into its own header, so you shouldn't be getting a
declaration of it any more from <sys/time.h>.

libmill provides some wrapping for polling mechanisms; you'd probably be going
through that in libmill-based sources.

The clash, if it happens, has very easy, localized workarounds.

Note that the library has a macro called _end_ , which is a very common
identifier in programs. Why didn't the author consider that a problem, but
switched Go's _select_ to _choose_?

~~~
legohead
_select_ is super well known in C, as I'm sure you're aware. I have over 20
years in it myself.

sure, workarounds are easy, but that's not the point. your suggestion that it
should be named the same as Go is a bit ridiculous. why is that even
important? what is important is potentially confusing developers, and adding a
new "select" into C would do just that.

the only mistake is Go using the word _select_ to begin with.

~~~
kazinator
_select_ isn't in C; it's in POSIX.

I worked in Windows development shops where nobody knew select; but they could
write WaitForMultipleObjects code in their sleep.

A strictly conforming ISO C program can use the _select_ identifier however it
wants, including as an external name for an object or function.

> _your suggestion that it should be named the same as Go is a bit ridiculous_

It's not any more ridiculous than wanting to have a library which imitates Go
concurrency down to macros that imitate some of the syntax.

~~~
xeeeeeeeeeeenu
>I worked in Windows development shops where nobody knew select; but they
could write WaitForMultipleObjects code in their sleep.

That's hard to believe considering the fact that POSIX-compatible select() is
a part of the winsock API.

------
jwr
This is something that would be extremely useful on microcontrollers, where
you do lots of event-driven programming. Any sane design ends up with a state
machine (or a hierarchy of state machines) driven by events generated in
interrupts.

Coming from Clojure, I wished for something like core.async on
microcontrollers for a long time — a way to convert most of my state machine
into sequential code, with the complexity hidden, all while keeping everything
in C (converted/generated during compile).

~~~
jupp0r
Have you considered C++ coroutines? Imho they struck a really nice tradeoff in
making it a language feature and letting you swap out the underlying
infrastructure.

~~~
creatornator
C++ coroutines, being a feature of C++17/C++20, are not present in most if not
all micro-controller toolchains, so I'm not sure if it would be relevant for
the parent

~~~
jupp0r
What processors are you referring to? Everything ARM is well supported by
LLVM/Clang which implements the coroutines TS.

~~~
creatornator
AVR and PIC? Maybe things have improved since the last time I've explored
compilers alternative to those supplied by manufacturers. But from what I
understand avr-gcc is the standard for avr, and PIC is just targeted by the
manufacturer's compilers.

------
AceJohnny2
There's was an episode of the This Week In Tech podcast from 2015 that
interviewed LibMill's creator about its design concepts:

[https://twit.tv/shows/floss-weekly/episodes/358](https://twit.tv/shows/floss-
weekly/episodes/358)

And HN discussion from 4 years ago:
[https://news.ycombinator.com/item?id=10585505](https://news.ycombinator.com/item?id=10585505)

------
snarfy
It seems like development stopped a few years ago. There were steady releases
almost monthly for a few years and then it just stops in 2017. Did the author
lose interest?

Are there any plans to support multicore? I noticed one of the examples
addresses this by using fork(). Multicore is something goroutines > 1.5
support.

------
coliveira
Isn't this something already provided by libtask? Libtask was written by Russ
Cox.

~~~
Jtsummers
Based on a _very_ cursory check, it seems libtask doesn't do channels. Libmill
does, in the style of Go. So libmill seems to be more a superset of libtask.

~~~
aidenn0
libtask does have channels[1].

libdill (also by the creator of libmill) has some features that libtask does
not.

[edit]

Also one should note that libtask predates Go, and so the API definitely feels
very different. Libmill seems to specifically have a goal of making the usage
feel "go-like"

1: [https://swtch.com/libtask/channel.c](https://swtch.com/libtask/channel.c)

~~~
nicklaf
It's amusing to note that the rewriting of a concurrent language as a C
library has happened before in Bell Lab's history (by some of the same people
who worked on Go and its precursors).

Specifically, the same thing we're talking about here already happened with
Alef[0], a CSP-based language, which was scrapped in favor of a C library[1]
(man 2 thread) in the third edition of the Plan 9 OS[2].

[0]
[http://doc.cat-v.org/plan_9/2nd_edition/papers/alef/](http://doc.cat-v.org/plan_9/2nd_edition/papers/alef/)

[1]
[http://man.cat-v.org/plan_9/2/thread](http://man.cat-v.org/plan_9/2/thread)

[2]
[http://doc.cat-v.org/plan_9/4th_edition/papers/release3](http://doc.cat-v.org/plan_9/4th_edition/papers/release3)

------
azhenley
Is libmill safe with garbage collectors (like Boehm GC)?

------
alexhutcheson
How does this compare to boost:Fiber (other than the obvious "it's in C, not
C++")?

------
gigatexal
I actually really like the syntax for how they're emulating sending and
receiving from channels. I like it better than Go's way of doing this with the
<\- operator.

What would be nice would be a defer function for closing channels and things.

------
abbiya
The out and in functions should be swapped to match the go example?

------
StreamBright
What is Go style in this context? Isn’t it CSP?

------
yandrypozo
who is using libmill by the way? like other open source projects using this
library?

------
jjtheblunt
Go is Go-style concurrency _almost_ in C.

------
oneplane
How come neither libmill nor libdill sites have TLS. It's almost a chore to
set up a site without it nowadays.

