![]() ![]() ![]()
Какой рейтинг вас больше интересует?
|
![]()
go to II2015-07-15 21:19:06 (читать в оригинале)Арсенал команд большинста процессоров для организации ветвлений исчерпывается различными видами условных переходов. Первые программисты за первые пару десятков лет неплохо научились ими пользоваться для создания довольно больших программ. После появления языков программирования высокого уровня, накопленные техники никуда не исчезли. Одна из самых важных gotoборческих статей написана Эдсгером Дейкстрой в 1968-ом году (кстати, бложек Дейкстры http://www.cs.utexas.edu/users/EWD/ - это один из лучших бложиков ever). После непродолжительного десятилетнего флейма gotoборцы забороли gotoфилов. Победила точка зрения, что процедур/while/if достаточно для всего. Несмотря на эту яркую победу, широкое использование goto прекратилось лишь более-менее с выходом на тот или иной род пенсии людей, которые этому стилю обучились в молодости. Не стоит недооценивать силу плохого, но систематического образования. Я, например, хвастаться тут нечем, тоже пишу последние пятнадцать лет в стиле, которому был обучен еще в старших классах школы. Я с большим интересом слежу за реинкарнацией goto на новом техническом уровне. Отчего-то мне, старперу, вся это любовь к лямбда/горутинам/async/await кажется в большинстве случаев неуместным способом ускорить фазу написания кода в ущерб его читаемости. А ведь чтение кода занимает большинство времени в реальных проектах. Не, конечно, корутины/горутины/fibers предоставляют совершенно былинные возможности по управлению графом выполнения. Например, можно преобразовать генератор на callback'ах в IEnumerator без модификации самого генератора: #include <windows.h> #include <iostream> #include <vector> #include <string> using namespace std; class ICallback { public: virtual void OnToken(char ch) = 0; virtual ~ICallback() { } }; class TSplitter { public: void Split(const string& s, ICallback* callback) { auto p = s.begin(); while (s.end() != p) { callback->OnToken(*p); ++p; } } }; typedef vector<char> TBuffer; void __stdcall FiberFunctionSplitter(void* param); class TFiberIteratorContext : public ICallback { private: bool m_hasNext; char m_value; public: TSplitter m_splitter; string m_string; LPVOID m_mainFiber; LPVOID m_fiberSplitter; TFiberIteratorContext(const string& s, LPVOID mainFiber) : m_hasNext(true) , m_string(s) , m_mainFiber(mainFiber) { m_fiberSplitter = CreateFiber(1 << 16, FiberFunctionSplitter, this); } void Run() { SwitchToFiber(m_fiberSplitter); } virtual void OnToken(char ch) { m_value = ch; SwitchToFiber(m_mainFiber); } bool HasNext() const { return m_hasNext; } char Value() const { return m_value; } void Next() { SwitchToFiber(m_fiberSplitter); } void Eof() { m_hasNext = false; SwitchToFiber(m_mainFiber); } }; void __stdcall FiberFunctionSplitter(void* param) { TFiberIteratorContext* context = reinterpret_cast<TFiberIteratorContext*>(param); context->m_splitter.Split(context->m_string, context); context->Eof(); } int main() { try { LPVOID mainFiber = ConvertThreadToFiber(NULL); TFiberIteratorContext fiberContext("123456789", mainFiber); fiberContext.Run(); while (fiberContext.HasNext()) { cout << fiberContext.Value(); fiberContext.Next(); } cout << endl; } catch (...) { cout << "exception" << endl; } return 0; } Я даже не понимаю, почему столь широкие возможности fibers не были по достоинству оценены разработчиками, заботящимися о своей job security. Но все проблемы с читаемостью горутин, конечно, меркнут по сравнению проблемами, возникающими с некоторыми попытками написать многопоточную программу. Вот там есть настоящий простор для головоломок, к решению которых мозг человека никак не приспособлен.
|
![]() ![]()
Категория «Радио»
Взлеты Топ 5
Падения Топ 5
![]()
Популярные за сутки
|
Загрузка...

BlogRider.ru не имеет отношения к публикуемым в записях блогов материалам. Все записи
взяты из открытых общедоступных источников и являются собственностью их авторов.
взяты из открытых общедоступных источников и являются собственностью их авторов.