Closing Channels in GDScript

In GDScript, we can demonstrate the concept of closing channels using a custom implementation, as GDScript doesn’t have built-in channels. We’ll use a custom Channel class to simulate the behavior.

extends Node

class Channel:
    var queue = []
    var is_closed = false
    var semaphore = Semaphore.new()

    func send(value):
        semaphore.wait()
        if not is_closed:
            queue.append(value)
        semaphore.post()

    func receive():
        semaphore.wait()
        var value = null
        var more = true
        if queue.size() > 0:
            value = queue.pop_front()
        elif is_closed:
            more = false
        semaphore.post()
        return [value, more]

    func close():
        semaphore.wait()
        is_closed = true
        semaphore.post()

func _ready():
    var jobs = Channel.new()
    var done = Channel.new()

    # Worker thread
    var worker_thread = Thread.new()
    worker_thread.start(self, "_worker", [jobs, done])

    # Send jobs
    for j in range(1, 4):
        jobs.send(j)
        print("sent job ", j)
    jobs.close()
    print("sent all jobs")

    # Wait for worker to finish
    done.receive()

    # Try to receive from a closed channel
    var result = jobs.receive()
    print("received more jobs: ", result[1])

    worker_thread.wait_to_finish()

func _worker(userdata):
    var jobs = userdata[0]
    var done = userdata[1]

    while true:
        var result = jobs.receive()
        var j = result[0]
        var more = result[1]
        if more:
            print("received job ", j)
        else:
            print("received all jobs")
            done.send(true)
            return

In this example, we create a custom Channel class to simulate the behavior of channels. The _ready function acts as our main function, where we set up the jobs channel and create a worker thread.

We send three jobs to the worker over the jobs channel, then close it. The worker thread receives jobs until the channel is closed, then notifies completion through the done channel.

After waiting for the worker to finish, we attempt to receive from the closed jobs channel to demonstrate that it returns false for the second value when the channel is closed and empty.

To run this script, save it as a .gd file and attach it to a Node in your Godot scene. The output will be similar to the original example:

sent job 1
sent job 2
sent job 3
sent all jobs
received job 1
received job 2
received job 3
received all jobs
received more jobs: false

Note that GDScript doesn’t have built-in support for channels or goroutines, so we’ve simulated these concepts using threads and a custom Channel class. The overall structure and behavior remain similar to the original example, demonstrating the concept of closing channels in a GDScript context.