Cosmos.Coroutines 1.0.1

dotnet add package Cosmos.Coroutines --version 1.0.1
NuGet\Install-Package Cosmos.Coroutines -Version 1.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cosmos.Coroutines" Version="1.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Cosmos.Coroutines --version 1.0.1
#r "nuget: Cosmos.Coroutines, 1.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Cosmos.Coroutines as a Cake Addin
#addin nuget:?package=Cosmos.Coroutines&version=1.0.1

// Install Cosmos.Coroutines as a Cake Tool
#tool nuget:?package=Cosmos.Coroutines&version=1.0.1

cosmos-coroutines

A simple, non-preemptive coroutine scheduler that allows for cooperative multitasking within Cosmos kernels.

This project was created to demonstrate the ability to use C#'s iterator support to achieve cooperative multitasking.

Limitations

Cosmos.Coroutines has the following limitations:

  • non-preemptive; you need to do a yield return to hand back control to the coroutine scheduler
  • basic round-robin; no priority system
  • CPU halting - which occurs in many parts of Cosmos - will also halt the coroutine pool scheduler

Other than the caveats mentioned above, the coroutine system can act like a cooperative kernel task scheduler.

Installing

Cosmos.Coroutines is available on NuGet; either use the NuGet package manager in your IDE of choice, or, in a package manager terminal, type in:

NuGet\Install-Package Cosmos.Coroutines -Version 1.0.0

Usage

The following classes are included in the Cosmos.System.Coroutines namespace:

  • Coroutine - represents a coroutine, which can belong to only one CoroutinePool.
  • CoroutinePool - manages multiple coroutines. A global CoroutinePool is allocated on startup and can be accessed using CoroutinePool.Main. This pool will not affect the execution of the OS in any way until the StartPool instance method is called.
  • CoroutineControlPoint - an object returned by valid coroutine implementations of the IEnumerator interface, and accepted by the Coroutine constructor. Specifies whether the coroutine should be ticked at a given time.
  • WaitFor - a CoroutineControlPoint that waits for the specified amount of nanoseconds.
  • WaitUntil - a CoroutineControlPoint that waits until a given condition is met.
  • WaitIndefinetly - a CoroutineControlPoint that halts the coroutine until it's explicitly un-halted through said control point.

To use the main CoroutinePool, simply do:

CoroutinePool.Main.StartPool();

To create a coroutine:

var coroutine = new Coroutine(MyCoroutine1());
coroutine.Start(); // will run the coroutine on the main pool; to run it in another, use CoroutinePool.AddCoroutine

// ...

IEnumerator<CoroutineControlPoint> MyCoroutine1()
{
    while(true) {
        Console.WriteLine("This prints every second.");
        yield return WaitFor.Seconds(1);
    }
}

You can start as many coroutines as you want, however, please note that with more coroutines, the slower the operating system gets.

Warning<br> A coroutine is not the same as a traditional C# thread, and you should not mistake the two. A C# thread is preempted; that is, if the thread encounters, for example, an infinite loop, the kernel will still continue to execute, as the thread will be automatically switched from (preempted) after a time quantum. A coroutine relies on the method to voluntarily give back control to the pool; if a software bug appears that would make the coroutine refrain from giving back control to the pool, the kernel would halt.

Creating a "main" function

After performing a cycle over all coroutines, you may want to execute kernel code, to perform e.g. maintanance tasks. This can be easily achieved using the CoroutinePool.OnCoroutineCycle event:

CoroutinePool.Main.OnCoroutineCycle += Main;
CoroutinePool.Main.StartPool();

// ...

void Main() {
    // everything in this method will be executed after a pool cycle
}

As this is a regular C# event, you can have as many handlers as you want.

Coroutines and memory management

CoroutinePools can be set to automatically collect all unused objects on the heap after the executor finishes a cycle - that is, when all coroutines in its internal list have been ticked. This is enabled by default for the main pool, but disabled for user-created pools. It's strongly recommended to enable periodic heap collection if you're running the pool on your main thread (as is most likely the case with Cosmos).

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.1 271 9/7/2023
1.0.0 296 1/5/2023