Я изучаю Kotlin Собственный и у меня есть программа с кучей Рабочих , выполняющих параллельные операции (работает на Windows, но это общий вопрос).
Теперь я хотел добавить простую регистрацию. Компонент, который просто регистрирует строки, добавляя их как новые строки в файл, который остается открытым в режиме 'добавления'.
(В идеале, я бы просто имел "глобальную" функцию ...
fun log(text:String) {...} ]
... что я смогу позвонить откуда угодно, в том числе "изнутри" другим работникам, и это сработало бы. Смысл здесь в том, что сделать это не тривиально, потому что из Kotlin Нативных правил, касающихся передачи объектов между потоками (TLDR: вы не должны передавать изменяемые объекты вокруг. См .: https://github.com/JetBrains/kotlin-native/blob/master/CONCURRENCY.md#object -transfer-and-freezing ). Кроме того, моя функция журнала в идеале приняла бы любой замороженный объект.)
Я пришел к выводу о решениях, использующих DetachedObjectGraph :
Сначала я создаю отсоединенный объект logger
val loggerGraph = DetachedObjectGraph { FileLogger("/foo/mylogfile.txt")}
, а затем используйте loggerGraph.asCPointer()
( asCPointer () ), чтобы получить COpaquePointer
для отдельного графика:
val myPointer = loggerGraph.asCPointer()
Теперь я может передать этот указатель рабочим (через производителя лямбда рабочего выполнить функцию ) и использовать ее там. Или я могу сохранить указатель в глобальной переменной @ ThreadLocal .
Для кода, который записывает в файл, всякий раз, когда я хочу записать строку, мне нужно создать DetachedObjectGraph
объект из указателя снова и attach()
его, чтобы получить ссылку на мой объект fileLogger:
val fileLogger = DetachedObjectGraph(myPointer).attach()
Теперь я могу вызвать функцию регистрации в регистраторе:
fileLogger.log("My log message")
Это то, что я придумал, глядя на API, которые доступны (по состоянию на Kotlin 1.3.61) для параллелизма в Kotlin Native, но Мне интересно, что лучше подход будет (используя Kotlin, не прибегая к C). Ясно, что создавать объект DetachedObjectGraph для каждой записанной строки плохо.
Можно задать этот вопрос более общим образом: как сохранить изменяемый ресурс открытым в отдельном потоке (или работнике ) и отправлять ему сообщения.
Дополнительный комментарий: Наличие сопрограмм , которые действительно используют потоки, решило бы эту проблему, но вопрос заключается в том, как решить эту задачу с помощью API в настоящее время (Kotlin 1.3.61).