[HN Gopher] libmill - Go-style concurrency in C
       ___________________________________________________________________
        
       libmill - Go-style concurrency in C
        
       Author : graderjs
       Score  : 139 points
       Date   : 2022-03-16 15:16 UTC (7 hours ago)
        
 (HTM) web link (libmill.org)
 (TXT) w3m dump (libmill.org)
        
       | MisterTea wrote:
       | Prior art:
       | 
       | http://man.postnix.pw/plan_9/2/thread (Plan 9's thread(2).
       | Personal note: I absolutely LOVE working with this library)
       | 
       | https://swtch.com/libtask/ (Rus Cox's portable library (Someone
       | on the 9fans mailing list ported it to a micro-controller))
       | 
       | See Also:
       | 
       | https://seh.dev/go-legacy/ (A nice code tour of the historical
       | CSP lineage of Go)
       | 
       | https://swtch.com/~rsc/thread/ (Bell Labs and CSP Threads)
        
         | s-video wrote:
         | >Someone on the 9fans mailing list ported it to a micro-
         | controller
         | 
         | Do you have a link to this?
        
           | bakul wrote:
           | Probably this one: https://9fans.topicbox.com/groups/9fans/Te
           | f717f57ede82d4f-M5...
        
         | ck45 wrote:
         | libthread is great, although I somehow wish that the
         | programming language Alef won in some alternate universe.
         | 
         | libthread was written as a replacement when Alef was abandoned
         | in Plan 9 3rd edition
        
         | bakul wrote:
         | libthread is available as part of plan9port on Unix systems.
        
       | jjtheblunt wrote:
       | why not just use Go, since it's a modern day lovechild of C and
       | Scheme, with a very smart compiler?
        
         | jayar95 wrote:
         | There's a lot of C out there homie
        
       | didip wrote:
       | @dang needs to bust out his prior submission script here. libmill
       | and libdill has been posted a lot on Hacker News.
        
         | Jtsummers wrote:
         | Only two with significant comments:
         | 
         | May 10, 2019 - https://news.ycombinator.com/item?id=19879679
         | (76 comments)
         | 
         | Nov 18, 2015 - https://news.ycombinator.com/item?id=10585505
         | (83 comments)
        
         | heinrichhartman wrote:
         | Here is the full list:
         | 
         | https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
        
         | hu3 wrote:
         | Previous post was 10 months ago?
         | 
         | https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...
        
       | moltke wrote:
       | Without go's nested functions and variable capture it's really
       | not the same. The best use for channels in go (IMO) is to use
       | variable scope checking to keep people new to the codebase from
       | messing with resources outside of the right threads. You put all
       | the critical code in a nested function and pass it over the
       | channel, viola the compiler helps make sure your program is
       | correct.
        
       | [deleted]
        
       | Shadonototra wrote:
       | That is why i love C, you can model it to do whatever you want,
       | it truly empowers you to program your PC
        
         | Findecanor wrote:
         | It isn't pure C. It uses x86-64 assembly language to save
         | register context.
         | 
         | It falls back to setjmp()/longjmp() when its not x86-64, but
         | (contrary to popular belief) those don't actually save all the
         | registers, and longjmp() will on some platforms terminate the
         | program if it detects it being abused in this way.
        
         | pjmlp wrote:
         | Same could have been done in Modula-2 or Object Pascal, to name
         | just two among many, including the Assembly and setjmp/longjmp
         | parts.
        
       | ibraheemdev wrote:
       | The follow up to this library was libdill, the library that I
       | believe originally introduced structured concurrency:
       | http://libdill.org/structured-concurrency.html
        
         | synergy20 wrote:
         | "Technically, these are the differences: Libdill is idiomatic
         | C. Whereas libmill takes Go's concurrency API and implements it
         | in an almost identical manner in C, libdill tries to provide
         | the same functionality via a more C-like and POSIX-like API."
        
       | marcofiset wrote:
       | Why not call this for what it is? It's CSP in C. Go is not the
       | only language in which CSP is used as the concurrency model.
       | 
       | I understand using "Go-style" as an adjective to describe this
       | makes it easier for the uninitiated but it's doing everyone a
       | disservice IMHO.
        
         | intrepidhero wrote:
         | I'm very much a novice in concurrent programming so I looked
         | that up:
         | https://en.wikipedia.org/wiki/Communicating_sequential_proce...
         | 
         | > ...communicating sequential processes (CSP) is a formal
         | language for describing patterns of interaction in concurrent
         | systems. > ... based on message passing via channels.
         | 
         | That seems like a mathematical language that could describe
         | goroutines and channels but also seems like it could describe
         | python's multiprocessing and queue constructs. I think of those
         | as very different things given the (vastly different)
         | applications. When I think of "go-style" I think of lightweight
         | threads (I can have 1000s), where as python processes are heavy
         | (100 is pushing it?). So maybe the specifics of the
         | implementation have as much to do with the go-style as the
         | abstract concept?
         | 
         | My understanding here is fuzzy for sure and I welcome
         | corrections and more detail.
        
           | jlokier wrote:
           | There are no queues in CSP, although you can make one by
           | making a queue process.
           | 
           | In CSP, the sending side of a message is always logically
           | simultaneous with the receiving side. So it's like Go's
           | default channels where the sender and receiver both block
           | until ready to transfer, and different from Python's
           | multiprocessing and queue constructs, where the sender
           | doesn't block.
           | 
           | CSP was used in Occam1 on Transputers2 in the 1980s. In
           | Occam, it was normal to have a large number of tiny
           | processes, some of them maybe only a few instructions (such
           | as an implementation of a queue), and the thread switching
           | and communication primitives were actual CPU instructions.
           | The CPUs were joined with dedicated message communication
           | links into large meshes, providing hardware parallelism with
           | a very different model than today's SMP multi-core. A similar
           | architecture exists today, XMOS3.
           | 
           | Go implements a model similar to CSP on today's SMP multi-
           | core systems and OSes, emphasising many efficient, small
           | threads running loops that communicate synchronously.
           | Channels are unbuffered by default, making them like CSP.
           | They can be made buffered, which adds a queue, as if a CSP
           | queue process was added. Go is much less rigid than Occam,
           | because you can also make new channels and spawn new threads
           | efficiently, which are essential features in modern sofware.
           | 
           | Python multiprocessing doesn't provide efficient, small
           | threads. You need larger thread units to get good performance
           | out of it. It also emphasises queuing. So it's quite
           | different from CSP.
           | 
           | Erlang implements a model like Occam and Go of many,
           | efficient, small threads, but the messaging is always
           | asynchronous. The communication is similar to Go with
           | buffered channels.
           | 
           | 1 https://en.wikipedia.org/wiki/Occam_(programming_language)
           | 2 https://en.wikipedia.org/wiki/Transputer 3
           | https://en.wikipedia.org/wiki/XMOS
        
         | zucker42 wrote:
         | Looks like it is "go-style" because the API/syntax is modelled
         | after the go API. In particular the "choose" macro from the
         | example looks to be designed to mimic "select" even though
         | otherwise macros might be dispreferred.
         | 
         | There's another library linked that has similar functionality
         | with a less go-like API.
         | 
         | Just a guess.
        
           | yakubin wrote:
           | I think Concurrent ML (1991) had select before Go. Go itself
           | took it from Newsqueak (1994) and Limbo (1995) I think. The
           | name itself probably comes from the UNIX select(2) syscall,
           | which first appeared in 4.2BSD (1983).
        
           | stingraycharles wrote:
           | As someone who worked with a decent variety of languages that
           | all claim their fame to CSP (Erlang, Clojure and Go), suffice
           | to say that these all look very similar. It's the tooling
           | _around_ the CSP where the real differences are.
        
             | [deleted]
        
             | gpderetta wrote:
             | Isn't erlang closer to actors than CSP? I.e. no rendez-
             | vous.
             | 
             | Edit: this has been better discussed elsethread.
        
         | aidenn0 wrote:
         | Libdill[1] is the structured concurrency (i.e. CSP) library by
         | this author. Libmill is specifically trying to look as much
         | like Go as possible.
         | 
         | 1: http://libdill.org/
        
         | [deleted]
        
         | adrusi wrote:
         | Well it's specifically CSP using cooperative multitasking
         | (sadly no multithreading support unlike go) and a go-like API.
         | CSP is a lot less specific than that.
        
         | mmcgaha wrote:
         | I think because many people's first exposure to CSP was in go,
         | go-style-concurrency has become the crescent wrench of CSP.
        
         | freedomben wrote:
         | Interesting, I didn't realize CSP was so specific.
         | 
         | I heard someone say that Erlang's model was CSP too. They
         | aren't called "channels" but they're very similar in that you
         | have two different process/threads that are reading/writing
         | to/from an ordered stream that feels the same as
         | reading/writing to/from a Go channel.
         | 
         | What would Erlang's model be called? Does "the Actor Model"
         | cover it?
        
           | Jtsummers wrote:
           | Yes, Erlang is based more on the actor model.
           | 
           | CSP is synchronous, so sending to a channel will block if the
           | receiver isn't ready. Erlang and actors are asynchronous in
           | this matter. They will send regardless of whether the
           | receiver is in a state where it can receive the message.
           | Practically, Go (and libmill) allow buffered channels so that
           | you only block if the channel's buffer is full.
           | 
           | CSP is based on anonymous processes. Actors have identity,
           | and this would be the process IDs in Erlang. Erlang and the
           | actor model don't use channels (though you can use processes
           | to mimic them).
        
             | freedomben wrote:
             | Nice, thanks that makes a lot of sense and definitely an
             | important difference.
        
             | masklinn wrote:
             | > Practically, Go (and libmill) allow buffered channels so
             | that you only block if the channel's buffer is full.
             | 
             | Go also allows rendezvous channel (channels with an empty
             | buffer, so either side can only proceed when the other
             | arrives: the actual message exchange is synchronous).
        
       | qbasic_forever wrote:
       | This looks great! A port to microcontroller platforms like
       | Arduino would be really slick IMHO.
        
         | pjmlp wrote:
         | Or given that Arduino uses C++, just use co-routines instead.
        
       | ta-nehdjebdh wrote:
       | Also possibly of interest here:
       | https://github.com/wingo/fibers/wiki/Manual
        
       ___________________________________________________________________
       (page generated 2022-03-16 23:01 UTC)