<<<предыдущий список следующий>>>

Это - копия документа, находившегося на http://dz.ru. Авторские права, если не указано иначе, принадлежат Дмитрию Завалишину и/или Евгении Завалишиной. Все изменения, внесенные мной, находятся в этой рамочке.Пожалуйста, прочитайте disclaimer.


3 января

Война по поводу противодействия нитей и select в форуме достигла масштабов мировой и уже перелилась в формы отвратительно конеретные. Люди добрые, можно ли так далеко уходить от милой моему сердцу абстракции к каким-то суетным реалиям? :-)

Началось-то всё с чего, кто помнит? Дядька один операционку делал. Новую. Новую! У него не было ваших проблем с реализацией (точнее, её отсутствием до сих пор) в Юниксе нитей. У него не было проблем сделать её такой, какая нужна.

Теперь о многомашинности. Конечно, умение написать задачу так, чтобы она раскладывалась на несколько машин, а не процессоров - это сильно и круто. Только при чём тут противостояние select и нитей - мне невдомёк. Оба способа тут - не помощники.

Теперь об ОО и его будто бы ортогональности. Гм. Гм. Умное слово, товарищ, хорошо к месту. Здесь оно - не. Семантика процеcса и его ОО-ность не ортогональны, и не надо трогать Оккама. Процесс явно отвечает требованиям инкапсуляции, а как только у него появляются вызываемые извне точки входа, он автоматически, вне зависимости от того, любите вы ОО или нет, подпадает под определение объекта и отвечает требованиям о полиморфизме и даже, в некоторой мере, наследование (fork) присутствует. Правда, отсутствует типизация в смысле C++, но этого никто, собственно, не требовал - можно, без проблем можно иметь язык, тип каждого объекта в котором уникален. Ну или можно считать типом объекта-процесса идентификатор его исполняемого образа - это даже правомерно. (Одно "но" - если считать типом исполняемый образ, то fork - не есть наследование. Объектность получается ущербная. Да она, собственно, и есть ущербная при такой реализации. Никто и не спорит.:)

Ещё раз для измученных нарзаном объектности людей: это не я предлагаю вам считать процессы с точками входа объектами. Это - по определению. Оно просто так есть, хотя это, конечно, омерзительно и чрезвычайно обидно. Эта проклятая объектная парадигма такова, что подпасть под неё очень несложно. Нужно обладать всего несколькими простыми свойствами, достаточно очевидными в смысле их разумности и за пределами парадигмы. А как только ты эти свойства обрёл - оп, и ты уже объектный. И не хватайся за Оккама - только порежешься.

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

"Она [программа -- dz] "одномерна""

Ни-ког-да. (Ну, почти.:) Обычный программерский самообман. Как только есть два сокета - программа уже не одномерна и уже решает задачу синхронизации. В случае с тривиальным

while( EOF != (c = getchar()) ) putchar(c);

синхронизация тоже есть, она просто "дефолтовая", от балды. И семафоры есть - только они все попрятаны в ядре и потому незадачливому программисту кажется, что он избавился от проблемы. На практике он запихал её сапогами с глаз долой в чулан и переложил головную боль с себя на ОС. Это приемлемо, когда человек понимает, что делает. Но если тот же человек говорит, что с применением нитей и коллбэков задача УСЛОЖНЯЕТСЯ - он явно не понимает, что делает. Потому что задача не меняется - лишь реализация её является ему на глаза из глубин ОС. Не ПОявляется - она всегда была. Просто выныривает.

И код вида

char c;


thread1()
	{
	while(1)
		{
		wait for sema to be set;
		c = getchar();
		clear sema;
		}
	}


thread2()
	{
	while(1)
		{
		wait for sema to be clear;
		putchar(c);

		set sema;
		}
	}

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

Теперь представим себе, что все внешние события приходят в процесс сами, что у процесса есть точки входа, которые вызываются ядром (или другими процессами) по факту свершения события. Асинхронного, конечно. Например, по факту прибытия данных из сокета или пайпа.

call_this_on_socket_data_available( char *data, int len )

	{
	write( socket2_fd, data, len ); // не помню порядок аргументов уже, но не суть
	}

Отметим - этот код опять делает то же самое. Читает из одной дырки и пишет прочитанное в другую. Чем он лучше? Здесь отсутствует одна точка синхронизации - та, что "wait for sema to be set;" в предыдущем варианте. Источник больше не ждёт нашей готовности. Чем он хуже? Здесь отсутствует одна точка синхронизации. Источник больше не ждёт нашей готовности. Следовательно, отсутствует flow control и если входящий поток не пролезает в выходное отверстие система ляжет, запустив слишком много нитей-экземпляров обработчика этого события.

Как избежать? Тривиально - назначить предел по числу запущеных экземпляров, например.

Что получаем в итоге? Получаем много. Получаем адекватную семантику. Не приемлемую, как в случае с select, не кое-как пригодную, а отражающую суть вещей. Это важно, потому что позволяет решать задачи не через анальное отверстие автогеном, а по-человечески. Сделать из многомерного пространства одномерное посредством запихивания всего мира в прокрустово ложе select-а можно. Можно. Иногда и нужно. Но следует же отдавать себе отчёт в том, что многомерность при этом не исчезла, а кастрирована. Грубо, топором. После этого всё становится проще (не нужны семафоры), но это - не решение задачи, а уход от него.

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

Знаете, чего мне не хватает в фотошопе? Какой-то ерунды. (Экая параллель с предыдущей темой!) Многомерности структуры слоёв.

Если кто не знает - фотошоп располагает системой слоёв - (полу)прозрачных "калек", на которых можно рисовать - итоговый рисунок получается складыванием их в стопочку - нижние видны сквозь "дырки" в верхних. Например:

+ + +

Результат:

Просто, доступно, удобно. Масса возможностей. Но этого мало. Хочется вставить слой, каждая точка которого бы была селектором. Если она белая - то итог берём из первой стопки слоёв. Если чёрная - то из второй. То есть вместо одномерной пачки калек хочется иметь их целое дерево. Нет ли наших в Адобе? Передали бы разработчикам, что ли, пожелание. :-)

Человек и Интернет.

На сайте metro.ru, в гостевой книге, наблюдаю лаконичную запись: "снисте цену на доргу". Четыре слова, а сколько в них информации!

Читатели попеняли мне по поводу моей фразы про переход через границу века. Господа - позвольте три соображения.

1. Для компьютеров границей века является точка, в которой единичка в левом разряде сменилась двойкой. Хоть ты лопни, а у них новый век настал, что бы мы тут себе ни решили. О чём и шла речь.

2. "Нулевого года не было, значит, начало века - 2001-й год." Аргумент не принят - первого года тоже не было, и второго, и даже тысячного. Значит ли это, что начало века откладывается более, чем на тысячу лет? Нет, конечно.

3. Фраза "тысяча лет с рождества Христова", а именно она имеется в виду, когда мы пишем "0:00 1 Янв 1000 г" означает, что с момента первого крика младенца прошла одна тысяча лет. Отмечу: прошла. Не "настал тысячный год", а "прошла одна тысяча лет". Какой год настал - неизвестно. Существует два метода счёта. Правильный (когда первый год настаёт, когда Христу исполняется год) и человеческий (когда первым называют тот год, когда Иисус родился). Выбирать тот или иной способ можно лишь одним путём - постановив, что он наступает тогда-то.

Далее, поскольку это влияет лишь на решение одного вопроса, а именно - когда и сколько выпить водки, то правильный ответ очевиден. Новый век наступает дважды. :-)