@dlangru

Страница 294 из 719
Oleg
20.10.2017
10:34:54
Ну или хотя ldc должен быть версии с raii

Dmitry
21.10.2017
07:32:51
Блин, мой любимый вопрос. По файберам foo() { блокирующаяОперация() yield() } Как будет происходить переключение на другой файбер, если у нас ялд будет вызван только после выполнения блокирующей операции

Во, очень интересную штуку нашел. Как я понимаю весь рантайм NET уместили в 40 тыс строк кода https://www.codeproject.com/Articles/1211457/DotNetAnywhere-An-Alternative-NET-Runtime

Dmitry
21.10.2017
08:12:50
> рантайм NET уместили в 40 тыс строк кода Интересно было бы с жабой сравнить. Вернее, с жабами, они же разные есть.

Google
Friedrich
21.10.2017
08:17:22
35k строк gc.cpp и ещё 5k строк нормального кода ? (нет)

Dmitry
21.10.2017
08:29:44
А как в нормальном коде делается чтобы блокировки не было?

Ievgenii
21.10.2017
08:35:56
А какого типа блокировка?

Что это за операция?

Andrey
21.10.2017
09:07:23
Блин, мой любимый вопрос. По файберам foo() { блокирующаяОперация() yield() } Как будет происходить переключение на другой файбер, если у нас ялд будет вызван только после выполнения блокирующей операции
блокирующую операцию нужно вызывать через неблокирующий метод) например, переводим сокет в неблокирующий режим и пытаемся прочесть. если не данных - yeld. или например асинхронный запрос к постгре. проде так

либо проверяем состояния дескриптора чере select к примеру. если должен заплокироваться при чтении - йыэлд

Dmitry
21.10.2017
09:34:27
А какого типа блокировка?
Ну классика жанра. Обращение к БД или ФС

@asan13 у меня картинка в голове не формируется упорно. Неблокирующий метод в себе же должен содердать какую-то логику?

Ievgenii
21.10.2017
09:36:00
Вон тебе выше сказали решение, при блокирующих операциях типа работы с сетью

смотри

если блокируящая операция - это чего-то расчет, типа матиматика, то тут сложно.

Если это простое IO, то нужно с ней просто в не блокирующем режиме работать

Google
Ievgenii
21.10.2017
09:37:16
и все

Dmitry
21.10.2017
09:38:41
тоесть функция чтения (потенциально блокирующая) должна в себе содержать какую-то логику? Навроде: 1. проверить есть ли данные в буфере 2. если их нет сделать yield 3. если есть считать

Ievgenii
21.10.2017
09:39:07
Что-то вроде того

Тогда у тебя эта операция будет не блокирующей

Dmitry
21.10.2017
09:40:17
А вот операция ссчитывания они же тоже в каком-то потоке должна выполяться? Есть какие-то системные потоки? Просто данные же должен кто-то ссчитывать

Ievgenii
21.10.2017
09:40:53
не понял

Dmitry
21.10.2017
09:41:30
ну вот операция ссчитывания она же должна кем-то выполняться

Ievgenii
21.10.2017
09:41:53
Считывания откуда?

Из stdIn?

Dmitry
21.10.2017
09:42:07
пусть будет из файла

Ievgenii
21.10.2017
09:42:37
Смотри

Берем файл

Открываем его на чтение

И читаем его только тогда, когда появляется время на его чтение

Если сокет - то читаем только тогда, когда что-то приходит в него (меняется его внутренее состояние)

Читаем не весь файл

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

Ну пускай читаем 16Кб

Придположим

Dmitry
21.10.2017
09:44:36
И читаем его только тогда, когда появляется время на его чтение
я не могу понять когда оно моявляется. Сейчас скину переписку с Ольшанским по теме. Один момент. Просто после общения с ним я только снова начал путаться

Google
Ievgenii
21.10.2017
09:44:42
После чего возвращаем управление приложению, может там какой-то таймер хочет сработать

Dmitry
21.10.2017
09:51:00
Я: "Тоесть условно говоря есть а) потока где работают файберы б) все остальные потоки Если встречается блокирующая операция то дергается тред из группы Б который выполняет само считывание данных, а тред из группы А просто перещелкивается" Он: Ага примерно так Он: запрос на чтение фиксируется и когда появится эвент из кернеля по этому сокету тогда поток из группы Б считывает Он: Инчае ты просто начнешь локать по одному треду из Б на сокет, та же проблема Он: 1 тред под диспетчера, К тредов для Файберов и М тредов под IO

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

Ievgenii
21.10.2017
09:53:38
Не совсем

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

Или в них!

Их может быть более одного

Чтобы не блокировать основной поток

Andrey
21.10.2017
09:54:42
смотри. есть у нас файберы, в одном из них делаем запрос к БД, асинхронный. после него делаем yeld(), что бы дать поработать другим файберам, так как, пока результат не получили, далтать этому файберу нечего, только ждать результат. затем, когда в следующий раз переключаемся в этот файбер, проверяем, если результат полуцчен - обрабатываем, если нет - опять yeld()

Ievgenii
21.10.2017
09:55:47
Ну или можно это сделать без файберов, а на колбеках.

Но тогда код не выглядет как синхронный

Вот и все

Andrey
21.10.2017
09:56:37
или например, в файберах делешь http запросы. отослал запрос, проверяешь состояние сокета - если ответ не пришел, то опять таки, ждать нечего, делаешь yeld. и так проверяешь постоянно, если ответ пришел - обрабатываешь

Ievgenii
21.10.2017
09:56:44
Это зависит от того, используешь ли ты шедулер

Andrey
21.10.2017
09:56:45
нет

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

Google
Ievgenii
21.10.2017
09:57:08
Если используешь шидулер, то этот файбер может выполняться в другом треде

Andrey
21.10.2017
09:58:37
файберы это просто возможноть переключать поток выполнения там, где у тебя появляется простой

Ievgenii
21.10.2017
09:58:55
https://dlang.org/phobos/std_concurrency.html#.FiberScheduler

Это будет в основном потоке

Dmitry
21.10.2017
09:59:36
@asan13 а про какие тогда треды Ольшанский говорит из группы Б?

Andrey
21.10.2017
09:59:56
это из твоей цитаты?

Dmitry
21.10.2017
10:00:30
да

Ievgenii
21.10.2017
10:00:36
А вот этот https://dlang.org/phobos/std_concurrency.html#.ThreadScheduler

Он делает, как я понимаю, отдельный тред и выполняет твой код, который тоже может быть файбером, в отдельном потоке

Admin
ERROR: S client not available

Andrey
21.10.2017
10:02:15
да
ну можно по разному организовать выполнение, зависит от конкретной программы. в простом случае, у тебя есть один нативный поток с файберами. но ничто не мешает насоздавать потоков, в ни х файберы, и перещелкивать-передавть, и что угодно.

может ты хочешь выделить отдельный тред для каких либо действий. файбер-шедулер не смотрел, наверно это какая то обертка для упрощения. но суть yeld()/call() и неблокирующего чтения именно в этом - проверяешь - если будет блокировка - делаешь yeld(). а там хоть в другом потоке читать пытайся, хоть в в этом позже, это уже детали

Ievgenii
21.10.2017
10:10:09
Нужно понять, что файбер не даёт асинхронность, он просто позволяет приостановить выполнения некой функции до тех пор, пока тебе не понадобится ее продолжить

Вот и все

Это некая надстройка над генератором

Andrey
21.10.2017
10:11:35
ну да.

Ievgenii
21.10.2017
10:14:58
А в каком потоке ты его запустиш (файбер) - это уже твоё дело

Andrey
21.10.2017
10:56:17
поток группы Б ожидает завершения асинхронных операций и о них сообщает в основные потоки

в vibe.d так сделано

С точки зрения файбера выполняется блокирующая операция. Но на самом деле операция выполняется асинхронно в другом потоке.

Google
Andrey
21.10.2017
10:59:18
В это время выполняются другия файберы. А когда приходит уведомление о завершении асинхронной операции, то ожидающий файбер продолжает работу

Dmitry
21.10.2017
14:55:17
Ievgenii
21.10.2017
14:57:46
Ну чтобы он не заблокировался, нужно работать с не блокирующими сокетами

Dmitry
21.10.2017
17:06:09
Так ну вот допустим функция из исходников vibed: alias read = Stream.read; size_t read(scope ubyte[] dst, IOMode) { assert(this.readable); size_t len = dst.length; while (dst.length > 0) { enforce(dst.length <= leastSize); auto sz = min(dst.length, 4096); enforce(() @trusted { return .read(m_fileDescriptor, dst.ptr, cast(int)sz); } () == sz, "Failed to read data from disk."); dst = dst[sz .. $]; m_ptr += sz; yield(); } return len; } Как оно получается будет работать?

поток группы Б ожидает завершения асинхронных операций и о них сообщает в основные потоки
Так. Тоесть все же есть еще потоки? Получается картина следующая. Рассматриваем случай когда библиотеки построены с рассчетом на ассинхронность. Есть основной поток (А) приложения. Он просто один за другим молотит функции одна за другой ничего не зная о их природе. Внутри самих функций предусмотрен неблокирующий механизм работы тоесть если ей нужно какой-то IO она стартует в фоновом потоке, а файберу помечает что данные скоро будут. Потом когда управление к нему возвращается он уже получает данные

Andrey
21.10.2017
17:33:35
ну а что непонятно в примере кода? ты правда взял специфичный случай, чтение из файла

Dmitry
21.10.2017
17:36:36
вот мы вызываем функцию read. В какой момент начинается чтение и в какой момент идет перещелкивание на другой файбер. После того как чтение начато оно будет в другом потоке идти?

Andrey
21.10.2017
17:41:49
конкретно в этом коде, мы с цикле вызываем системный read, который вычитывает максимум 4096 байт за раз, и отдает управление затем. на другой файбер перещелкивание идет в yeld, как ни странно))

то есть перещелкиваемся после каждой операции чтения

поскольку читаем из файла, то никогда не будет блокировки в read

а как этот код используется, хз, надо вайб смотреть

т.е на всякий, неоднозначно выразился, переключение не в самом системном read естественно, в коде ниже. а то вдруг не так поймешь)

Dmitry
21.10.2017
17:46:23
вызываем блокирующее чтение, но оно оказывается не блокирующим потому что читает 4096 байт и возвращает управление в функцию?

Andrey
21.10.2017
17:46:49
да. потому что читаем из файла

то есть данные всегда доступны, либо вычиали все.

Dmitry
21.10.2017
17:47:24
а в какой момент мы дочитаем его до конца? Типа мы же уже вернули что-то в функцию в которой был read вызван

Andrey
21.10.2017
17:50:07
до конца дочитали, когда dst.length == 0. перед чтеием она равна длине файла. там в цикле несколько мутная логика на первый взгляд

короче, есть у нас файл 1 мег длиной. читаем из него порциями по 4096 байт, и отдаем управление после каждого чтения

Dmitry
21.10.2017
17:53:06
foo() { data = read("foo.txt"); process(data); } Вот мы вызвали функцию чтения. Она при запуске как будет работтать? Мы же не сможем process() запустить т.к. данные не до конца прочитали

Andrey
21.10.2017
17:54:40
будет, потому что ты до process дойдешь, тоолько когда выйдешь из цикла, и затем из функции

если этот foo в файбере выполняется. в read будет постоянно происходить переключение, пока не вычитаем файл. затем только до process доберемся

вот ты хаял книжку Али, лучше б почитал там главу про файберы))

Страница 294 из 719