Channel (programming): Difference between revisions

Content deleted Content added
 
(30 intermediate revisions by 22 users not shown)
Line 1:
{{About-distinguish|software interprocess communication|Channel (communications)|I/O channel}}
 
In computing, a '''channel''' is a model for [[interprocess communication]] and [[synchronization]] via [[message passing]]. A message may be sent over a channel, and another process or thread is able to receive messages sent over a channel it has a [[reference (computer science)|reference]] to, as a [[stream (computing)|stream]]. Different implementations of channels may be buffered or not, and either synchronous or asynchronous.
 
== {{Proper name|libthread}} channels ==
Channels are fundamental to the [[process calculus]] approach to concurrency, and originated in [[communicating sequential processes]] (CSP), a formal model for concurrency, and has been used in many derived languages, such as [[occam (programming language)|occam]], and [[Limbo programming language]] (via [[Newsqueak]] and the [[Alef programming language]]). They are also used in [[Plan 9 from Bell Labs]]'s libthread, as well as in [[Stackless Python]] and the [[Go programming language]].
The [[Multithreading (computer architecture)|Multithreadingmultithreading]] library, [[libthread]], which was first created for the operating system [[Plan 9 from Bell Labs|Plan 9]], offers inter-thread communication based on fixed-size channels.
 
=== OCaml events= ==
==Channel implementations==
The [[OCaml]] event module offers typed channels for synchronization. When the module's send and receive functions are called, they create corresponding send and receive events which can be synchronized.
 
== Examples ==
Channels modeled after the CSP model are inherently [[Synchronization (computer science)|synchronous]]: a process waiting to receive an object from a channel will [[Blocking (computing)|block]] until the object is sent. This is also called [[rendezvous behaviour]].
Typical supported operations are presented below using the example of the [[libthread]] channel API.
* Channel creation of fixed or variable size, returning a [[reference]] or [[Reference (computer science)|handle]] <source lang="c">Channel* chancreate(int elemsize, int bufsize)</source>
* sending to a channel <source lang="c">int chansend(Channel *c, void *v)</source>
* receiving from a channel <source lang="c">int chanrecv(Channel *c, void *v)</source>
 
===libthread channelsLua Love2D ===
The [[Löve (game engine)|Love2D]] library which uses the [[Lua (programming language)|Lua]] programming language implements channels with push and pop operations similar to stacks. The pop operation will block so as long as there is data resident on the stack. A demand operation is equivalent to pop, except it will block until there is data on the stack<syntaxhighlight lang="lua">
-- A string containing code which will be interpreted by a function such as loadstring(),
-- but on the C side to start a native thread.
 
local threadCode = [[
The [[Multithreading (computer architecture)|Multithreading]] library, [[libthread]], which was first created for the operating system [[Plan 9 from Bell Labs|Plan 9]], offers inter-thread communication based on fixed-size channels.
love.thread.getChannel("test"):push("Hello world!")
]]
 
===OCaml events===
 
function love.load()
The [[OCaml]] event module offers typed channels for synchronization. When the module's send and receive functions are called, they create corresponding send and receive events which can be synchronized.
-- Start the thread.
thread = love.thread.newThread(threadCode)
thread:start()
-- The thread will block until "Hello world!" is popped off channel test's stack.
-- Because the channel can be popped from before the thread first executes, there may not be data on the stack.
-- in that case use :demand() instead of :pop() because :demand() will block until there is data on the stack and then return the data.
print(love.thread.getChannel("test"):demand())
-- The thread can now finish.
end
 
</syntaxhighlight>
== Examples ==
 
=== XMOS XC ===
The [[XMOS]] programming language [[XC (programming language)|XC]] provides a primitive type "chanChan" and two operators "<:" and ":>" for sending and receiving data from a channel.<ref>{{Cite web |url=https://www.xmos.com/node/17653?version=&page=23 |title=XMOS Programming Guide &#124; XMOS |access-date=2015-05-10 |archive-url=https://web.archive.org/web/20160304132653/https://www.xmos.com/node/17653?version=&page=23 |archive-date=2016-03-04 |url-status=dead }}</ref>
 
The [[XMOS]] programming language [[XC (programming language)|XC]] provides a primitive type "chan" and two operators "<:" and ":>" for sending and receiving data from a channel.<ref>https://www.xmos.com/node/17653?version=&page=23</ref>
 
In this example, two hardware threads are started on the XMOS, running the two lines in the "par" block. The first line transmits the number 42 through the channel while the second waits until it is received and sets the value of x. The XC language also allows asynchronous receiving on channels through a select statement.
 
<sourcesyntaxhighlight lang="go">
chan c;
int x;
Line 36 ⟶ 50:
c :> x;
}
</syntaxhighlight>
</source>
 
=== Go ===
This snippet of [[Go (programming language)|Go]] code performs similarly to the XC code. First the channel c is created, then a [[goroutine]] is spawned which sends 42 through the channel. When the number is put in the channel x is set to 42. Go allows channels to buffer contents, as well as non blocking receiving through the use of a select block.<ref>{{Cite web|url=https://golang.org/doc/effective_go.html#channels|title = Effective Go - the Go Programming Language}}</ref>
 
<sourcesyntaxhighlight lang="go">
This snippet of Go code performs similarly to the XC code. First the channel c is created, then a goroutine is spawned which sends 42 through the channel. When the number is put in the channel x is set to 42. Go allows channels to buffer contents, as well as non blocking receiving through the use of a select block.<ref>https://golang.org/doc/effective_go.html#channels</ref>
 
<source lang="go">
c := make(chan int)
 
go func() {c <-+ 42}()
 
x := <- c
</syntaxhighlight>
</source>
 
=== Rust ===
[[Rust (programming language)|Rust]] provides asynchronous channels for communication between threads. Channels allow a unidirectional flow of information between two endpoints: the <code>Sender</code> and the <code>Receiver</code>.<ref>{{cite web |title=Channels - Rust By Example |url=https://doc.rust-lang.org/rust-by-example/std_misc/channels.html |website=doc.rust-lang.org |access-date=28 November 2020}}</ref>
 
<syntaxhighlight lang="rust">
use std::sync::mpsc;
use std::thread;
 
fn main() {
let (tx, rx) = mpsc::channel();
 
thread::spawn(move || {
tx.send(123).unwrap();
});
 
let result = rx.recv();
println!("{:?}", result);
}
</syntaxhighlight>
 
== Applications ==
In addition to their fundamental use for interprocess communication, channels can be used as a primitive to implement various other concurrent programming constructs which can be realized as streams. For example, channels can be used to construct [[futures and promises]], where a future is a one-element channel, and a promise is a process that sends to the channel, fulfilling the future.<ref>"[https://sites.google.com/site/gopatterns/concurrency/futures Futures] {{Webarchive|url=https://web.archive.org/web/20201204060631/https://sites.google.com/site/gopatterns/concurrency/futures |date=2020-12-04 }}", ''[https://sites.google.com/site/gopatterns Go Language Patterns] {{Webarchive|url=https://web.archive.org/web/20201111222255/https://sites.google.com/site/gopatterns |date=2020-11-11 }}''</ref> Similarly, [[iterator]]s can be constructed directly from channels.<ref>"[https://sites.google.com/site/gopatterns/object-oriented/iterators Iterators] {{Webarchive|url=https://web.archive.org/web/20201015115025/https://sites.google.com/site/gopatterns/object-oriented/iterators |date=2020-10-15 }}", ''[https://sites.google.com/site/gopatterns Go Language Patterns] {{Webarchive|url=https://web.archive.org/web/20201111222255/https://sites.google.com/site/gopatterns |date=2020-11-11 }}''</ref>
 
==Channel List of implementations ==
List of non-standard, library-based implementations of channels
 
* For Scala:
** CSO -- Communicating Scala Objects<ref>{{Citation |last=Sufrin |first=Bernard |title=ThreadCSO |date=2021-07-13 |url=https://github.com/sufrin/ThreadCSO/blob/5f8ef6eebdfd8e001e45af18fea52fec36ff7ddd/Lectures/cso-paper.pdf |access-date=2023-02-17}}</ref> is a complete DSL for channel-based communication and concurrency whose semantic primitives are generalizations of the OCCAM primitives. CSO has been used since 2007 in the teaching of concurrent programming, and relevant lectures can be found with the ThreadCSO implementation.<ref>{{Citation |last=Sufrin |first=Bernard |title=ThreadCSO |date=2021-07-13 |url=https://github.com/sufrin/ThreadCSO |access-date=2023-02-17}}</ref>
 
* For C++:
** [[stlab]]<ref>{{cite web|url=https://stlab.cc/libraries/concurrency|title=stlab is the ongoing work of what was Adobe's Software Technology Lab. The Adobe Source Libraries (ASL), Platform Libraries, and new stlab libraries are hosted on github.|date=2021-01-31}}</ref> This implementation supports splits, and different merge and zip operations. Different executors can be attached to the individual nodes.
 
* For Rust:
** [[Tokio (software)|Tokio]]
 
== References ==
Line 59 ⟶ 103:
 
== External links ==
* [httphttps://plan9.bell-labsgithub.com/sourcesbrho/plan9/blob/master/sys/src/libthread/channel.c Libthread Channel Implementation]
* [http://swtch.com/~rsc/thread/ Bell Labs and CSP Threads]
* [http://www.vitanuova.com/inferno/limbo.html Limbo – Inferno Application Programming]
Line 66 ⟶ 110:
 
[[Category:Inter-process communication]]
[[Category:Go (programming language) software]]