Select in GDScript

The select statement in GDScript allows you to wait on multiple channel operations. Combining threads and channels with select is a powerful feature of GDScript.

extends Node

func _ready():
    # For our example we'll select across two channels.
    var c1 = Channel.new()
    var c2 = Channel.new()

    # Each channel will receive a value after some amount
    # of time, to simulate e.g. blocking RPC operations
    # executing in concurrent threads.
    Thread.new().start(func():
        OS.delay_msec(1000)
        c1.put("one")
    )
    Thread.new().start(func():
        OS.delay_msec(2000)
        c2.put("two")
    )

    # We'll use select to await both of these values
    # simultaneously, printing each one as it arrives.
    for i in range(2):
        var result = yield(select([c1, c2]), "completed")
        match result:
            [0, var msg]:
                print("received ", msg)
            [1, var msg]:
                print("received ", msg)

func select(channels):
    var select_array = []
    for channel in channels:
        select_array.append(channel.get())
    return yield(GDScriptFunctionState.new().idle_frame, "completed")

class Channel:
    var queue = []
    var mutex = Mutex.new()
    var semaphore = Semaphore.new()

    func put(value):
        mutex.lock()
        queue.append(value)
        mutex.unlock()
        semaphore.post()

    func get():
        semaphore.wait()
        mutex.lock()
        var result = queue.pop_front()
        mutex.unlock()
        return result

We receive the values “one” and then “two” as expected.

$ godot -s select.gd
received one
received two

Note that the total execution time is only ~2 seconds since both the 1 and 2 second delays execute concurrently.

In this GDScript version:

  1. We use Thread to simulate goroutines.
  2. We implement a simple Channel class to mimic Go’s channels.
  3. We create a custom select function that uses yield to wait for the first channel to receive a value.
  4. Instead of time.Sleep, we use OS.delay_msec for delays.
  5. We use a match statement (similar to Go’s switch) to handle different channel cases.

This implementation provides similar functionality to the original Go code, allowing for concurrent operations and selecting from multiple channels.

查看推荐产品