Run user defined tasks to run on their own separate stack with stack switching orchestration.
The library offers the ability for functions to yield control at any point in the jobs execution to be resumed later.
Note: This project is in active development although the core of the functionality is available. This documentation does not yet cover the whole functionality of the system but should provide enough to use the system.
Currently only x86-64 Windows systems are compatible. I aim to support arm in the future.
The project uses cmake build system. CMakeLists.txt is located in the project root.
Dependencies are managed by Microsoft Vcpkg which needs to be available.
Refer to CMakeUserPresets[EXAMPLE].json.
There are two Task types currently implemented.
First we create a function that the simple task will run. A simple task must follow the same function signature:
void SimpleTask(Tasklet* tasklet)
{
// work goes here
std::cout << "Hello" << std::endl;
std::cout << "World" << std::endl;
}A simple task can then be created and run as follows.
// Create Task bound the function TestCreateAndRunTask
StackfullTasks::SimpleTask task(TestCreateAndRunTask);
// Run the Task
task.Run();The output will then give.
Hello
World
As it stands this is an elaborate way to call a function, but the special thing here is that the job executed on it's own stack.
The power becomes more obvious when we use some of the special orchestration functions.
For example, if we add a yield to the SimpleTask function:
void SimpleTask(Tasklet* tasklet)
{
// work goes here
std::cout << "Hello" << std::endl;
tasklet->Yield();
std::cout << "World" << std::endl;
}Then the execution of the job will now stop at tasklet->Yield();.
So now when running the below code we get a different output.
StackfullTasks::SimpleTask task(TestCreateAndRunTask);
task.Run();Now gives the output of:
Hello
But what happened to the rest?
The task is not complete and is now in a SUSPENDED state. See StackfullTasks::Tasklet::GetState to query a task's state.
A SUSPENDED can be resumed by simply running it again.
task.Run();Execution will continue where it yielded and so the output will give:
World
Tasks with complex function signatures are supported via StackfullTasks::Task. This structure is still under development but is functional.
These functions currently support all non-void return types and must use 1 or more additional arguments after StackfullTasks::Tasklet* tasklet.
std::string addStrings(StackfullTasks::Tasklet* tasklet, std::string a, std::string b)
{
std::string c = a + b;
tasklet->Yield();
return c;
}The example function which will add two std::strings, yield, and then when resumed will return the result.
// Create the Task supplying <ReturnType, 1- n Argument types>
StackfullTasks::Task<std::string, std::string, std::string> task(TestTaskWithArgumentsAndReturnFunction);
// Bind the argument values to be passed the job
task.bind("hello","world");
// First run of the task which will run to Yield
task.Run();
// Second run of the task to complete the job
task.Run();
// Retreive result
std::string returnValue = task.GetReturnValue();