А компилятору и не нужно это определять. И тем более компилятор не интересуют утеряны ли там данные — это уже про логические ошибки, поэтому даже рассматривать их не буду.
Из того что я читаю, Вы можете определить какая часть буфера уже была чем-то заполнена. В таком случае, Вы можете хранить буфер в виде &[MaybeUninit<AtomicU8>] (или другой тип атомиков и пр). Далее, после вычисления какая часть реально заполнена, Вы можете получить эту часть в виде &[AtomicU8]. С ней уже можно либо либо куда-то скопировать, либо выдать какую-нибудь обёртку для прямой работы с буфером.
Конкретно с чтением неинициализированных данных здесь проблем никаких нет(и никакое UB не нужно). И это вполне себе несложно прячется за безопасный интерфейс.
Здесь есть проблема с конкурентным доступом, но о ней Вы ничего пока не говорили. Суть в том, что нужно аккуратно сообщить компилятору, что гонка данных здесь разрешена и прочее. С этим чуть сложнее.
Не, не понимаю. Если Вы хотите работать с данными, которые могут быть неинициализированны, то их нужно хранить в MaybeUninit. В местах использования вызывать assume_init{_ref}, когда как-то удостоверились, что данные фактически были инициализированны.
Делать как в комментарии выше строго нельзя — собственно MaybeUninit был добавлен как раз по этому (раньше был std::mem::uninitialized).
Если Вам кажется, что я упускаю какой-то юзкейс, то приведите пожалуйста набросок кода, который, как Вам кажется, не может быть реализован эффективно без mem::uninitialized.
У него есть гарантии на repr: MaybeUninit<T> всегда будет иметь точно такой же репр, что и T. Поэтому его и указатели/ссылки на него вполне себе можно передавать в extern "C".
Но я честно говоря затрудняюсь понять о каких именно случаях Вы говорите, поэтому если приведёте пример с проблемой — будет проще
Основная идея у такого подхода в том, что ошибка определяется местом потребления. Мотивация в том, что мы хотим выдавать ошибки даже в нетипизированных частях нашей программы.
То есть, пока мы просто создали такой список и не используем — это ок. Но как только мы начинаем его использовать нам тут же обратят внимание, что типы не сходяться(не такие, какие мы ожидали).
Довольно сильный недостаток тоже имеется: ошибки выдаются чаще всего далеко от места их фактического возникновения. Собственно с этим и помогают аннотации типов.
Плюс есть пара теоретических проблем. Для начала, вывод типов в достаточно мощных системах типов, увы, undecidable. Плюс, такого рода задачи зачастую лучше и проще решаются инструментами статического анализа.
Вроде же "всё придумано до нас" - есть swiss table, который решает все эти проблемы: отдельный блок для хешей(1 байт каждый), отдельный для ключей+значений; квадратичное пробирование, но блоками по 8/16 ячеек/байт. Вроде как такая схема работает всегда быстрее (кроме итерации — но кто вообще итерируется по хештаблицам (я знаю кто =/))
Наличие технической возможности и пользы довольно быстро создаст приложения, которые решают данную проблему прозрачно для пользователей. Webrtc, syncthing и прочие не на пустом месте появились.
Ну, два cast требуют переписывать сервера под потребителей. А так, можно сделать два call одновременно (да, через сырую отправку, увы). Тут даже noreply не нужен (если например вызовы к разным авторам, или если мы боремся с rtt).
Возможность селективного receive это очень важная фишка, которую многие акторные фреймворки забывают сделать, увы.
Ну, я же говорю, что это абсолютно нужно для реализации кастомных паттернов. Банальная задача: сделать два вызова сервера параллельно. В эрланге делается просто: отправляем два сообщения на запросы (call), после чего делаем два receive. А вот в модели трейтов, тут сложнее — нужно прыгать прям до основного ивент-лупа, там получать эти сообщения и дальше продолжать исполнение обработчика. Абсолютно лишняя сложность.
Не путайте, символы ("кодпоинты") и кодюниты. Длина в js выдаётся в кодюнитах, но храниться всё же utf-16. Просто одна из фишек utf-16, что он позволяет разрезать один кодпоинт на две суррогатных пары.
Правда ли что из-за backref-ов требует линейную память при декодировании? Аналогичный вопрос при кодировании (но там проще, т.к. можно поддерживать только для шейпов (если пользователю ок)).
Да, в том смысле, что на них можно просто прочекать весь мир. Но нет, потому что это практически неюзабельно.
Даже на взаимодействии двух акторов слишком часто приходиться закатывать солнце вручную. Я уже не говорю про всякие интересные правила типа "после того, как я получил сообщение W от актора X, я могу отправлять сообщение M всем авторам из группы G, но всего, не более чем 3 раза". Ну и там, по-хорошему, нужны линтипы для моделирования сообщений, которые можно отправить лишь некоторое количество раз.
Без линтипов, там нужно всех акторов запихивать в одну огромную монаду и трекать набор доступных сообщений в её типе. И то есть сложности...
А компилятору и не нужно это определять. И тем более компилятор не интересуют утеряны ли там данные — это уже про логические ошибки, поэтому даже рассматривать их не буду.
Из того что я читаю, Вы можете определить какая часть буфера уже была чем-то заполнена. В таком случае, Вы можете хранить буфер в виде &[MaybeUninit<AtomicU8>] (или другой тип атомиков и пр). Далее, после вычисления какая часть реально заполнена, Вы можете получить эту часть в виде &[AtomicU8]. С ней уже можно либо либо куда-то скопировать, либо выдать какую-нибудь обёртку для прямой работы с буфером.
Конкретно с чтением неинициализированных данных здесь проблем никаких нет(и никакое UB не нужно). И это вполне себе несложно прячется за безопасный интерфейс.
Здесь есть проблема с конкурентным доступом, но о ней Вы ничего пока не говорили. Суть в том, что нужно аккуратно сообщить компилятору, что гонка данных здесь разрешена и прочее. С этим чуть сложнее.
Не, не понимаю. Если Вы хотите работать с данными, которые могут быть неинициализированны, то их нужно хранить в MaybeUninit. В местах использования вызывать assume_init{_ref}, когда как-то удостоверились, что данные фактически были инициализированны.
Делать как в комментарии выше строго нельзя — собственно MaybeUninit был добавлен как раз по этому (раньше был std::mem::uninitialized).
Если Вам кажется, что я упускаю какой-то юзкейс, то приведите пожалуйста набросок кода, который, как Вам кажется, не может быть реализован эффективно без mem::uninitialized.
P.S. Или Вы буквально оставляете UB в коде?
Тогда о чём речь?
У него есть гарантии на repr: MaybeUninit<T> всегда будет иметь точно такой же репр, что и T. Поэтому его и указатели/ссылки на него вполне себе можно передавать в extern "C".
Но я честно говоря затрудняюсь понять о каких именно случаях Вы говорите, поэтому если приведёте пример с проблемой — будет проще
В каком смысле? Что мешает гонять по коду MaybeUninit?
Это другие списки. В ядре используются интрузивные списки — и там отдельный набор трейдоффов на тему того, а как это можно реализовать в расте
Это insta ub. Так писать нельзя
А как тогда её исключают?
Основная идея у такого подхода в том, что ошибка определяется местом потребления. Мотивация в том, что мы хотим выдавать ошибки даже в нетипизированных частях нашей программы.
То есть, пока мы просто создали такой список и не используем — это ок. Но как только мы начинаем его использовать нам тут же обратят внимание, что типы не сходяться(не такие, какие мы ожидали).
Довольно сильный недостаток тоже имеется: ошибки выдаются чаще всего далеко от места их фактического возникновения. Собственно с этим и помогают аннотации типов.
Плюс есть пара теоретических проблем. Для начала, вывод типов в достаточно мощных системах типов, увы, undecidable. Плюс, такого рода задачи зачастую лучше и проще решаются инструментами статического анализа.
А можете привести пример, когда метод цепочек будет быстрее?
Вроде же "всё придумано до нас" - есть swiss table, который решает все эти проблемы: отдельный блок для хешей(1 байт каждый), отдельный для ключей+значений; квадратичное пробирование, но блоками по 8/16 ячеек/байт. Вроде как такая схема работает всегда быстрее (кроме итерации — но кто вообще итерируется по хештаблицам (я знаю кто =/))
Наличие технической возможности и пользы довольно быстро создаст приложения, которые решают данную проблему прозрачно для пользователей. Webrtc, syncthing и прочие не на пустом месте появились.
Это я увидел. Выглядит в целом норм
Не знаю, где там Вы и что нашли. Но факт остаётся фактом: js хранит строки в utf-16, не в ucs-2.
Ну, два cast требуют переписывать сервера под потребителей. А так, можно сделать два call одновременно (да, через сырую отправку, увы). Тут даже noreply не нужен (если например вызовы к разным авторам, или если мы боремся с rtt).
Возможность селективного receive это очень важная фишка, которую многие акторные фреймворки забывают сделать, увы.
Ну, я же говорю, что это абсолютно нужно для реализации кастомных паттернов. Банальная задача: сделать два вызова сервера параллельно. В эрланге делается просто: отправляем два сообщения на запросы (call), после чего делаем два receive. А вот в модели трейтов, тут сложнее — нужно прыгать прям до основного ивент-лупа, там получать эти сообщения и дальше продолжать исполнение обработчика. Абсолютно лишняя сложность.
Не путайте, символы ("кодпоинты") и кодюниты. Длина в js выдаётся в кодюнитах, но храниться всё же utf-16. Просто одна из фишек utf-16, что он позволяет разрезать один кодпоинт на две суррогатных пары.
Ну, то есть линейная
, так?
Правда ли что из-за backref-ов требует линейную память при декодировании? Аналогичный вопрос при кодировании (но там проще, т.к. можно поддерживать только для шейпов (если пользователю ок)).
Да, в том смысле, что на них можно просто прочекать весь мир. Но нет, потому что это практически неюзабельно.
Даже на взаимодействии двух акторов слишком часто приходиться закатывать солнце вручную. Я уже не говорю про всякие интересные правила типа "после того, как я получил сообщение W от актора X, я могу отправлять сообщение M всем авторам из группы G, но всего, не более чем 3 раза". Ну и там, по-хорошему, нужны линтипы для моделирования сообщений, которые можно отправить лишь некоторое количество раз.
Без линтипов, там нужно всех акторов запихивать в одну огромную монаду и трекать набор доступных сообщений в её типе. И то есть сложности...