Синхронное будущее Scala без отдельного потока

Я создаю библиотеку, которая, как часть ее функциональности, делает HTTP-запросы. Чтобы заставить его работать в нескольких средах, в которых он будет развернут, я бы хотел, чтобы он мог работать с фьючерсами или без них.

Один из вариантов заключается в том, чтобы библиотека параметризовала тип своего ответа, чтобы вы могли создать экземпляр библиотеки с типом Future или экземпляр с типом Id, в зависимости от того, используете ли вы асинхронную реализацию HTTP. (Id может быть монадой Identity - достаточно, чтобы предоставить пользователям непротиворечивый интерфейс)

Я начал с этого подхода, но он усложнился. Вместо этого я бы хотел использовать тип Future везде, упаковывая синхронные ответы в Future, где это необходимо. Однако я понимаю, что использование фьючерсов всегда будет влечь за собой какой-то пул потоков. Это не будет летать, например. AppEngine (необходимая среда).

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

(ps в качестве дополнительного требования мне нужно иметь возможность кросс-сборки библиотеки обратно в Scala v2.9.1, что может ограничить функции, доступные в scala.concurrent)


person adamnfish    schedule 01.08.2013    source источник
comment
Is there a way to create a Future from a value that will be executed on the current thread Зачем тогда использовать будущее??   -  person Jatin    schedule 01.08.2013
comment
Как я объясняю, чтобы создать согласованный тип возвращаемого значения для всех реализаций   -  person adamnfish    schedule 01.08.2013
comment
Извините, я не понял вопроса. Если вы имеете в виду, что у вас уже есть окончательное значение результата и вам нужна будущая оболочка для него, то как насчет использования Promise?   -  person Jatin    schedule 01.08.2013


Ответы (2)


Насколько я понимаю, вы хотите что-то выполнить, а затем обернуть результат Future. В этом случае вы всегда можете использовать Promise

val p = Promise[Int]
p success 42
val f = p.future

Следовательно, теперь у вас есть оболочка future, содержащая окончательное значение 42.

Обещание очень хорошо объяснено здесь .

person Jatin    schedule 01.08.2013
comment
А, конечно, спасибо! Фантастическая ссылка также. Проблема здесь в том, что вам все еще нужно предоставить ExecutionContxt (неявно или иным образом). Мне не ясно, действительно ли предоставленный ExecutionContext используется с этим подходом Promise, но в любом случае это заканчивается как проверенные исключения в Java, когда контекст должен быть включен на всем протяжении приложения, которое потребляет будущее. - person adamnfish; 01.08.2013
comment
Кроме того, объект Promise включает в себя метод, позволяющий сделать это более лаконично: Promise.successful(42).future. - person adamnfish; 01.08.2013
comment
@adamnfish Нет, вам не нужен ExecutionContext для кода выше. Мы не представляем никакого будущего в любом месте. Я думаю, что вы ошибаетесь с этим. Просто import scala.concurrent._ будет достаточно. Также, пожалуйста, примите ответ, если вы думаете, что он отвечает :) - person Jatin; 01.08.2013
comment
А объект Future включает в себя метод, позволяющий сделать это еще более лаконично: Future successful 42 - person Aaron Novstrup; 02.08.2013
comment
Эта строка не нуждается в ExecutionContext, но когда вы используете это Future (например, путем его сопоставления), оно вам нужно там, даже если это Future просто оборачивает значение. Импорт concurrent._ импортирует глобальный ExecutionContext, поэтому вы, скорее всего, не увидите проблемы. Как я уже сказал, требуется, чтобы это работало без необходимости в пуле потоков. На данный момент я сам реализовал ExecutionContext, который работает в текущем потоке, но меня интересует, есть ли решения, которые не требуют этого пластыря. - person adamnfish; 02.08.2013
comment
@adamnfish Вы действительно можете использовать Future без ExecutionContext, вызвав (блокирующие) методы ready или result. В вашем случае, поскольку вы знаете, что Future будет завершена, вы знаете, что эти вызовы не будут заблокированы. С другой стороны, использование другого ExecutionContext для различения синхронных и асинхронных случаев, вероятно, является наиболее естественным решением с Future API Scala. Это позволит вам передать будущее через код, который ничего не знает о том, работаете ли вы на самом деле в асинхронном контексте. - person Aaron Novstrup; 02.08.2013