Go style Channels for Lua
github.com
github.com
Lua supports cooperative coroutines out of the box, which is great. Unfortunately Lua lacks built-in communication primitives. To fill the void I've implemented Go style channels in pure Lua.
Of course abstract channels without any concurrent IO aren't terribly useful, but fortunately the code is pretty straightforward and adapting it to your event loop shouldn't be a problem.
The code is ~400 lines of code + ~200 of tests.
For example, here's [2] Eratosthenes sieve following Russ Cox explanation [3].
[1] http://lua-users.org/lists/lua-l/2013-08/msg00546.html
[2] https://github.com/majek/lua-channels/blob/master/sieve.lua
Basically channels are yet-another synchronization paradigm like locking or shared memory, some people like it some don't. Channels are an implementation of Hoare's CSP [0].
Channels can be passed around, the same could be said about Lua coroutines. But with channels you get more flexibility:
- you can "block" on many channels at once using the "chanalt" statement. You can "resume" only one lua coroutine at a time.
- channels they can buffer messages (ie: channels can queue several values)
- many coroutines may "send" a value to a channel at the same time, many coroutines may try to "listen" (receive) a value at the same time.
- finally you can pass a channel over a channel
I find channels, as opposed to many other synchronization paradigms, to be composable and generally nice in use.
It's a "better" alternative to synchronization locking and mutable data. But in Lua, of course, there aren't multiple threads so why synchronization is useful? In the same way that coroutines are useful - they allow you to decompose a program into set of smaller programs. The example given by Russ Cox is the Eratosthenes sieve. You can read about it [1] or watch him talking about it [2], finally my implementation following his talk [3].
[0] https://en.wikipedia.org/wiki/Communicating_sequential_proce...
[1] http://swtch.com/~rsc/thread/
[2] http://www.youtube.com/watch?feature=player_detailpage&v=hB0...
[3] https://github.com/majek/lua-channels/blob/master/sieve.lua
- time ordering (in both, the send "happens before" the receive, and the next line in the sender "happens after" the receive)
- communication
- pipelined architecture
but not these:
- the runtime chooses a goroutine that can proceed and schedules it, you don't need to fear blocking, producers can make headway while consumers are waiting, and you don't need to manually arrange multi-goroutine control flow into some sort of pass-the-buck loop.
- nonblocking sends allow a variation of the time ordering (the send "happens before" the receive, but the next line in the sender is not coordinated with the receiver, it may happen immediately)
- decoupling sender and recipient: the recipient goroutine doesn't need to know which goroutine to resume such that the sender can pick up where it left off
- ability to choose which channel you'll communicate down,
--- simultaneously, whichever is ready (listen for "shutdown", "timeout" and "data", for example) and with a default that can be used for the non-blocking alternative
--- at different times in one goroutine (read "producer" then write "consumer" then read "status" then write "confirmation", for example - you can do this in stock Lua but the coupling would be awful)
Go provides microthreads, which are both concurrent and parallel, and extremely lightweight.
Libtask provides concurrency. It does not provide parallelism. Parallelism is important.
No. I just implement libtask/channel.c in Lua.
It does not provide parallelism. Parallelism is important.
I'm doing it in pure Lua. Lua doesn't use multiple OS threads. Doing channels _across_ Lua contexts would be an interesting thing.
Lua doesn't use multiple OS threads.
I didn't know that. That's really disappointing. Parallelism really is important. It sounds like it's possible, just really awkward: http://kotisivu.dnainternet.net/askok/bin/lanes/
Kudos on making a nice CSP library for Lua though. In my opinion, CSP is a good paradigm for high-level concurrent and parallel processing. Hopefully one day Lua will add reasonable parallelism.
Could this be possible?
sorry I know this is out side the scope of this project.
Maybe it's just a wrapper? I don't understand the reasoning for this.
[0] with a twist, the default size is 0 meaning unbuffered: items can't be stored in the queue, so a PUT will block until a GET is performed