Я создаю приложение для Android (используя Scala 2.9) и использую поток, который отображается в SurfaceView; это для игры, поэтому она должна обновляться как можно чаще. Я предполагаю, что эта проблема похожа на другие игровые «циклы событий», где ввод поступает из другого потока.
Вот грубое приближение текущего подхода, основанного на синхронизации. Это «работает достаточно хорошо», но у меня есть общие опасения по поводу необходимости использовать явную синхронизацию и «привязывать» поток просмотра/ввода.
Вид, "поток пользовательского интерфейса":
def View.onTouchEvent(e) { // on UI thread
Game.handleInput(e)
}
Игра, "Игровая нить":
def Game.handleInput(e) = S synchronized { // on UI thread
alterStateBasedOnInput
}
def Game.run () { // on Game thread
while (running) {
S synchronized {
doGameStuff
}
View.post(someStateRelayedViaRunnable)
yield
}
}
Вместо того, чтобы явно использовать синхронизацию, я хотел бы иметь что-то вроде этого:
def View.onTouchEvent(e) { // on UI thread
Game.sendMessage(e)
}
def Game.run () { // on Game thread
while (running) {
processMessage
doGameStuff
View.sendMessage(someState) // hopefully same as Game.sendMessage
yield
}
}
Теперь это относительно легко реализовать вручную с помощью ConcurrentLinkedQueue
или аналогичного, но я действительно не хотел бы изобретать велосипед здесь. Кроме того, было бы неплохо использовать такой актер/очередь для обратной отправки в пользовательский интерфейс — прямо сейчас я использую поддержку Android для публикации (асинхронного) Runnable в потоке пользовательского интерфейса.
Я кратко рассмотрел несколько различных реализаций акторов (в основном стандартные Scala и Scalaz) и несколько различных библиотек Java для «передачи сообщений», таких как Jetlang, но большинство из них, похоже, используют неявные потоки или службу исполнителя потоков. Но в моем случае я хочу [запускать актера и] обрабатывать сообщения в определенное время в определенном потоке. Для View.sendMessage сообщения также должны обрабатываться в потоке пользовательского интерфейса, но время не так важно и может быть связано с выполнением Runnable, упомянутым выше.
Тогда, я думаю, мой вопрос, учитывая вышеизложенное:
Каким был бы хороший (например, "эффективный" и идиоматический) подход к передаче данных между этими двумя потоками?
(Я также готов принять предположение, что я совершенно не понимаю акторы Scala и/или акторы Scalaz и/или другие библиотеки передачи сообщений; кажется, что Scalaz может работать так, как я себе представляю, но мне сложно уследить)