/*
This file is part of Ingen.
Copyright 2007-2016 David Robillard
Ingen is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or any later version.
Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
You should have received a copy of the GNU Affero General Public License
along with Ingen. If not, see .
*/
#ifndef INGEN_ENGINE_TASK_HPP
#define INGEN_ENGINE_TASK_HPP
#include
#include
#include
namespace Ingen {
namespace Server {
class BlockImpl;
class RunContext;
class Task : public std::vector {
public:
enum class Mode {
SINGLE, ///< Single block to run
SEQUENTIAL, ///< Elements must be run sequentially in order
PARALLEL ///< Elements may be run in any order in parallel
};
Task(Mode mode, BlockImpl* block=NULL)
: _block(block)
, _mode(mode)
, _done_end(0)
, _next(0)
, _done(false)
{
assert(!(mode == Mode::SINGLE && !block));
}
Task& operator=(const Task& copy) {
*static_cast*>(this) = copy;
_block = copy._block;
_mode = copy._mode;
_done_end = copy._done_end;
_next = copy._next.load();
_done = copy._done.load();
return *this;
}
Task(const Task& copy)
: std::vector(copy)
, _block(copy._block)
, _mode(copy._mode)
, _done_end(copy._done_end)
, _next(copy._next.load())
, _done(copy._done.load())
{}
/** Run task in the given context. */
void run(RunContext& context);
/** Pretty print task to the given stream (recursively). */
void dump(std::function sink, unsigned indent, bool first) const;
/** Simplify task expression. */
void simplify();
/** Steal a child task from this task (succeeds for PARALLEL only). */
Task* steal(RunContext& context);
Mode mode() const { return _mode; }
BlockImpl* block() const { return _block; }
bool done() const { return _done; }
void set_done(bool done) { _done = done; }
private:
Task* get_task(RunContext& context);
BlockImpl* _block; ///< Used for SINGLE only
Mode _mode; ///< Execution mode
unsigned _done_end; ///< Index of rightmost done sub-task
std::atomic _next; ///< Index of next sub-task
std::atomic _done; ///< Completion phase
};
} // namespace Server
} // namespace Ingen
#endif // INGEN_ENGINE_TASK_HPP