Перейти к содержимому

Своё поверх ядра

Если вашей библиотеке нужны своё состояние, очередь или правила планирования, наследуйте JobBase<T> и JobContextBase. Базовые классы обеспечивают описанный выше жизненный цикл, а наследники добавляют поведение библиотеки. Защищённый API даёт доступ к статусу, ожидающей отмене, дочерним задачам, запуску и завершению. У отмены есть флаг, определяющий, может ли задача её отклонить. Переопределите started() и finished() для обработки событий жизненного цикла.

Например, собственный класс задачи может создавать свой тип контекста и предоставлять координатору метод запуска:

final class MyJob<T> extends JobBase<T> {
final Future<T> Function(MyContext ctx) _body;
MyJob(this._body, {super.key, super.observer});
@override
JobContextBase createContext() => MyContext(this);
@override
Future<T> execute(covariant MyContext ctx) => _body(ctx);
// `start` защищён: движок открывает к нему свою дверь.
void launch() => start();
}
final class MyContext extends JobContextBase {
MyContext(super.owner);
}
final job = MyJob<int>((ctx) => ctx.wait(load))..launch();

wait, join и uncancellable начинают с вызова check(). Переопределите его, чтобы добавить проверки сразу во все три метода.

Защищённые методы доступны внутри наследников. Если отдельному координатору нужен такой вызов, предоставьте метод-обёртку в своём классе, как launch() в примере.

Добавляя собственную обработку ошибок, используйте reportToZone, чтобы передать ошибку в зону создания задачи, если получателя нет. Если метод контекста нельзя вызывать из работы, запущенной через unattended, проверяйте это с помощью throwIfUnattended.

solo использует эти возможности расширения. Полный защищённый API описан в справке JobBase.

Обычный Job планирует свой запуск на следующую микротаску. Если момент запуска должен выбрать вызывающий код, используйте Job.deferred(body). Он возвращает DeferredJob<T> с публичным методом start(). Его можно вызвать самостоятельно, поручить запуск очереди или передать задачу родителю через ctx.run(child), как в примере с дочерней задачей.

final job = Job.deferred<void>((ctx) => ctx.wait(work));
// ... позже, или из своей очереди
job.start();