photon

Photon is a lightweight transparent fiber scheduler. It's inspired by Golang's green thread model and the spawn function is called go doing the same job that Golang's keyword does. The framework API surface is kept to a minimum, many programs can be written using only three primitives: startloop to initialize Photon, runFibers to start fiber scheduler and go to create tasks, including the initial tasks.

Discussion

Example, showcasing channels and std.range interop:

  1. /+ dub.json: { "authors": [ "Dmitry Olshansky" ], "copyright": "Copyright © 2024, Dmitry Olshansky", "dependencies": { "photon": { "path": ".." } }, "description": "A test for channels API", "license": "BOOST", "name": "channels" } / module examples.channels; import std.algorithm, std.datetime, std.range, std.stdio; import photon; void first(shared Channel!string work, shared Channel!int completion) { delay(2.msecs); work.put("first #1"); delay(2.msecs); work.put("first #2"); delay(2.msecs); work.put("first #3"); completion.put(1); } void second(shared Channel!string work, shared Channel!int completion) { delay(3.msecs); work.put("second #1"); delay(3.msecs); work.put("second #2"); completion.put(2); } void main() { startloop(); auto jobQueue = channel!string(2); auto finishQueue = channel!int(1); go({ first(jobQueue, finishQueue); }); go({ // producer # 2 second(jobQueue, finishQueue); }); go({ // consumer foreach (item; jobQueue) { delay(1.seconds); writeln(item); } }); go({ // closer auto completions = finishQueue.take(2).array; assert(completions.length == 2); jobQueue.close(); // all producers are done }); runFibers(); }

  • Declaration

    void startloop();

    Initialize event loop and internal data structures for Photon scheduler.

  • go

    Declaration

    void go(void delegate() func);
    void go(void function() func);

    Setup a fiber task to run on the Photon scheduler.

  • Declaration

    void runFibers();

    Start sheduler and run fibers until all are terminated.

  • Declaration

    struct Channel(T);

    A ref-counted channel that is safe to share between multiple fibers. In essence it's a multiple producer single consumer queue, that implements OutputRange and InputRange concepts.

    • put

      Declaration

      void put(T value);

      OutputRange contract - puts a new item into the channel.

    • Declaration

      bool empty();

      Part of InputRange contract - checks if there is an item in the queue. Returns true if channel is closed and its buffer is exhausted.

    • Declaration

      ref T front();

      Part of InputRange contract - returns an item available in the channel.

    • Declaration

      void popFront();

      Part of InputRange contract - advances range forward.

  • Declaration

    auto channel(T)(size_t capacity = 1);

    Create a new shared Channel with given capacity.

  • Declaration

    void select(Args...)(auto ref Args args) if (allSatisfy!(isChannel, Even!Args) && allSatisfy!(isHandler, Odd!Args));

    Multiplex between multiple channels, executes a lambda attached to the first channel that becomes ready to read.

  • Declaration

    enum auto isChannel(T);

    Trait for testing if a type is Channel