Сообщение Re[25]: Mногопоточность: C++ vs Erlang vs другие от 13.06.2015 10:50
Изменено 13.06.2015 10:52 Evgeny.Panasyuk
Здравствуйте, vdimas, Вы писали:
EP>>Никакое не ЧТД
EP>>Что мешает вот это:
EP>>
EP>>
V>То, что future<void> — это value-type, который владеет через shared над future_shared_state.
И как это мешает?
V>>>Так вот, если уши торчат, как в твоём примере, то нафига это тянуть в стандарт?
EP>>Я не предлагаю в стандарт тянуть эмуляцию на макросах. Ещё раз, я показываю как оно может быть устроенно внутри.
V>Я прекрасно понимаю, как оно устроено изнутри. Но я, хоть убей, не могу понять, как ты собрался реализовать свои желания с т.з. системы типов C++?
V>Вот у нас есть тип std::future, который устроен примерно так:
V>
V>Т.е. внутри него всего одно поле и sizeof(future<>) скорее всего совпадет с sizeof(shared_state_).
V>Где ты предлагаешь разместить аналог своего asio::coroutine в future<>?
Там же где и обычное обычное замыкание-продолжение.
Абстрагируйся от asio::coroutine, представь простое замыкание-продолжение. Например у нас вместо:
V>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.
А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Другое дело:
V>
V>Т.к. тип iterator<> еще не специфирован, вполне возможно, что у него будет некое зарезервированное поле, в котором можно поместить целочисленную переменную — состояние автомата-корутины.
Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?
V>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.
Зачем? Вложенная корутина будет просто полем объекта внешней корутины
Вот пример, в нём нет никаких аллокаций в куче (Live Demo on Coliru):
EP>>Никакое не ЧТД
EP>>Что мешает вот это:
EP>>
EP>>future<void> coroutine() ...
Преобразовать вот в это:EP>>
EP>>struct coroutine : asio::coroutine ...
EP>>
?V>То, что future<void> — это value-type, который владеет через shared над future_shared_state.
И как это мешает?
V>>>Так вот, если уши торчат, как в твоём примере, то нафига это тянуть в стандарт?
EP>>Я не предлагаю в стандарт тянуть эмуляцию на макросах. Ещё раз, я показываю как оно может быть устроенно внутри.
V>Я прекрасно понимаю, как оно устроено изнутри. Но я, хоть убей, не могу понять, как ты собрался реализовать свои желания с т.з. системы типов C++?
V>Вот у нас есть тип std::future, который устроен примерно так:
V>
V>template<class T>
V>class future {
V>...
V> shared_ptr<shared_state> shared_state_;
V>}
V>
V>Т.е. внутри него всего одно поле и sizeof(future<>) скорее всего совпадет с sizeof(shared_state_).
V>Где ты предлагаешь разместить аналог своего asio::coroutine в future<>?
Там же где и обычное обычное замыкание-продолжение.
Абстрагируйся от asio::coroutine, представь простое замыкание-продолжение. Например у нас вместо:
future<int> sum()
{
int x = await foo();
int y = await bar();
return x + y;
}
есть ручное нарезание на продолжения:future<int> sum()
{
return foo().then([](int x)
{
return bar().then([=](int y)
{
return x + y;
});
});
}
Где по-твоему здесь размещаются эти продолжения? И почему stackless корутина должна размещаться в каком-то другом месте?V>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.
А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Другое дело:
V>
V>iterator<T> generate() resumable {
V> yield return 1;
V> yield return 2;
V>};
V>
V>Т.к. тип iterator<> еще не специфирован, вполне возможно, что у него будет некое зарезервированное поле, в котором можно поместить целочисленную переменную — состояние автомата-корутины.
Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?
V>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.
Зачем? Вложенная корутина будет просто полем объекта внешней корутины
Вот пример, в нём нет никаких аллокаций в куче (Live Demo on Coliru):
struct first_coroutine : asio::coroutine
{
unsigned i;
int operator()()
{
reenter(*this)
{
for(i = 0; ; ++i)
yield return i;
}
};
};
struct second_coroutine : asio::coroutine
{
first_coroutine inner;
int operator()()
{
reenter(*this)
{
while(true)
yield return [b] inner()[/b] * 2;
}
};
};
int main()
{
second_coroutine c;
for(int i=0; i!=5; ++i)
cout << c() << endl;
}
Вывод:0
2
4
6
8
Re[25]: Mногопоточность: C++ vs Erlang vs другие
Здравствуйте, vdimas, Вы писали:
EP>>Никакое не ЧТД
EP>>Что мешает вот это:
EP>>
EP>>
V>То, что future<void> — это value-type, который владеет через shared над future_shared_state.
И как это мешает?
V>>>Так вот, если уши торчат, как в твоём примере, то нафига это тянуть в стандарт?
EP>>Я не предлагаю в стандарт тянуть эмуляцию на макросах. Ещё раз, я показываю как оно может быть устроенно внутри.
V>Я прекрасно понимаю, как оно устроено изнутри. Но я, хоть убей, не могу понять, как ты собрался реализовать свои желания с т.з. системы типов C++?
V>Вот у нас есть тип std::future, который устроен примерно так:
V>
V>Т.е. внутри него всего одно поле и sizeof(future<>) скорее всего совпадет с sizeof(shared_state_).
V>Где ты предлагаешь разместить аналог своего asio::coroutine в future<>?
Там же где и обычное обычное замыкание-продолжение.
Абстрагируйся от asio::coroutine, представь простое замыкание-продолжение. Например у нас вместо:
V>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.
А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Другое дело:
V>
V>Т.к. тип iterator<> еще не специфирован, вполне возможно, что у него будет некое зарезервированное поле, в котором можно поместить целочисленную переменную — состояние автомата-корутины.
Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?
V>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.
Зачем? Вложенная корутина будет просто полем объекта внешней корутины
Вот пример, в нём нет никаких аллокаций в куче (Live Demo on Coliru):
EP>>Никакое не ЧТД
EP>>Что мешает вот это:
EP>>
EP>>future<void> coroutine() ...
Преобразовать вот в это:EP>>
EP>>struct coroutine : asio::coroutine ...
EP>>
?V>То, что future<void> — это value-type, который владеет через shared над future_shared_state.
И как это мешает?
V>>>Так вот, если уши торчат, как в твоём примере, то нафига это тянуть в стандарт?
EP>>Я не предлагаю в стандарт тянуть эмуляцию на макросах. Ещё раз, я показываю как оно может быть устроенно внутри.
V>Я прекрасно понимаю, как оно устроено изнутри. Но я, хоть убей, не могу понять, как ты собрался реализовать свои желания с т.з. системы типов C++?
V>Вот у нас есть тип std::future, который устроен примерно так:
V>
V>template<class T>
V>class future {
V>...
V> shared_ptr<shared_state> shared_state_;
V>}
V>
V>Т.е. внутри него всего одно поле и sizeof(future<>) скорее всего совпадет с sizeof(shared_state_).
V>Где ты предлагаешь разместить аналог своего asio::coroutine в future<>?
Там же где и обычное обычное замыкание-продолжение.
Абстрагируйся от asio::coroutine, представь простое замыкание-продолжение. Например у нас вместо:
future<int> sum()
{
int x = await foo();
int y = await bar();
return x + y;
}
есть ручное нарезание на продолжения:future<int> sum()
{
return foo().then([](int x)
{
return bar().then([=](int y)
{
return x + y;
});
});
}
Где по-твоему здесь размещаются эти продолжения? И почему stackless корутина должна размещаться в каком-то другом месте?V>Я бы его разместил в объекте-наследнике того самого shared_state, который, в свою очередь, создаётся на куче.
А здесь можно вообще не менять ни сам future, ни лезть в его внутренности (типа наследования от shared_state). Потому что используем ли мы обычные продолжения, или объект-автомат (ручной или сгенерированный stackless coroutine) — это совершенно ортогонально тому где мы их размещаем.
V>Другое дело:
V>
V>iterator<T> generate() resumable {
V> yield return 1;
V> yield return 2;
V>};
V>
V>Т.к. тип iterator<> еще не специфирован, вполне возможно, что у него будет некое зарезервированное поле, в котором можно поместить целочисленную переменную — состояние автомата-корутины.
Ты понимаешь что над корутинами из Boost.Asio можно сделать обёртку-итератор, в котором полностью будет хранится вся корутина? Или показать пример?
V>Если твоя легковесная корутина будет содержать в себе другие корутины, то нужно эмулировать стек для их правильного обхода. И тут уже, извини, но без выделения памяти в куче — никак.
Зачем? Вложенная корутина будет просто полем объекта внешней корутины
Вот пример, в нём нет никаких аллокаций в куче (Live Demo on Coliru):
struct first_coroutine : asio::coroutine
{
unsigned i;
int operator()()
{
reenter(*this)
{
for(i = 0; ; ++i)
yield return i;
}
};
};
struct second_coroutine : asio::coroutine
{
first_coroutine inner;
int operator()()
{
reenter(*this)
{
while(true)
yield return inner() * 2;
}
};
};
int main()
{
second_coroutine c;
for(int i=0; i!=5; ++i)
cout << c() << endl;
}
Вывод:0
2
4
6
8