169 похожих чатов

Коллеги, привет! Помогите с корутинами, пожалуйста. Есть некий сервис А

с долгим процессом инициализации. И есть другой, Б, с кучей функций, который этот сервис под собой использует.

Каждая функция сервиса Б проверяет, готов ли А, и затем исполняется. Если не готов - запускает инициализацию и ждёт.

Я хочу, чтобы на время этой инициализации функции прервались, а сразу после - продолжили выполняться. Как это лучше всего реализовать?

Инициализация сервиса А - не suspend функция, но есть коллбэк об успешном завершении. Кажется, что Channel должен здесь помочь, но я не могу знать, какое количество функций ждёт инициализацию, чтобы именно столько значений туда допихать. Если только в какой-нибудь AtomicInteger переменной считать, но мне кажется, что должно быть решение поэлегантней

22 ответов

32 просмотра

Верните результат инициализации в виде Deferred. Тогда все, кто будет делать ему await, то обудет ожидать, пока не завершится. И потом сразу все, что зависит стартанет. Не надо никаких каналов. Самый простой способ заворачивания колбэка такой: fun initialize(): Deferred<T>{ val res = CompletableDeferred<T>() startInitialization( callback = { result -> res.complete(result)} return res }

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Верните результат инициализации в виде Deferred. Т...

Выглядит классно! А если коллбек - это конкретный инстанс класса, который уже объявлен и используется всегда, есть ли какое-то более элегантное решение, чем оборачивание его в новый коллбек, который будет комплитить deferred и передавать управление?

Kamo Spertsyan
Выглядит классно! А если коллбек - это конкретный ...

При создании инстанса колбэка передать ему незавершенный деферред

Kamo-Spertsyan Автор вопроса
Alexander Nozik
При создании инстанса колбэка передать ему незавер...

он уже создан, то есть по сути это поле в классе, которое один раз создаётся. В принципе, могу переделать это поле в creator и при каждом обращении создавать новый инстанс

Kamo Spertsyan
он уже создан, то есть по сути это поле в классе, ...

Не понял, а как вы на него реагировать хотите, если на эту реакцию никак подписаться нельзя?

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Не понял, а как вы на него реагировать хотите, есл...

ну вот думаю, как это лучше всего реализовать) Коллбек-обёрткой или коллбек-криэйтором. По сути +- одно и то же

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Верните результат инициализации в виде Deferred. Т...

Мой кейс немного усложнился и теперь это решение не подходит. Дело в том, что успешная инициализация может произойти в одной из всех параллельных попыток, и в этом случае все корутины должны продолжиться, а закомплитить я смогу только один deferred, который был передан конкретно коллбеку, который вызвал успешную инициализацию. Все остальные просто не дождутся ответа (или ответ будет а-ля "уже идет процесс инициализации"). Есть ли какие-то опции для такой ситуации?

Kamo Spertsyan
Мой кейс немного усложнился и теперь это решение н...

Можно сделать несколько девередов и там по-моему есть готовый метод, который из нескольких выбирает певрый успешный, а остальные отменяет

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Можно сделать несколько девередов и там по-моему е...

а мне же надо, чтобы все успехом завершились, чтобы все ожидающие корутины продолжили выполняться

Kamo Spertsyan
а мне же надо, чтобы все успехом завершились, чтоб...

Не понял. Инициализация одна на всех или у каждого своя?

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Не понял. Инициализация одна на всех или у каждого...

Попробую чуть подробнее. Есть сервис А, который нужно инициализировать. Доступа к его коду у меня нет. Метод init() принимает коллбек, который дёргается с кодом результата. Есть также мой сервис В, в котором несколько разных методов работают с инициализированным сервисом А. Все они могут параллельно обратиться к нему и потребовать инициализации, если она ещё не произошла. То есть, скажем, 3 корутины параллельно запросили инициализацию и ждут. Первая запустила, две другие получили ответ, что "инициализация уже в процессе" и всё (коллбек отработал и больше не вызовется). Я хочу, чтобы как только инициализация из первой корутины завершилась, все 3 корутины получили результат и продолжили выполнение

Kamo Spertsyan
Попробую чуть подробнее. Есть сервис А, который ну...

deferred подходит. я так понимаю это уже и советовали

Kamo Spertsyan
Попробую чуть подробнее. Есть сервис А, который ну...

еще раз. Один раз делаете метод инициализации, который возвращает кэшированный Deferred. Потом его можно раздать всем. private val result = CompletableDeferred<T>() private var initializationStarted = false public fun initialize(): Deferred<T>{ if(!initializationStarted) { initializeService(); initializationStarted = true} return result } Или какой-то вариант на тему.

Kamo-Spertsyan Автор вопроса
Anton Lakotka
deferred подходит. я так понимаю это уже и советов...

А как с ним быть? По сути deferred-ы из двух корутин, которые вызвали init() после первой, сразу оборвутся без нужного результата. Сработает только deferred у первой

Kamo-Spertsyan Автор вопроса
Alexander Nozik
еще раз. Один раз делаете метод инициализации, кот...

А, то есть кешировать deferred? Окей, спасибо, попробую такой вариант

Alexander Nozik
еще раз. Один раз делаете метод инициализации, кот...

+ только я бы initializationStarted засинхронизировал

Kamo Spertsyan
А, то есть кешировать deferred? Окей, спасибо, поп...

Да, именно так. Или просто один раз его создать автоматом. Зависит от того, хотите вы его сбрасывать или нет.

Kamo-Spertsyan Автор вопроса
Alexander Nozik
Да, именно так. Или просто один раз его создать ав...

Хочу, в теории может повторная инициализация потребоваться

Kamo-Spertsyan Автор вопроса
Kamo Spertsyan
Хочу, в теории может повторная инициализация потре...

ну тогда делаете его нуляблем и присваиваете в иницализации вместо того, чтобы булю выносить.

Kamo-Spertsyan Автор вопроса
Anton Lakotka
+ только я бы initializationStarted засинхронизиро...

Не нужно, если сам метод синхронизирован.

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта