Jobs Manual

About

A job is a threaded, reusable, independent work item (task). It can be queued to be executed with other jobs in a (parallel) pipeline.

Job

A custom job is based on maxon::JobInterfaceTemplate, maxon::JobResultInterface and maxon::JobInterface. The custom class contains data and implements the function call operator with the actual workload. A job instance is based on maxon::JobRef.

Warning
Make sure that a job has no additional, hidden dependencies like for example executing parallelized code internally.
// This example shows a job that returns a value.
// FactorialJob calculates the factorial of the given number.
class FactorialJob : public maxon::JobInterfaceTemplate<FactorialJob, maxon::UInt>
{
public:
FactorialJob() { };
MAXON_IMPLICIT FactorialJob(maxon::UInt n)
{
_n = n;
}
// function operator with the actual workload
maxon::Result<void> operator ()()
{
// 0! and 1! are 1
maxon::UInt factorial = 1;
if (MAXON_LIKELY(_n > 1))
{
factorial = _n;
while (_n > 1)
{
--_n;
factorial *= _n;
}
}
// store result
return SetResult(std::move(factorial));
}
private:
maxon::UInt _n = 0;
};

A job can also implement:

A job has to be enqueued in a queue to be executed (see job queue below):

// This example creates and starts a job that will return a result value.
// create and start job
const maxon::UInt n = 10;
auto job = FactorialJob::Create(n) iferr_return;
job.Enqueue(); // enqueue the job in the current queue and start
// wait and get result
const maxon::UInt factorial = job.GetResult() iferr_return;
DiagnosticOutput("@! = @", n, factorial);

A running job can be cancelled:

// This example cancels the given job and waits for it to finish.
// cancel the given job
job.CancelAndWait();

These observers can be used to react to certain events:

Further utility function are:

Static utility functions are:

Job Group

Jobs can be organized in job groups. These groups are used to execute and wait for multiple jobs simultaneously. The jobs of a group typically belong together. The jobs are executed as efficiently as possible.

The maxon::JobGroupRef members are:

// This example creates a new job group and adds lambda functions to it.
// create group
for (const maxon::Url& file : files)
{
// add lambda function
group.Add(
[file]()
{
CreateFileHash(file) iferr_ignore("Lambda can't handle errors."_s);
}
// enqueue jobs and wait
group.Enqueue();
group.Wait();
// This example creates a new job group and adds newly created jobs to it.
// create group
for (const maxon::Url& file : files)
{
// create and add job
auto job = FileHashJob::Create(file) iferr_return;
group.Add(job) iferr_return;
}
// enqueue jobs and wait
group.Enqueue();
group.Wait();
// This example creates a new job group and adds generic jobs to it.
// create group
for (const maxon::Url& file : files)
{
// add generic job defined by a lambda function
[file]() -> maxon::Result<void>
{
return CreateFileHash(file);
group.Add(job) iferr_return;
}
// enqueue jobs and wait
group.Enqueue();
group.Wait();
// This example creates a new job group and adds an array of jobs to it
// create group
// prepare array of jobs
maxon::BaseArray<FileHashJob> jobs;
jobs.EnsureCapacity(files.GetCount()) iferr_return;
for (const maxon::Url& file : files)
{
// create job
FileHashJob& job = jobs.Append() iferr_return;
// init job
job.SetFile(file) iferr_return;
}
group.Add(jobs) iferr_return;
// enqueue jobs and wait
group.Enqueue();
group.Wait();

Jobs that do belong to a job group can handle sub-jobs:

Queue

Jobs are added to a queue which executes these jobs. A queue provides worker threads and distributes the jobs.

Note
Typically it is not needed to create a custom queue. maxon::JOBQUEUE_CURRENT should be used.

Default job queues are:

It is possible to manually create queues in order to organize job execution.

Note
Functions like maxon::JobInterface::Enqueue() or maxon::JobGroupRef::Enqueue() add the job or jobs to the current job queue if no argument is given.

Further Reading

maxon::JobGroupRef::Enqueue
JobGroupRef & Enqueue(JobQueueInterface *queue=JOBQUEUE_CURRENT)
Definition: jobgroup.h:426
maxon::JobGroupRef::Add
Result< void > Add(T &&obj)
Definition: jobgroup.h:522
maxon
The maxon namespace contains all declarations of the MAXON API.
Definition: c4d_basedocument.h:27
MAXON_IMPLICIT
#define MAXON_IMPLICIT
Definition: apibase.h:168
maxon::JobResultInterface< void >::SetResult
ResultOk< void > SetResult()
Definition: job.h:908
maxon::JobGroupRef::Create
static ResultMemT< JobGroupRef > Create(JOBGROUPFLAGS flags=JOBGROUPFLAGS::DEFAULT)
Definition: jobgroup.h:413
iferr_return
#define iferr_return
Definition: resultbase.h:1419
DiagnosticOutput
#define DiagnosticOutput(formatString,...)
Definition: debugdiagnostics.h:168
maxon::JobInterfaceTemplate
Definition: job.h:939
maxon::GetCount
Int GetCount(const ITERABLE &iterable)
Definition: collection.h:37
maxon::Result< void >
iferr_ignore
#define iferr_ignore(...)
Definition: resultbase.h:1384
maxon::JobGroupRef
Reference to a group (JobGroupInterface).
Definition: jobgroup.h:401
maxon::JobGroupRef::Wait
Bool Wait(TimeValue timeout=TIMEVALUE_INFINITE, WAITMODE mode=WAITMODE::DEFAULT) const
Definition: jobgroup.h:473
MAXON_LIKELY
#define MAXON_LIKELY(X)
Definition: compilerdetection.h:452
maxon::UInt
UInt64 UInt
unsigned 32/64 bit int, size depends on the platform
Definition: apibase.h:185
maxon::JobRef::Create
static auto Create(FN &&src, ARGS &&... args) -> ResultMemT< JobResultRef< decltype(src(std::forward< ARGS >(args)...))>>
Definition: job.h:1025
maxon::JobRef
Reference to a job (JobInterface).
Definition: job.h:1004