Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Using stages

Jan Stephan edited this page Dec 9, 2016 · 2 revisions

Philosophy

Each GLADOS pipeline is a connection of stages. A single GLADOS stage runs in its own thread and has an I/O interface for communication with other stages. The input side of a single stage can be adressed by multiple predecessors, the output side transfers a data set to exactly one successor stage.

GLADOS stages define a run function which encapsulates the actual implementation for this stage. They make no assumptions about the implementation itself apart from the restrictions which are mentioned below.

Implementation requirements

Implementations are passed to the stage class via template parameters. Each implementation needs to define the following types in its public or protected interface:

  • input_type: The type of the data which is passed to the current stage. Set to void if there is no input_type for the current stage.
  • output_type: The type of the data which is passed to the next stage. Set to void if there is no output_type for the current stage.

Additionally, the following function signatures have to be defined in the public or protected interface for each stage:

  • void set_input_function(std::function<input_type(void)>): This passes an input callback function to the implementation. This callback can then be used to acquire the next element from the stage's input side. If there is no input_type (i.e. input_type is void), this function can be omitted.
  • void set_output_function(std::function<void(output_type)>): This passes an output callback function to the implementation. This callback can then be used to send the currently processed element to the stage's output side. If there is no output_type (i.e. output_type is void), this function can be omitted.
  • void run(): The implementation's entry point. This function must not be omitted. It is guaranteed by GLADOS that set_input_function and set_output_function are called before run.
  • void assign_task(task_type): This function is only necessary if the current stage is part of a task_pipeline and can be omitted otherwise. It passes the current task to the implementation.

Implementation notes

  • If your implementation needs setup parameters you should pass them via the implementation's public constructor. There is no restriction to the parameter types or number passed via the constructor.
  • If your implementation needs runtime parameters which cannot be passed via the constructor you need to define a public function which takes these paremeters.

Examples

Simple stage

An intermediate stage takes data from a predecessor stage, processes the data and then passes it to its successor stage.

#include <cstdint>
#include <functional>
#include <vector>

class some_stage
{
    public:
        using input_type = std::vector<std::uint8_t>;
        using output_type = std::vector<float>;

    public:
        // setup parameters required for the implementation are passed via constructors
        some_stage(std::uint8_t x, std::uint8_t y, std::int32_t v, std::int32_t w);

        auto run() -> void;
        auto set_input_function(std::function<input_type(void)> input) -> void; 
        auto set_output_function(std::function<void(output_type)> output) -> void;

    private:
        // to input data, call 'auto foo = input_()' internally
        std::function<input_type(void)> input_;
        // to output data, call 'output_(foo)' internally
        std::function<void(output_type)> output_;
};

Source stage

Usually the first stage in a pipeline, a source stage loads or generates the data passed into the pipeline. In most cases it does not need an input_type.

#include <functional>
#include <string>
#include <vector>

class source_stage
{
    public:
        // no input_type needed, set it to void
        using input_type = void;
        using output_type = std::vector<float>;

    public:
        // setup parameters required for the implementation are passed via constructors
        source_stage(const std::string& path);

        auto run() -> void;
        auto set_output_function(std::function<void(output_type)> output) -> void;
        // no input_type: omitted set_input_function

    private:
        // to output data, call 'output_(foo)' internally
        std::function<void(output_type)> output_;
};

Sink stage

Usually the last stage in a pipeline, a sink stage saves the processed data. In most cases it does not need an output_type.

#include <functional>
#include <string>
#include <vector>

class sink_stage
{
    public:
        using input_type = std::vector<float>;
        // no output_type needed, set it to void
        using output_type = void;

    public:
        // setup parameters required for the implementation are passed via constructors
        sink_stage(const std::string& dst);

        auto run() -> void;
        auto set_input_function(std::function<input_type(void)> input) -> void;
        // no output_type: omitted set_output_function

    private:
        // to input data, call 'auto foo = input_()' internally
        std::function<input_type(void)> input_;
};