KomponentenThreadChannel::close()

ThreadChannel::close

(PHP 8.6+, True Async 1.0)

php
public ThreadChannel::close(): void

Schließt den Kanal. Nach dem Schließen:

  • Der Aufruf von send() wirft eine ThreadChannelException.
  • Der Aufruf von recv() gibt weiterhin bereits im Puffer vorhandene Werte zurück, bis dieser geleert ist. Sobald der Puffer leer ist, wirft recv() eine ThreadChannelException.
  • Threads, die aktuell in send() oder recv() blockiert sind, werden entsperrt und erhalten eine ThreadChannelException.

Der Aufruf von close() auf einem bereits geschlossenen Kanal ist ein No-op — es wird keine Ausnahme geworfen.

close() ist die Standardmethode, um dem konsumierenden Ende das "Stream-Ende" zu signalisieren. Der Produzent schließt den Kanal, nachdem alle Elemente gesendet wurden; der Konsument liest, bis er ThreadChannelException auffängt.

close() selbst ist thread-sicher und kann von jedem Thread aus aufgerufen werden.

Beispiele

Beispiel #1 Produzent schließt nach dem Senden aller Elemente

php
<?php

use Async\ThreadChannel;
use function Async\spawn;
use function Async\spawn_thread;
use function Async\await;

spawn(function() {
    $channel = new ThreadChannel(10);

    $producer = spawn_thread(function() use ($channel) {
        foreach (['alpha', 'beta', 'gamma'] as $item) {
            $channel->send($item);
        }
        $channel->close(); // signalisiert: keine weiteren Daten
    });

    $consumer = spawn_thread(function() use ($channel) {
        try {
            while (true) {
                echo $channel->recv(), "\n";
            }
        } catch (\Async\ThreadChannelException) {
            echo "Stream beendet\n";
        }
    });

    await($producer);
    await($consumer);
});

Beispiel #2 Close entsperrt einen wartenden Empfänger

php
<?php

use Async\ThreadChannel;
use function Async\spawn;
use function Async\spawn_thread;
use function Async\await;

spawn(function() {
    $channel = new ThreadChannel(); // ungepuffert

    // Dieser Thread blockiert in recv() und wartet auf einen Wert
    $waiter = spawn_thread(function() use ($channel) {
        try {
            $channel->recv(); // blockiert
        } catch (\Async\ThreadChannelException) {
            return "Durch close() entsperrt";
        }
    });

    // Den Kanal aus einem anderen Thread schließen — entsperrt den Wartenden
    spawn_thread(function() use ($channel) {
        $channel->close();
    });

    echo await($waiter), "\n";
});

Beispiel #3 close() zweimal aufzurufen ist sicher

php
<?php

use Async\ThreadChannel;

$channel = new ThreadChannel(5);
$channel->close();
$channel->close(); // No-op, keine Ausnahme wird geworfen

echo $channel->isClosed() ? "geschlossen" : "offen"; // "geschlossen"

Siehe auch