Re[26]: Mногопоточность: C++ vs Erlang vs другие
От: vdimas Россия  
Дата: 17.06.15 07:33
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

V>>Где ты предлагаешь разместить аналог своего asio::coroutine в future<>?


EP>Там же где и обычное обычное замыкание-продолжение.

EP>Абстрагируйся от asio::coroutine, представь простое замыкание-продолжение. Например у нас вместо:
EP>
EP>future<int> sum()
EP>{
EP>    int x = await foo();
EP>    int y = await bar();
EP>    return x + y;
EP>}
EP>
есть ручное нарезание на продолжения:

EP>
EP>future<int> sum()
EP>{
EP>    return foo().then([](int x)
EP>    {
EP>        return bar().then([=](int y)
EP>        {
EP>            return x + y;
EP>        });
EP>    });
EP>}
EP>
Где по-твоему здесь размещаются эти продолжения?


Оба раза в куче. ))
Т.е. лямбда создаётся на стеке, но при сохранении её в std::function, происходит создание её копии в куче, потому что объект function устроен как-то так (схематично):
template<>
class function<void()>
{
public:
  template<typename T>
  function(const T & closure)
    : closure_(makeClosure(closure))
  {}

  void operator()() {
    closure_->invoke();
  }

private:
  struct Closure {
    virtual void invoke() = 0;
  };

  template<typename T>
  static Closure * makeClosure(const T & closure) 
  {
    struct ClosureImpl {
      T closure_;
      virtual void invoke() { closure_(); }
    };
    
    return new ClosureImpl() {closure};
  };

  Closure * closure_;
};


Реальное исполнение отличается от приведенного попыткой оптимизации для маленьких замыканий, типа как для обычных адресов ф-ий, чтобы, если std::function создаётся от аргумента-простого адреса ф-ии, ничего в куче не создавать.


EP>И почему stackless корутина должна размещаться в каком-то другом месте?


Потому что, как и в случае std::string, для которого тоже есть некая оптимизация "маленьких" значений, реальный размер корутины заранее предугадать невозможно. Собсно, открой <functional> и посмотри на кол-во вызовов new.


V>>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.


EP>А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.


Если используем future, то у нас в любом случае будет выделение памяти из кучи. Я лишь предлагаю свести кол-во выделений к минимуму, реализовав корутину как наследника future, либо как в случае с make_shared, просто расположив оба объекта в одном куске памяти (что фактически идентично с т.з. использования памяти). И я УВЕРЕН, что это именно так и будет. Даже могу поспорить на денюжку. )) Сорри, но это слишком очевидно, чтобы это "промухать". Не промухают, я уверен.


V>>Другое дело:

V>>
V>>iterator<T> generate() resumable {
V>>  yield return 1;
V>>  yield return 2;
V>>};
V>>

V>>Т.к. тип iterator<> еще не специфирован, вполне возможно, что у него будет некое зарезервированное поле, в котором можно поместить целочисленную переменную — состояние автомата-корутины.

EP>Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?


Не надо пример. Я, как раз, понимаю о чем речь, но ты не вникаешь в суть моих вопросов. Я всегда спрашиваю одно и то же — какой будет тип результирующего объекта? Можно ли объявить переменную этого типа БЕЗ объявления корутины, а реальную корутину присвоить "потом" — как в твоём сценарии сериализации?


V>>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.

EP>Зачем?

Для рекурсии. В т.ч. всевозможной неявной, через вызовы, скажем, захваченных в лямбду методов-переменных.


EP>Вложенная корутина будет просто полем объекта внешней корутины


Ты забыл, что корутина у нас stack-less, поэтому стек ей придётся нарисовать ручками. И этот стек — штука динамическая, увы))
Поэтому — в куче.


EP>Вот пример, в нём нет никаких аллокаций в куче

(скипнул пример)

В этом примере нет, ес-но. Потому что нет недетерминированного стека вызовов.
Re[28]: Почему Эрланг
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 17.06.15 07:36
Оценка:
Здравствуйте, Ikemefula, Вы писали:

N>>А что, коллстек стал панацеей? Если у тебя уже мусор в данных, а откуда он появился, неизвестно, все подробности генерации давно забылись — у тебя на руках только мусор с момента его осознания таковым.

N>>Я действительно не вижу разницы. Если тебе нужны в рантайме какие-то подробности о происходящем, их можно вложить в контекст (например, через хитроназванные ключи объектов). Но для процедурного те же проблемы.
I>Колстек это не панацея, но он очень сильно помогает. Можно например выяснить, откуда пошел мусор.
I>"вложить в контекст" — это ты изобретаешь тот самый колстек.

Не-а. Я как раз обобщаю до правильного построения вопроса. Call stack — это очень частный случай истории: только те вызовы, которые ещё не редуцировались. Правильный вопрос — что нужно из истории, в общем смысле. Для примера — многие любят отладчик, как средство работы — расставить breakpoint'ы, пройтись пошагово... как только ты выходишь за пределы показа только того же call stack, ты переходишь к рассмотрению истории в широком смысле (в неё будет входить видимый тебе путь выполнения с переменными по ходу и т.п.)
Так вот — call stack это попсня от истории — это только то, что невозможно не скрыть. (Хотя современные компиляторы с их инлайнингом и прочими мерами способны и тут убрать нужное — я с gcc регулярно наблюдаю даже при -Og, что какое-то вполне нужное значение оказалось optimized out. Erlang, аналогично, при хвостовой рекурсии исключает предыдущие инвокации того же уровня, при этом даже не сохраняя счётчик хвостов. Пока у него в истории не появились номера строк, было иногда крайне сложно понять, откуда же пришли.)

I>В многопоточном коде я бы сказал 70-80% проблем решаются с помощью этого фокуса. Если проблема с забытыми ссылками, здесь, опять же, помогает колстек — в том же профайлере.


Забытые ссылки — ты явно не то имеешь в виду, что я. Я имел в виду в managed среде то, что не очищается через GC, потому что где-то в сложных данных осталась на него ссылка.

I>>>Не получится чесно остановить тот же http.get. И здесь другой фокус- как только отпускаешь отладчик, получаешь автоматом вырожденный кейс, когда респонсы валятся лавиной.

N>>А что, с остановкой всех тредов ты его не получаешь?
I>Полчаешь, только ручной работы несравнимо меньше"

Должно быть больше.
The God is real, unless declared integer.
Re[13]: Mногопоточность: C++ vs Erlang vs другие
От: vdimas Россия  
Дата: 17.06.15 07:38
Оценка:
Здравствуйте, netch80, Вы писали:

N>>>Если бы это было серьёзной проблемой, давно бы в винде встроили SCTP из коробки.

V>>Причем тут SCTP?
N>Message-oriented с гарантией доставки, всё, как ты просил.

А разве по нему можно пулять произвольные сообщения?

=======
Ну и дело-то не в винде, ес-но. Весь интернет построен на юникс-совеместимых системах. Винда больше на клиенте.
Ну и проблему установления и разрыва TCP-соединения тоже ведь не я придумал. Т.е. вот этот ненужный пинг-понг, он же не только при установлении TCP-соединения происходит? Помнишь же ту оптимизацию, когда рекомендуется для сокращения пинг-понгов рвать соединение не клиентом, а сервером? ))
Но в реальности соединение чаще рвет клиент-браузер, гоняя по сети уйму ненужных пакетов.

Это реальная дичь, о которой уже лет 10 регулярно говорится, но вот имеем что имеем. Легаси, мать его так.
Re[28]: Mногопоточность: C++ vs Erlang vs другие
От: Evgeny.Panasyuk Россия  
Дата: 17.06.15 07:47
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>Вдогонку. Что насчет локальных переменных корутины? Где их хранить?

EP>Так в этом же вся суть
EP>Функция автоматически преобразовывается в класс-автомат, и её локальные переменные становятся полями класса.
EP>Тоже самое например происходит в показанном ранее примере C# — обрати внимание на исходный код с await, на переменную result, и на поле <result>5__1 в сгенерированном коде
V>Я тебе на это уже отвечал — на примере C# видно, что корутина (произвольного размера) создаётся в куче, реализует некий публичный интерфейс, а локально мы имеем лишь ссылку на этот интерфейс.

Ты перескакиваешь с темы на тему. Тут я показываю что локальные переменные прекрасно хранятся в полях класса-автомата.

V>Т.е. для случая расположения корутины на куче у нас не страдает система типов, т.к. мы можем привести корутину к одному из известных типов,


А почему ты считаешь что она страдает в описываемом мной случае? У нас есть доступ к конкретному типу конкретной корутины, и даже известен sizeof — делай с ним что хочешь.

V>воспользовавшись рантайм-полиморфизмом, который работает исключительно и только для ссылочных типов данных.


Рантайм полиморфизм это тоже ортогонально к теме — так как он добавляется совершенно неинтрузивно, смотри примеры std::function и any_iterator.

V>>>Где будет хранится локальная переменная tmp в твоём случае, т.е. когда iterator<> — это полностью value-type объект?

EP>>Она будет хранится внутри объекта-автомата, который будет хранится внутри самого итератора. Естественно тип итератора будет зависеть от типа класса-автомата.
V>Ну вот на это я и намекал неделей ранее ))

А я где-то говорил другое? Очевидно что zero-overhead без этого никак не получить.

V>В общем, выходит так, что пользоваться такой корутиной можно только через auto,


Нет, это не так. Создаём корутину-генератор — имя класса concrete_generator. Для неё есть функции begin/end возвращающие coroutine_iterator<concrete_generator> — и ничто не мешает выписать вручную этот тип.

V>но не означает ли это невозможность использования сериализации?


Даже если "только через auto" — нет, не означает, так как есть decltype.
Отредактировано 17.06.2015 10:22 Evgeny.Panasyuk . Предыдущая версия .
Re[23]: Почему Эрланг
От: vdimas Россия  
Дата: 17.06.15 07:51
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>я посмотрел windows.h от win 3.1 — не было там никаких CS и прочих мьютексов.


В Win32s для win 3.1 было.

BZ>и на твой вопрос ответ — нет. при использовании синронных операций работы с файлами это ничем не отличается от записи в одном потоке


Ну я надеялся на вопрос от Ikemefula относительно использования асинхронной записи. ))
Там даже в асинхронном случае ничего такого не надо.
Re[29]: Почему Эрланг
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.15 07:53
Оценка:
Здравствуйте, netch80, Вы писали:


N>Не-а. Я как раз обобщаю до правильного построения вопроса. Call stack — это очень частный случай истории: только те вызовы, которые ещё не редуцировались. Правильный вопрос — что нужно из истории, в общем смысле. Для примера — многие любят отладчик, как средство работы — расставить breakpoint'ы, пройтись пошагово... как только ты выходишь за пределы показа только того же call stack, ты переходишь к рассмотрению истории в широком смысле (в неё будет входить видимый тебе путь выполнения с переменными по ходу и т.п.)


Если так, то согласен. Только с асинхронным кодом эти чудеса вылазят практически сразу.

I>>В многопоточном коде я бы сказал 70-80% проблем решаются с помощью этого фокуса. Если проблема с забытыми ссылками, здесь, опять же, помогает колстек — в том же профайлере.


N>Забытые ссылки — ты явно не то имеешь в виду, что я. Я имел в виду в managed среде то, что не очищается через GC, потому что где-то в сложных данных осталась на него ссылка.


Это оно и есть. Профайлер покажет, по какой цепочке ты выделил эту хрень. Это конечно очень затратный фокус, но в асинхронном коде нет даже и его.

N>>>А что, с остановкой всех тредов ты его не получаешь?

I>>Полчаешь, только ручной работы несравнимо меньше"

N>Должно быть больше.


Почему больше ?
Re[23]: Почему Эрланг
От: vdimas Россия  
Дата: 17.06.15 08:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>Я предпочитаю озвучить ТЗ, потому что это иначе спекуляции.

S>Какое ТЗ? Речь идёт о целом классе задач, у которых есть характерные общие черты.

Это слишком широкая трактовка. Конкретно мы с Ikemefula спорим о таком феномене, как "гонки". А это вполне конкретное событие, не допускающее столь широкого толкования, как ты попытался.


V>>Потому как иначе получается, что ты тоже умудрился много чего проигнорировать, например, то, что сама операция SetRemoteResource должна быть атомарной, например, для случая, когда тип I представлен значением, которое не записывается в своё хранилище за одну операцию процессора. Как эту атомарность обеспечивать будем в случае жабасрипта?

S>Ну, если у нас есть готовое решение для обеспечения атомарности всего блока, то уж наверное можно его применить и к отдельной операции, нет?

Ну конечно. Тут можно рассуждать сколько угодно далеко, всё дальше от сути спора о "гонках".
Вот это меня и возмутило в твоём примере... бо он настолько абстрактен, что в него можно впихнуть Всю Сущность Мироздания даже в любимом твоём том самом физическом смысле, бо физические процессы именно таковы и есть — происходят во времени и пространстве, да еще и одновременно (параллельно) ). Вот и всё что ты сказал в том посте. ))


V>>Вопрос, нужны ли в случае жабасрипта критические секции, мьютексы и т.д. для этой задачи?

S>Всё зависит от того, есть ли у нас гарантия единственности системного потока, в котором бегут эти логические потоки.

Золотые слова. ))
Об этом уже 3-й год идет спор.
Ну не то, чтобы прям всё время идет... но просто вернулись к одному эпическому спору.
Я однажды ляпнул, что если вся кооперативная многозадачность сидит на одном потоке ОС, типа как в ГУИ или в жабаскрипте, то можно построить код так, чтобы критические секции (и прочие мьютексы/семафоры) были не нужны. Теперь Ikemefula бегает за мной по всем форумам, вызывая на продолжение того спора. Но я уже, если честно, пожалел о том, что поддался на провокации. )) Потому что еще в тот раз было дано объяснение с намного большей степенью подробности, чем сейчас.


S>Потому что если вдруг VM начала использовать N потоков (или если мы тупо запустили 2 инстанса VM на одной машине), то без примитивов мы получаем гарантию мусора.


Да. Вот именно поэтому я уделил приличную часть этого поста
Автор: vdimas
Дата: 12.06.15
рассуждениям о том, что есть "контекст" в жабаскрипте и почему к одному "контексту" обязательно будет только один системный поток в один момент времени... даже если у нас VM многопоточная, как Node.js. Эти гарантии даются языком ECMAScript в неявном и явном виде.


S>Да, это так. Но вот эту уверенность лучше основывать на чём-то надёжнее, чем "я пока ни разу такого не видел".


Дык, у нас любой код пляшет от неких гарантий. Например, GUI-поток в виндах. Это же тоже гарантия, не? Ты же наверняка поупражнялся достаточно в GUI на клиентских приложениях в своё время? Думаю, ты пользовался знанием о том, где у тебя GUI-поток, а где нет. Более того, даже если в приложении было больше одного GUI-потока, ты всё-равно понимал детали происходящего. Например такие, что к некоторому окошку придут сообщения только из того потока, в котором это окошко создано.

С дотнетом 4.0 и выше идут 3 шедуллера Task-ов в комплекте, и об одном из них так и говорится — вот этот шедуллер основан на GUI-очереди сообщений, со всеми сопутствующими гарантиями. Пользуйтесь, если желаете.


S>Потому что я видел много "многопоточного" кода, который уверенно работал ровно до момента запуска на многоядерной машине.


Ну значит, он не работал и на одноядерной. ))
Потому что прерывания ядра — они такие, беспощадные, сцуко.
Бывают даже посреди операции i++.
Просто вероятность проявления ошибок на одноядерной машине была низка. Низкая вероятность проявления ошибки и отсутствие ошибки — это две большие разницы. Я же веду рассуждения именно об отсутствии ошибки в том, чтобы полагаться на однопоточный доступ к "контексту" жабаскрипта. Это как окно GUI — для каждого отдельного окна GUI гарантируется вызов событий только в одном системном потоке в один момент времени... Даже если этот поток переползет на другое ядро в процессе своей жизни. Точно так же и Node.js, даже если событие к некоему контексту будет обработано потоком из пула потоков, гарантируется, что в один момент времени контекст будет выполнять свой скриптовый код только из одного потока.


S>Ну, для этого придётся специально постараться. Но это будет ожидаемым поведением — важное выделено. В наивной реализации блокируюшего IO заблокируется вообще весь мир, а не только зависимые таски.


Традиционно блокирующее IO используется только в приватных потоках. Поэтому весь мир прекрасно живет даже в случае блокирующих потоков. И я не хочу спорить тут о сценариях, когда это плохо (твои 10тыщ соединений к серваку), бо намного больше сценариев, когда это работает намного-намного эффективней асинхронного ввода-вывода (раза в 2-3). Я как раз по работе этим занят. Кароч, под разные сценарии подходят разные решения.

В любом случае, это всё ушло далеко от первоначального спора. Потому что тому, что ты утверждаешь, у меня нет поля для возражения — только для уточнения. В общем, здравствуй переливание из пустого в порожнее.


S>Просто обычно вытесняющая многозадачность — адски дорогая. Поэтому лучше иметь кооперативную многозадачность с примитивами синхронизации.


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

Потому что дороговизна "традиционной" вытесняющей многозадачности складывается из следующих составляющих:
— смена юзверского контекста на ядерный;
— "тупой шедулер"; тупой, потому что ему недоступны прикладные зависимости м/у потоками, поэтому системный шедуллер каждый божий раз пробегается по ВСЕМ ожидающим примитивам синхронизации в надежде отыскать поток, который уже пора разбудить;

Поэтому-то CRITICAL_SECTION в 99.9% случаев обходится простым InterlockedCompareExchange и InterlockedIncrement, а создаёт ядерный семафор только в случае относительно долгого конфликта на ресурсе (такого, который не успел рассосаться за время spin-wait).

Вернемся к кооперативной асинхронщие.
Если использовать "асинхронные мьютексы", как предлагает Ikemefula, то мы поимеем аналог описанного "тупого шедулера" в полный рост.
Именно поэтому в асинхронщине более принято явно обозначать зависимости м/у задачами, а не "огораживать" ресурсы.

Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать. Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
Автор: vdimas
Дата: 13.06.15
(см function onKeyboard(nextChar) в сниппете по ссылке), — считай "разбудит" тот самый выделенный процесс, который пишет в файл. В этом и суть — что не шедуллер каждый раз проверяет "асинхронный мьютекс", (а на деле — вхолостую запускает задачу, а она, после обнаружения холостого запуска ставит сама себя в конец очереди и так бесконечно по кругу), вместо этого тупого алгоритма мы по-умному должны "разбудить" асинхронный процесс тогда и только тогда, когда ему есть что делать. И я вижу тут замечательнейшую на 100% надежную детерминированность и отсутствие всяких гонок.
Отредактировано 17.06.2015 8:51 vdimas . Предыдущая версия .
Re[27]: Mногопоточность: C++ vs Erlang vs другие
От: Evgeny.Panasyuk Россия  
Дата: 17.06.15 10:14
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Т.е. лямбда создаётся на стеке, но при сохранении её в std::function, происходит создание её копии в куче, потому что объект function устроен как-то так (схематично):


Естественно оно будет в общем случае в куче, так как происходит стирание типа, и соответственно размера.

EP>>И почему stackless корутина должна размещаться в каком-то другом месте?

V>Потому что, как и в случае std::string, для которого тоже есть некая оптимизация "маленьких" значений, реальный размер корутины заранее предугадать невозможно.

Это "потому что" никак не отвечает на поставленный вопрос. При стирании типа (как в std::function или .then), это справедливо и для передачи замыкания-лямбды, и для передачи корутины.
Как ответ на вопрос нужно показать чем объект-корутина отличается от лямбды в этом контексте, и почему её нужно размещать в другом месте. Ты же привёл общую для них характеристику, никак не обосновывающую необходимость отличий при размещении.

V>>>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.

EP>>А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Если используем future, то у нас в любом случае будет выделение памяти из кучи. Я лишь предлагаю свести кол-во выделений к минимуму, реализовав корутину как наследника future, либо как в случае с make_shared, просто расположив оба объекта в одном куске памяти (что фактически идентично с т.з. использования памяти). И я УВЕРЕН, что это именно так и будет. Даже могу поспорить на денюжку. )) Сорри, но это слишком очевидно, чтобы это "промухать". Не промухают, я уверен.

Подобная оптимизация возможна и для обычных замыканий, и для объектов-корутин которые я предлагаю — так как внутри .then мы знаем их размер, и можем аллоцировать их вместе с другими аллоцируемыми объектами за одну аллокацию (как в make_shared). Причём код оптимизации будет идентичным для обоих случаев, и авторам этой оптимизации вообще ничего не нужно знать о том что существуют ещё какие-то корутины.

В случае же proposal от microsoft, корутина аллоцируется своим отдельным аллокатором. И даже если оптимизация подобная make_shared и возможна — то автор future должен знать о том что у замыкания есть свой аллокатор, и писать отдельный код для этого случая.
Причём это относится не только к какой-то одной реализации future — а ко всем подобным. Специальный код должен быть в каждом случае.

EP>>Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?

V>Не надо пример. Я, как раз, понимаю о чем речь, но ты не вникаешь в суть моих вопросов. Я всегда спрашиваю одно и то же — какой будет тип результирующего объекта?

Посмотри ещё раз сюда
Автор: Evgeny.Panasyuk
Дата: 12.06.15
— у корутины есть тип, имя этого типа задаётся объявлении корутины, то есть struct coroutine, или с синтаксическим сахаром — future<void> coroutine().
Это обычный тип, никакой магии.

V>Можно ли объявить переменную этого типа БЕЗ объявления корутины, а реальную корутину присвоить "потом" — как в твоём сценарии сериализации?


Конечно можно — это банальное type erasure, такое же как и в std::function.

V>>>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.

EP>>Зачем?
V>Для рекурсии. В т.ч. всевозможной неявной, через вызовы, скажем, захваченных в лямбду методов-переменных.

Только в случае корутинной рекурсии. То есть:
1) если в корутине вызывается обычная рекурсивная функция типа quicksort — то используется стандартный стэк.
2) если в корутине вызывается другая корутина, без рекурсии, то никакой динаимики — размер обеих известен во время компиляции.
3) если происходит простой рекурсивный вызов корутины, то получим ошибку incomplete type, который обходится динамикой, конкретнее — стэком корутин.

Не вижу в этом проблемы. В proposal от Microsoft динамика же будет во всех трёх случаях.

EP>>Вложенная корутина будет просто полем объекта внешней корутины

V>Ты забыл, что корутина у нас stack-less, поэтому стек ей придётся нарисовать ручками. И этот стек — штука динамическая, увы))
V>Поэтому — в куче.

Только в случае рекурсивных корутин

EP>>Вот пример, в нём нет никаких аллокаций в куче

V>(скипнул пример)
V>В этом примере нет, ес-но. Потому что нет недетерминированного стека вызовов.

А в proposal от Microsoft есть аллокации, хотя их вообще тут не должно быть.
Re[29]: Mногопоточность: C++ vs Erlang vs другие
От: Sharov Россия  
Дата: 17.06.15 10:17
Оценка: :))
Здравствуйте, Evgeny.Panasyuk, Вы писали:

V>>Я тебе на это уже отвечал — на примере C# видно, что корутина (произвольного размера) создаётся в куче, реализует некий публичный интерфейс, а локально мы имеем лишь ссылку на этот интерфейс.


EP>Ты перескакиваешь с темы на тему.


Нормальный метод coroutine'ого общения.
Кодом людям нужно помогать!
Re[24]: Почему Эрланг
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.15 11:04
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Например, в моём ТЗ относительно "одновременных" записей сообщений в файл, этот файл НЕ НАДО лочить никаким асинхронным мьютексом, надо просто создать выделенный асинхронный процесс записи в файл, т.е. назначить файлу одного "владельца" и создать очередь из объектов-сообщений для записи в файл (или же из их сериализованных в байты тел — на вкус и цвет, как грится), где выделенный процесс будет эту очередь разгребать.


Такая очередь, если выделить её в отдельный компонент/функцию, и будет тем самым мутексом или семафором.

var operation = queued('resourceId', operationImpl, 2); 
// последний аргумент - количество одновременных тасков, 1 = мутекс, >1 = семафор

//в разных задачах можно спокойно вызывать operation


>Вот так решаются подобные задачи в асинхронщине — через зависимости. Потому что, если очередь пуста, то операция записи в такую очередь породит зависимость
Автор: vdimas
Дата: 13.06.15
(см function onKeyboard(nextChar) в сниппете по ссылке), — считай "разбудит" тот самый выделенный процесс, который пишет в файл. В этом и суть — что не шедуллер каждый раз проверяет "асинхронный мьютекс", (а на деле — вхолостую запускает задачу, а она, после обнаружения холостого запуска ставит сама себя в конец очереди и так бесконечно по кругу)


Асинхронному мутексу не надо ничего проверять. Он извлекает колбек из очереди и вызывает его. Если вызывающий код был готов писать в файл, то это значит, что все конкурирующие задачи или отработали или еще не начинали, а стало быть ресурс свободен.
Re[28]: Почему Эрланг
От: Ночной Смотрящий Россия  
Дата: 17.06.15 16:54
Оценка:
Здравствуйте, Ikemefula, Вы писали:

НС>>https://msdn.microsoft.com/en-us/library/dd998369.aspx

I>Так себе. Win.js применяется чуть менее чем нигде, а бОльшую часть js кода вижла даже дебажить толком не умеет.

Я не знаю что там с JS, но для дотнета этот тул показывает вполне подробную картину.
Re[29]: Почему Эрланг
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.15 17:08
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>https://msdn.microsoft.com/en-us/library/dd998369.aspx

I>>Так себе. Win.js применяется чуть менее чем нигде, а бОльшую часть js кода вижла даже дебажить толком не умеет.

НС>Я не знаю что там с JS, но для дотнета этот тул показывает вполне подробную картину.


Я в курсе, но это не интересно, потому что речь шла про JS, в частности — Node.
Re[30]: Почему Эрланг
От: Ночной Смотрящий Россия  
Дата: 17.06.15 17:26
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Я в курсе, но это не интересно, потому что речь шла про JS, в частности — Node.


Тем не менее сей тул показывает принципиальную возможность решения проблем и для JS.
Re[31]: Почему Эрланг
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.15 17:34
Оценка: :)
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Я в курсе, но это не интересно, потому что речь шла про JS, в частности — Node.


НС>Тем не менее сей тул показывает принципиальную возможность решения проблем и для JS.


Это неинтересно. В отладке имеет значение только то, что у тебя под рукой.
Re[32]: Почему Эрланг
От: Ночной Смотрящий Россия  
Дата: 17.06.15 17:38
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Это неинтересно. В отладке имеет значение только то, что у тебя под рукой.


Что то я не видел в предыдущем твоем вещании упоминания того, что это касается проблем конкретного инструментария.
Re[33]: Почему Эрланг
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 17.06.15 19:35
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Это неинтересно. В отладке имеет значение только то, что у тебя под рукой.


НС>Что то я не видел в предыдущем твоем вещании упоминания того, что это касается проблем конкретного инструментария.


Намекаешь, что мне в каждом сообщении напоминать, что я говорю в основном про нод ?
Re[24]: Почему Эрланг
От: BulatZiganshin  
Дата: 17.06.15 23:30
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>А как по твоему два процесса смогут работать с одним файлом, что бы гарантировать определенную последовательность записей ?

I>

а ровно так же, как и один процесс. просто не использовать yield в середине логичексой операции
Люди, я люблю вас! Будьте бдительны!!!
Re[24]: Почему Эрланг
От: BulatZiganshin  
Дата: 17.06.15 23:33
Оценка:
Здравствуйте, vdimas, Вы писали:

BZ>>я посмотрел windows.h от win 3.1 — не было там никаких CS и прочих мьютексов.


V>В Win32s для win 3.1 было.


win32s — это эмуляция win32 поверх win16, и оно там понадобилось ровно для того чтобы больше приложений написанных для nt, могло под win3.1 работать. но реализация была видимо такая как я изложил

BZ>>и на твой вопрос ответ — нет. при использовании синронных операций работы с файлами это ничем не отличается от записи в одном потоке


V>Ну я надеялся на вопрос от Ikemefula относительно использования асинхронной записи. ))

V>Там даже в асинхронном случае ничего такого не надо.

я так понимаю, под асинхронными тут понимаются всё та же кооперативная многопоточность, просто с колбеками вместо сопрограмм, что на ответ не влияет
Люди, я люблю вас! Будьте бдительны!!!
Re[28]: Почему Эрланг
От: BulatZiganshin  
Дата: 17.06.15 23:43
Оценка:
Здравствуйте, Ikemefula, Вы писали:

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


винда изначально была графической оболочкой, загружавшей несколько сопрограмм из разных exe-файлов. и весь api там был сконцентрирован на графике, очереди сообщений, перемещаемой памяти (для real mode). из всех "примитивов синхронизации" — только Yield()

а файловые локи появились где-то в dos 3.2 для работы с файлами в сети, и поддерживались всякими сетевыми клиентами, а не виндой
Люди, я люблю вас! Будьте бдительны!!!
Отредактировано 17.06.2015 23:45 BulatZiganshin . Предыдущая версия .
Re[14]: Mногопоточность: C++ vs Erlang vs другие
От: Sinclair Россия https://github.com/evilguest/
Дата: 18.06.15 05:37
Оценка:
Здравствуйте, vdimas, Вы писали:

V>А разве по нему можно пулять произвольные сообщения?

А почему нет? https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.