Kanał (programowanie) - Channel (programming)
W informatyce kanał jest modelem komunikacji międzyprocesowej i synchronizacji poprzez przekazywanie komunikatów . Wiadomość może zostać wysłana kanałem, a inny proces lub wątek może odbierać wiadomości wysłane przez kanał, do którego się odwołuje , jako strumień . Różne implementacje kanałów mogą być buforowane lub nie, synchroniczne lub asynchroniczne.
Kanały mają fundamentalne znaczenie dla podejścia rachunku procesów do współbieżności i pochodzą z komunikowania procesów sekwencyjnych (CSP), formalnego modelu współbieżności, i są używane w wielu językach pochodnych, takich jak occam i język programowania Limbo (poprzez Newsqueak i Alef język programowania ). Są one również używane w Planie 9 z wątku libthread Bell Labs , a także w Stackless Python i języku programowania Go .
Wdrożenia kanałowe
Kanały modelowane na podstawie modelu CSP są z natury synchroniczne : proces oczekujący na odebranie obiektu z kanału będzie blokowany do momentu wysłania obiektu. Nazywa się to również zachowaniem rendezvous . Typowe obsługiwane operacje są przedstawione poniżej na przykładzie kanału API libthread .
- Tworzenie kanału o stałym lub zmiennym rozmiarze, zwracanie referencji lub uchwytu
Channel* chancreate(int elemsize, int bufsize)
- wysyłanie na kanał
int chansend(Channel *c, void *v)
- odbieranie z kanału
int chanrecv(Channel *c, void *v)
kanały libthread
Wielowątkowość biblioteka libthread , który został stworzony dla systemu operacyjnego Plan 9 , oferty komunikacji między gwintem na podstawie kanałów o stałym rozmiarze.
Wydarzenia OCaml
W SML oferty Moduł zdarzeń wpisane kanały synchronizacji. Kiedy funkcje wysyłania i odbierania modułu są wywoływane, tworzą one odpowiednie zdarzenia wysyłania i odbierania, które mogą być synchronizowane.
Przykłady
Lua Love2D
Love2D biblioteka, która jest częścią Lua narzędziach język programowania kanałów push i pop operacji podobnych do stosów. Operacja pop będzie blokowana, o ile na stosie znajdują się dane. Operacja żądania jest równoważna operacji pop, z wyjątkiem tego, że będzie blokować, dopóki na stosie nie pojawią się dane
-- A string containing code which will be intereprted by a function such as loadstring(),
-- but on the C side to start a native thread.
local threadCode = [[
love.thread.getChannel("test"):push("Hello world!")
]]
function love.load()
-- 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
XMOS XC
Język programowania XMOS XC zapewnia prymitywny typ „chan” i dwa operatory „<:” i „:>” do wysyłania i odbierania danych z kanału.
W tym przykładzie dwa wątki sprzętowe są uruchamiane na XMOS, uruchamiając dwie linie w bloku "par". Pierwsza linia przesyła liczbę 42 przez kanał, podczas gdy druga czeka na jej odebranie i ustawia wartość x. Język XC umożliwia również asynchroniczne odbieranie na kanałach za pomocą instrukcji select.
chan c;
int x;
par {
c <: 42;
c :> x;
}
Udać się
Ten fragment kodu Go działa podobnie do kodu XC. Najpierw tworzony jest kanał c, a następnie odradzana jest gorutyna, która wysyła 42 przez kanał. Gdy numer jest wstawiony do kanału x jest ustawiony na 42. Go pozwala kanałom na buforowanie zawartości, a także na nieblokujące odbieranie poprzez użycie bloku wyboru.
c := make(chan int)
go func() {c <- 42}()
x := <- c
Rdza
Rust zapewnia asynchroniczne kanały komunikacji między wątkami. Kanały umożliwiają jednokierunkowy przepływ informacji między dwoma punktami końcowymi: Senderi Receiver.
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);
}
Aplikacje
Oprócz ich fundamentalnego zastosowania do komunikacji międzyprocesowej, kanały mogą być używane jako prymityw do implementacji różnych innych współbieżnych konstrukcji programistycznych, które mogą być realizowane jako strumienie. Na przykład, kanały mogą służyć do konstruowania kontraktów futures i obietnic , gdzie przyszłość jest kanałem jednoelementowym, a obietnica to proces, który wysyła do kanału, spełniając przyszłość. Podobnie iteratory można konstruować bezpośrednio z kanałów.
Lista wdrożeń
Lista niestandardowych, opartych na bibliotekach implementacji kanałów
- Dla C++:
- stlab Ta implementacja obsługuje podziały i różne operacje scalania i zip. Do poszczególnych węzłów można podłączyć różne executory.