Closing Channels in UnrealScript

class ChannelClosing extends Object;

struct JobInfo
{
    var int JobId;
    var bool IsValid;
};

var array<JobInfo> JobsChannel;
var bool bDone;

function Main()
{
    local int i;
    local JobInfo Job;

    // Initialize the jobs channel
    JobsChannel.Length = 5;

    // Start the worker thread
    StartWorkerThread();

    // Send 3 jobs to the worker
    for (i = 1; i <= 3; i++)
    {
        Job.JobId = i;
        Job.IsValid = true;
        JobsChannel[JobsChannel.Length] = Job;
        `log("Sent job" @ i);
    }

    // Close the channel by setting all remaining elements to invalid
    for (i = JobsChannel.Length; i < 5; i++)
    {
        Job.IsValid = false;
        JobsChannel[i] = Job;
    }
    `log("Sent all jobs");

    // Wait for the worker to finish
    while (!bDone)
    {
        Sleep(0.1);
    }

    // Try to receive more jobs
    Job = ReceiveJob();
    `log("Received more jobs:" @ Job.IsValid);
}

function StartWorkerThread()
{
    local JobInfo Job;
    local bool bMore;

    // Simulate a separate thread with a loop
    while (true)
    {
        Job = ReceiveJob();
        bMore = Job.IsValid;

        if (bMore)
        {
            `log("Received job" @ Job.JobId);
        }
        else
        {
            `log("Received all jobs");
            bDone = true;
            return;
        }
    }
}

function JobInfo ReceiveJob()
{
    local JobInfo Job;

    if (JobsChannel.Length > 0)
    {
        Job = JobsChannel[0];
        JobsChannel.Remove(0, 1);
    }
    else
    {
        Job.IsValid = false;
    }

    return Job;
}

DefaultProperties
{
    bDone=false
}

In this example, we’re simulating channel behavior and goroutines using UnrealScript’s native features. Here’s a breakdown of the translation:

  1. We define a JobInfo struct to represent jobs, which includes a job ID and a validity flag.

  2. Instead of channels, we use an array JobsChannel to store jobs. The bDone variable is used for synchronization.

  3. The Main() function acts as the entry point, similar to the main() function in the original example.

  4. We simulate sending jobs by adding them to the JobsChannel array.

  5. Channel closing is simulated by setting the IsValid flag to false for remaining elements in the array.

  6. The worker “goroutine” is simulated using the StartWorkerThread() function, which runs in a loop processing jobs.

  7. We use a while loop and Sleep() to wait for the worker to finish, simulating channel synchronization.

  8. The ReceiveJob() function simulates receiving from a channel by removing and returning the first element from the array.

This UnrealScript version maintains the core concepts of the original example, adapting them to fit UnrealScript’s language features and idioms. Note that UnrealScript doesn’t have built-in support for true concurrency or channels, so we’ve simulated these concepts using available language constructs.

To run this code, you would typically include it in an UnrealScript class within an Unreal Engine project. The log statements would output to the Unreal Engine console or log file.