Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: Сопрограммы в языке программирования C  (Прочитано 158506 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« : 18-10-2010 08:37 » 

Обсуждение статьи: «Сопрограммы в языке программирования C»
« Последнее редактирование: 02-08-2011 19:27 от RXL » Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 20-10-2010 09:37 » 

У меня шок! Не думал, что такое можно скомпилировать...

Код:
    switch (count % 8) {
        case 0:        do {  *to = *from++;
        case 7:              *to = *from++;
        case 6:              *to = *from++;
        case 5:              *to = *from++;
        case 4:              *to = *from++;
        case 3:              *to = *from++;
        case 2:              *to = *from++;
        case 1:              *to = *from++;
                       } while ((count -= 8) > 0);
    }

Проверил - GCC принимает.

Материал трудно читается. Причина - не понятно, о чем идет речь и что означают приведенные подпрограммы. Разбираться в их работе или переходить по ссылкам не очень хочется. Лучше вкратце описать задачу.

Добавлено через 13 минут и 5 секунд:
Весь текст нуждается в правке форматирования, но это сделаем в конце, после рецензирования.
« Последнее редактирование: 20-10-2010 09:50 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 20-10-2010 09:58 » 

Ром, case X: - это всего лишь метка (как для goto, но только внутри блока switch)

но такую оптимизацию лично я бы только в белых тапочках видел ))
« Последнее редактирование: 20-10-2010 10:00 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 20-10-2010 10:32 » new

Леш, аналогично. Лучше через switch настроить набор переменных для определения состояния и начальных условий для общего алгоритма. Мне так было бы понятней. Обычный конечный автомат.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 20-10-2010 10:47 » 

У меня шок! Не думал, что такое можно скомпилировать...

"Устройство Даффа" - старый трюк, ему без малого 30 лет. Традиционно очень часто используется в холиварах типа "C vs Pascal - что круче" как доказательство крутизны C.

Материал трудно читается. Причина - не понятно, о чем идет речь...
Лучше вкратце описать задачу.

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

Без этого, наверное, статья будет плохо восприниматься. Все равно что написать о классах С++, а о принципах объектно-ориентированного подхода не сказать ни слова.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 20-10-2010 11:08 » 

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

Вот небольшой фрагмент в Википедии попался по теме:

Цитата
Прямое использование конечных автоматов программистами часто затруднено тем, что выбранный язык программирования не позволяет ясно и просто представить состояния и переходы автомата в коде (см. примеры в статье «Автоматное программирование»).

Один из удачных вариантов предложен Саймоном Тэтхемом и представляет собой способ реализации неявного конечного автомата при помощи устройства Даффа. В свою очередь, конечные автоматы были использованы Тэтхемом для реализации сопрограмм, что позволило ему реализовать задачу производителя-потребителя без использования многопоточности и сопутствующих проблем.

Тот же подход, в числе прочих, был использован и Адамом Данкелсом (Adam Dunkels) в его библиотеке «protothreads», посвящённой различным способам реализации псевдо-многопоточности при помощи неявных конечных автоматов.
« Последнее редактирование: 20-10-2010 11:11 от Dale » Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 20-10-2010 14:55 » 

Насчет нужности или ненужности подобной оптимизации - в отрыве от контекста совершенно беспредметный спор.
не соглашусь. Не хватает ресурсов - можно и нужно писать на ассемблере. Там такой изврат хоть прилично и оправданно смотрится Улыбаюсь
Записан

Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 20-10-2010 16:10 » 

Алексей1153++, не всегда. на си - тоже можно писать по разному...
например:
//подсчет единичных бит в 32 скопипастил не глядя 15 разрядном! слове.
Код:
unsigned long pop(unsigned short x)
{
    __int64 y;
    y = x * 0x0002000400080010ULL;
    y = y & 0x1111111111111111ULL;
    y = y * 0x1111111111111111ULL;
    y = y >> 60;
    return (unsigned long)y;
}
из чумовой книги Генри Уоррен, мл. "Алгоритмические трюки для программистов".
четыре операции! без цикла, без ветвлений!
PS а современные компиляторы достаточно эффективно генерят код, обычно достаточно знать каким боком в быстродействии тебе выльется та или иная операция.
« Последнее редактирование: 21-10-2010 11:03 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 20-10-2010 16:20 » 

Ochkarik, по-моему, 32 сдвига быстрее сделаются, чем это шаманство Улыбаюсь

Добавлено через 3 минуты и 50 секунд:
А ещё, я не уверен за удачное и правильно выполнение вот этого сдвига, если процессор - 32 битный
y = y >> 60;

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

0xFFFFFFFFFFFFFFFF/0x0002000400080010==7FFF
« Последнее редактирование: 20-10-2010 16:28 от Алексей1153 » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 20-10-2010 16:54 » 

Цитата
И в этом случае они были бы правы, поскольку проектирование подобных функций, ужасно затемняющих структуру алгоритма.
"затемняет", наверное
Записан

Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 20-10-2010 21:25 » 

не соглашусь. Не хватает ресурсов - можно и нужно писать на ассемблере.

А разве ассемблер добавит ресурсов? Хороший оптимизирующий компилятор C дает код прекрасного качества, и не факт, что пишущий на ассемблере сможет его превзойти. Чаще получается то же самое (или хуже, если код сложный), только гораздо большими усилиями.

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

Пару слов о том, зачем это затевалось. Дафф делал видеоэффекты для Голливуда. В частности, у него был девайс, который должен был перегонять массивы данных на ЦАП, формирующий видеосигнал (в приведенном фрагменте "*to = *from++;" to как раз указывает на регистр ЦАПа, отображенный на адресное пространство оперативной памяти). Но быстродействия процессора не хватало, чтобы в цикле выдавать видеосигнал в реальном времени (понятное дело, никакой асемблер в данном случае ничем не поможет, нужно менять сам принцип). Заказчика же покадровый режим не устраивал, он настаивал на выводе видео в реальном времени. Только описанный выверт и спас отца русской демократии Даффа от провала проекта.

В данном случае, конечно, мы не гонимся за скородействием. Просто некоторые взяли пример на вооружение и нашли ему другие применения, хотя при первом знакомстве с таким приемом наиболее естественная реакция именно такова:
У меня шок! Не думал, что такое можно скомпилировать...
Механизм сопрограмм используется при разработке встроенных систем как способ организовать мультизадачность. Если эта тема пойдет на форуме (вроде в архивах я не видел проявлений интереса к этой теме, но вдруг), можно будет ее развить, поскольку она входит в круг моих интересов.

Давайте не отклоняться от темы.

Действительно, давайте пока не будем обсуждать само содержание статьи, потому что у нас тут получается маленький междусобойчик в закрытой теме, а большинство членов клуба этого просто не увидит и никак не может поучаствовать в дискуссии. Давайте сейчас сосредоточимся на технической стороне: опечатки, ошибки, несогласованные предложения, стиль перевода,  визуальное оформление и т.д. К самой теме вернемся после публикации.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 21-10-2010 21:48 » 

У меня другое предложение - развить тему несколькими своими небольшими статьями (и, может, подходящими переводами, если попадутся).

Дело в том, что статья произвела эффект, несколько отличный от того, что я ожидал. Пока только два человека прочитали ее внимательно - вы с Алексеем ( может, были и другие, но пока промолчали), и оба в первую очередь обратили внимание на устройство Даффа, которое бросается в глаза своей парадоксальностью. Сопрограммы остались как-то в тени, на заднем плане. А ведь это - лишь трюк, который делает возможным организовать сопрограммы средствами стандартного ANSI C и тем самым заставить их работать на любой платформе (лично мне удавалось реализовать сопрограммы только средствами ассемблера, но это чистое хакерство, завязанное на особенностях архитектуры машины, ОС,  генерируемого компилятором Паскаля кода и прочих деталях, которые напрочь лишают мое решение переносимости).

Мне представляется целесообразным такой способ подачи пояснительного материала:

1. Совсем обзорно - о взаимодействии слабо связанных процессов.
2. Обзорно - проблемы синхронизации процессов.
3. Подробнее - классическая задача "производитель-потребитель", варианты ее решения.
4. Еще подробнее - сопрограммы как один из вариантов решения задачи "производитель-потребитель", плюсы и минусы такого решения.
5. Организация сопрограмм на микроконтроллере в виде автономной программы (без операционной системы).
6. Организация сопрограмм в простейших ОС реального времени.

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

Ссылки на Википедию и прочие источники тоже нужны, но в большинстве случаев они написаны очень заумным языком, и не все захотят разбираться в этих хитросплетениях. Поэтому приведу их среди собственных комментариев для тех, кто захочет копнуть тему детальнее.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 21-10-2010 22:07 » 

Dale, для меня просто пример не очень близкий)
но суть (если я правильно понял) - фактически попытка написать некий предельно простой механизм ручного переключения контекста и прозрачной передачи данных?
в суть примера мне тяжело с ходу вкурить, так как я обычно отталкиваюсь от процесса являющегося "мастером" и полностью задающего темп обработки.
PS постановку задачи я почти понял, но пока не сообразил откуда она могла бы родится в моей деятельности)
« Последнее редактирование: 21-10-2010 22:09 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 21-10-2010 22:27 » 

но суть (если я правильно понял) - фактически попытка написать некий предельно простой механизм ручного переключения контекста и прозрачной передачи данных?

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

Это действительно ручное переключение контекста, а конкретнее - разновидность кооперативной мультизадачности. Выделенного "мастера" в данном случае нет, потому что процессы полностью равноправны, а главное - ничего не знают друг о друге. Первый уверен лишь в том, что его вывод будет обработан неким партнером, а второй - что некто будет поставлять ему на вход данные.

Автору статьи принес известность в первую очередь пакет Putty. Он пишет, что реализовал протокол SecureShell через описанный в статье механизм сопрограмм.

А вообще применений такому подходу можно найти массу. Например, препроцессор некоего языка, который, ничего не зная о самом языке, отыскивает во входном потоке макросы, раскрывает их и передает на вход компилятору, который понятия не имеет о существовании макросов. Или стек протоколов, в котором модуль парсит свой уровень протокола и передает результат дальше.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 22-10-2010 09:26 » 

Dale, много статей - всегда хорошо. Будет что обсудить Улыбаюсь
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 22-10-2010 09:39 » 

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

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 22-10-2010 13:12 » 

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

насчет отсутствия "мастера" - мне это трудно представимо...  как будто процесс, генерирующий данные, оторван от всего на свете и живет своей жизнью.
тогда откуда он берет исходные данные? с внешнего устройства, с диска? - тогда мастером является внешнее устройство (прерывание например), дисковые операции. темп ввода(а соответственно и вывода) задает именно это внешнее устройство. для меня это логично и понятно)
соответственно в этом рассмотрении, четко видна последовательность обработки.
для первого - он получает данные, и передает далее, скорость его работы - обусловлена скоростью поступления данных к нему.
для второго - он просто не имеет права работать без входных данных, которые не придут к нему, пока не будут обработаны первым процессом.
вроде бы прямая последовательность. ключевой для меня вопрос - зачем ее запутывать?)
вот поэтому мне кажется не очень удачным, пример с парсером...
да, чем больше смотрю на преобразованный код парсера в функию ("parser(int c)" ),
тем больше убеждаюсь, что это не преобразование такое плохое, а просто написано так некрасиво.  код специально извращен до нечитаемости - так не честно, можно написать лучше и без сопрограмм.
PS а кроме того код преобразованный в функцию еще и не идентичен первоначальному, как мне кажется.
по мне могло бы выглядеть и так
Код:
static boolean new_word = FALSE;

void parser(int c)
{
    if (c == EOF)
        return 0; //выход из цикла, про который в parser() - забыли.

    if (isalpha(c))
    {
        add_to_token(c);
        new_word = 1;
    }
    else
    {
        if (new_word)
            got_token(WORD);
        add_to_token(c);
        got_token(PUNCT);
        new_word = 0;
    }
    return 1;
}
старался переписать дословно, в примере я не совсем понял назначения got_token(WORD)/got_token(PUNCT)
и поэтому мне непонятно, что  делать при нескольких подряд идущих !isalpha(c)...
по моему это не такой страшный код?
и вообще его можно было бы модифицировать к
Код:
static boolean new_word = FALSE;

void parser(int c)
{
    if (c == EOF)
        return 0; //выход из цикла, про который в parser() - забыли.

    add_to_token(c);
    if (!isalpha(c))
    {
        got_token(WORD);
        got_token(PUNCT);
    }
    return 1;
}
- если бы я понимал что там происходит))))

Добавлено через 7 часов, 54 минуты и 17 секунд:
PS за два дня наконец разобрался что к чему...
поправка:
Цитата
Отметим, что с Visual C++ версии 6 трюк с сопрограммами не проходит, поскольку его отладочное состояние по умолчанию (Program Database for Edit and Continue) делает нечто странное с макросом __LINE__.
- эта крайне полезная опция позволяет осуществлять модификацию участков кода в отладчике, без перезапуска исполняемого модуля.
таким образом физический смысл макроса __LINE__ - несколько плывет, так как номер строки может меняться в процессе исполнения модуля.

...ИМХО было бы полезнее начинать статью не с "непонятного парсера", а непосредственно с конечных автоматов. представить решение задачи в виде switch-case, а потом заменить их макросами. так - я понял бы быстрее Скромно так...
не пинайте сильно, но я просто сразу не въехал в сакральный смысл)
« Последнее редактирование: 22-10-2010 21:06 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 22-10-2010 21:17 » 

После обязательного пятничного пива я сразу столько не осилю, постараюсь отвечать небольшими фрагментами Улыбаюсь
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 22-10-2010 21:23 » 

Dale, поддерживаю. Причем, в основном, свою голову руками. Ага
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 22-10-2010 21:25 » 

так и я статью с первого раза не осилил)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 22-10-2010 21:53 » 

лично мне было бы понятнее если бы пример был из области ну не знаю... допустим эмуляция как раз многозадачности.

А это как раз и есть частный случай многозадачности - "кооперативная многозадачность". Та самая, давно забытая со времен 16-битных версий  Windows (впрочем, в виртуальной 16-разрядной машине Windows, которая до сих пор используется для исполнения 16-разрядных приложений) она применяется до сих пор.

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

Наша цель как раз в этом и состоит - максимально абстрагироваться от подобных деталей.

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

Может, такая аналогия немного прояснит идею. Мы проектируем некий автоматизированный измерительный стенд. У нас есть набор приборов, которые могут замерять напряжение, ток, импеданс, частоту... И есть набор интерфейсов для передачи данных по USB, Ethernet, BlueTooth, Zigbee... Мы хотим создать на их базе максимально универсальный стенд с наименьшими затратами.

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

Если мы справимся с такой задачей, то как мы определим, кто из этих модулей "мастер"? Вольтметр, который произвел очередной цикл измерения и заставляет интерфейс Ethernet передать эти данные по сети? Или сетевой интерфейс, который успешно передал очередное измерение и запускает следующий цикл измерения?

Есть третий вариант - симметричная кооперация. Вольтметр (в роли поставщика) формирует поток данных, не заботясь о том, как они будут доставлены конечному потребителю. А интерфейc Ethernet (потребитель) знает, как доставить эти данные по сети, но ему все равно, что это за данные. Именно такой, наиболее общий, вариант мы и рассматриваем.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 22-10-2010 22:30 » 

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

Именно так. "Поставщик определяет темп работы всей цепочки обработки данных.

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

Совершенно справедливо. Именно поэтому в данном случае нас не интересуют более изощренные способы мультипрограммирования вроде вытесняющей многозадачности. Даже если планировщик заданий решит, что пора отдать квант второму процессу, пользы в этом не будет ни на грош. Из всех возможных вариантов (которые я, надеюсь, рассмотрю с недалеком будущем) кооперативная многозадачность в нашем случае - самое то. А с учетом скудных ресурсов микроконтроллеров, возможно, сопрограммы - наиболее оптимальное решение.

вроде бы прямая последовательность. ключевой для меня вопрос - зачем ее запутывать?)

Вот на этот вопрос я наиболее затрудняюсь ответить. Я именно потому и ухватился за эту статью, что она внесла для меня полную ясность, как мне с наименьшими затратами труда синхронизировать некоторые процессы в устройствах, над которыми я сейчас работаю. Я интуитивно понимал, что сопрограммы спасут отца русской демократии, но меня несколько удручала перспектива реализации этого механизма на ассемблере (сам принцип устройства Даффа я, конечно, знал с 1980-х, научный руководитель заставлял нас отслеживать подобные публикации, но применить его в данном контексте в жизни бы не додумался). А мешать C и ассемблер в моем представлении - это как смешивать пиво и водку: сами по себе вещи вполне достойные, а вместе в одной посуде - так себе, да и последствия не очень...

В данном случае вся прелесть состоит не в том, что сделано (можно было и иначе выкрутиться), а в том, как это сделано (в рамках ANSI C, а значит, максимально переносимо).
« Последнее редактирование: 22-10-2010 22:37 от Dale » Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 22-10-2010 23:48 » 

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

Цитата
Вольтметр (в роли поставщика) формирует поток данных, не заботясь о том, как они будут доставлены конечному потребителю. А интерфейc Ethernet (потребитель) знает, как доставить эти данные по сети, но ему все равно, что это за данные. Именно такой, наиболее общий, вариант мы и рассматриваем.
- опять же. интерфейс Ethernet не будет отправлять данные которых нет. поэтому даже в этом случае вольтметр является мастером, то есть частота его опроса.
если скорость опроса ограничена пропускной способсностью ethernet-а, мастер - ethernet.
действительно разделение на master/slave провести сложно. однако даже в этом случае при простой последовательности "опрос данных"-"отправка данных" в цикле, проблема вроде как решается. оба устройства  все равно будут работать с максимальной скоростью, независимо от того кто ее определяет.

а вот при многозадачности или синхронизации действительно независимых процессов - смысл яснее. допустим что контроллер Ethernet-а должен отправлять данные от многих источников. функции опроса этих источников могут быть сложны и содержать массу функций ожидания, во время которых можно сделать много полезного. тогда в каждой из подзадач довольно просто выделить возможные места "перключения контекста", а вот свести все процессы воедино - довольно муторно.
тут - предложенное решение расцветает во всей красе.
я не настаиваю на ethernet и частностях. для примера действительно лучше без  них. но какой то сакральный смысл действий должен быть объяснен изначально?... ведь даже вы, ища статью - искали решение конкретной проблемы, я думаю)
мне на первом курсе вываливали информацию, без объяснения, и только сильно позже я начал понимать, куда можно было запрячь эти сани.. только время упущено) скучно слушать то, чему не видишь применения)

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

я собственно что хотел сказать... я вроде не думаю, что я самый тупой инженер на свете  Скромно так... ... но три дня осмысливать статью, это как-то неправильно) я начинаю падать с своих глазах Жжешь
поэтому мне и кажется, что может что-то  не так с подачей материала? либо я просто не сталкивался со спецификой парсеров, поэтому с ходу не представляю, всех граблей, раскиданных на пути их написания, и то что подход и там может быть полезен? но в примере - это совсем не явно, хотя идея и правда хороша) начинаю думать куда бы я ее мог пристроить... у меня как раз асинхронные потоки от железа в одном месте сейчас сталкиваются) написать - написал, но функция на четыреста строк кода, и разбивать ее совсем невыносимо. число строчек не уменьшить, но то что есть - совершенно не читаемо.
« Последнее редактирование: 22-10-2010 23:51 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 23-10-2010 11:06 » 

- опять же. интерфейс Ethernet не будет отправлять данные которых нет. поэтому даже в этом случае вольтметр является мастером, то есть частота его опроса.
если скорость опроса ограничена пропускной способсностью ethernet-а, мастер - ethernet.
действительно разделение на master/slave провести сложно. однако даже в этом случае при простой последовательности "опрос данных"-"отправка данных" в цикле, проблема вроде как решается. оба устройства  все равно будут работать с максимальной скоростью, независимо от того кто ее определяет.

Давайте представим такую ситуацию. Чтобы добиться полной универсальности прибора, мы делаем его в модульном исполнении. Вольтметр размещаем на одной плате, интерфейс - на другой  (пусть даже они получатся с ноготок каждая, мы умышленно их разделяем конструктивно). Для соединения у них есть унифицированный разъем. АЦП берем типовой, не отличающийся сверхскоростью. Подключаем к нему 100 МБит сетевой интерфейс для передачи данных в центр обработки. Передача данных происходит гораздо быстрее, чем измерение. Назначаем вольтметр "мастером", поскольку именно он определяет темп работы прибора в целом.

Другой заказчик требует укомплектовать прибор интерфейсом RS-232 на 1200 бод. Теперь уже интерфейс передачи оказывается гораздо медленнее, чем АЦП, и определяет общий темп. Теперь передатчик назначается мастером: он забирает предыдущий результат, запускает следующий цикл преобразования, чтобы вольтметр не терял времени даром, и начинает передачу.

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

Возьмем житейскую аналогию. Вы с другом сажаете деревья. Вы выкапываете лунку, а друг помещает в нее саженец и засыпает ее. Кто из вас главный? Да никто, вы просто вместе делаете общее дело. Главное - синхронизация, чтобы друг не пытался всунуть саженец в еще не выкопанную лунку. Но назначать для этого начальника вовсе не обязательно. Вполне годится симметричная модель двух взаимодействующих синхронизированных равноправных процессов.

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

Вы это бросьте Улыбаюсь

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

Вспомните Козьму Пруткова:
Цитата
Многие вещи нам непонятны не потому, что наши понятия слабы; но потому, что сии вещи не входят в круг наших понятий.


поэтому мне и кажется, что может что-то  не так с подачей материала?

Само собой. Автор ведь не собирался написать учебную статью с введением и всей необходимой теорией. Он как бы говорит нам: "Все вы, конечно, знаете, что такое сопрограммы, и пользуетесь ими каждый день; а сейчас я покажу вам, как все это сделать на чистом С". Я и сам, честно говоря, неявно предполагал, что сопрограммы входят в базовый курс программирования, который читают в институтах. Меня с ними познакомил научный руководитель в студенчестве еще во времена транзисторных ЭВМ с ферритовой памятью.

Способ исправить ситуацию я предложил выше (пост 18).

хотя идея и правда хороша) начинаю думать куда бы я ее мог пристроить...

В любом случае у инженера, который знаком с механизмом сопрограмм, есть два выбора: применить их или нет. У инженера, который его не знает, выбор лишь один, вынужденный Улыбаюсь

Так что время, потраченное на осмысление статьи, не окажется потраченным даром.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #24 : 23-10-2010 15:00 » 

ведь даже вы, ища статью - искали решение конкретной проблемы, я думаю)

Не совсем так. Попалась она мне случайно в коллекции ссылок для "гиков" языка С. Кстати, именно оттуда маленький тест на знание языка С, о котором я писал недавно. Как всегда, ищешь одно, а находишь совершенно другое. Просто, увидев, что речь идет о сопрограммах, не смог пройти мимо. Все-таки эта тема недостаточно освещена в литературе.

Какой-то четко определенной проблемы на данный момент нет. Скорее желание подтянуть уровень знаний на современный уровень. Знания в области схемотехники у меня застыли на уровне логики 155-й серии, микропроцессоров 8080 и Z80 и АЦП/ЦАП серии 572. Товарищи посоветовали обратить внимание на Atmel AVR.

На работе я разрабатываю серверные приложения для телефонного биллинга в среде .NET. Привык к определенному подходу к проектированию и разработке, в частности, к разработке через тестирование (TDD), регрессионному тестированию, определенным паттернам управления версиями ПО, непрерывной интеграции, инструментальной поддержке документирования проекта, верификации кода и т.д. Попытался применить все это к разработке встроенного ПО - и обломался. В литературе по программированию микроконтроллеров на С считается, что проектирование сводится к написанию исходников и прошивке их в память МК. На форумах разработчиков эти темы тоже обходят молчанием, мастера паяльника и лазерного утюга не заморачиваются такими материями. Решил попытать счастья на форумах программистов - тоже без результата: на RSDN даже раздела подходящего не нашел, здесь нашел раздел по встроенным системам, но ответа тоже не получил... Решил копать сам.

Вот по крупицам кое-что начал собирать. Информации, прямо скажем, весьма не густо: на русском языке абсолютный нуль, на английском - несколько статей по модульному тестированию firmware (один перевод уже опубликован, второй готов и ждет публикации), данная статья по организации сопрограмм, уникальная книга Джеймса Греннинга "Test Driven Development for Embedded C"... Учитывая, как трудно было собрать все воедино, решил начать публиковать это на форуме. Уверен, что на русском языке больше нигде этого найти не удастся. А конечная цель всей этой затеи - выстроить полную замкнутую цепь инструментов и технологий проектирования устройств с микроконтроллерами от идеи до готового устройства.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #25 : 23-10-2010 21:49 » 

я на самом деле самоучка в программировании) начинал с бейсика еще в школе на Z80, немного ассемблера, потом паскаль, потом перешел на дельфи. Си - уже устроившись на работу пришлось изучать для драйверов, С++ совсем недавно, да и то на примитивном уровне. так что теоретической базы у меня практически никакой) все знания - из практики. я даже про паттерны - ничего толком не знаю)

а так, я инженер радиотехники. работа на 200% по специальности, большая часть - сигнальная обработка (на x86,  преимущественно), а там алгоритмы укладываются в рамки последовательного вызова функций... знаком с ядром винды, из за драйверов. из за них же - хорошо с многопоточностью и синхронизацией под windows. немного изучал один из вариантов RTOS.
с контроллерами практически не сталкивался. разве что под TMS недавно писал первый раз в жизни. но там, кстати, чистый TDD получился. полностью разработка и отладка алгоритма на x86, портирование кода на другой процессор, и борьба за быстродействие. все через тесты в контрольных точках, и сравнение с эталонным алгоритмом на x86. не знаю насколько это можно считать embedded...

программирование для меня в первую очередь - реализация алгоритма обработки, на выдумывание которого уходит 90% времени. программирование там уже рутина, как правило.
хотя вру. максимальных результатов можно достичь только разрабатывая алгоритм с учетом платформы и аппаратных ограничений. но это у меня как раз само собой получается)

PS попробуйте поискать информацию о разработке на ПЛИСах. там сейчас пытаются внедрить язык "systemС", говорят похоже на С++. и вообще, там все завязано на параллельность процессов. может быть найдется какая то аналогия, или статьи близкие по духу. для затравки http://www.chip-news.ru/archive/chipnews/200609/Article_13.pdf
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #26 : 23-10-2010 22:37 » 

с контроллерами практически не сталкивался. разве что под TMS недавно писал первый раз в жизни. но там, кстати, чистый TDD получился. полностью разработка и отладка алгоритма на x86, портирование кода на другой процессор, и борьба за быстродействие. все через тесты в контрольных точках, и сравнение с эталонным алгоритмом на x86. не знаю насколько это можно считать embedded...

Конечно же, это и есть embedded в чистом виде. То, что алгоритм сначала моделировался на другой системе, сути дела совершенно не меняет.

Мне было бы чрезвычайно... нет, не так: чрезвычайно любопытно ознакомиться с вашим опытом применения TDD для проектирования firmware. Не будет преувеличением сказать, что далеко не все программисты слышали про TDD; из тех, кто слышали, не все знают, что это значит; из тех, кто знают, не все понимают, как это делается; из тех, кто понимает, не все решаются воспользоваться на практике. В консервативной области проектирования embedded систем можно еще смело вводить поправочный коэффициент примерно 0.01, не ошибемся.Поэтому грех упускать такую возможность. Тем более что своего опыта у меня пока что нет, плотно застрял на подготовительном этапе.

(Это такое слегка замаскированное подстрекательство написать небольшой очерк о том, как все происходило, чем пользовались, с какими трудностями встретились, как их одолели и т.д.).  Скромно так...
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #27 : 24-10-2010 13:41 » 

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

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #28 : 24-10-2010 15:22 » 

Dale, да честно говоря и не было никакого особого опыта применения... просто надо было сделать довольно сложный алгоритм, получающий данные как раз с АЦП. то есть тоже не так: алгоритма не было! алгоритм надо было выдумать (он из разряда сигнальной обработки).

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

для разработки алгоритмов - у нас есть собственная среда моделирования радиосигналов  (графика и прочее, аналог Labview или Simulink , но гораздо более быстрая), которая позволяет подключать пользовательские библиотеки.

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

на втором - алгоритм был частично переписан в целочисленной (16/32 бит) арифметике за исключением sin()/cos() и FFT (всплыли некоторые баги связанные с ограничением разрядности - устранили)  в некоторых местах пришлось перейти на 64 битную арифметику (помня что АЛУ у конечной платформы 40-разрядное, поэтому если не допускать переполнений то можно)

на третьем - полный перенос на целочисленную арифметику.

на четвертом - специалист отказался перекладывать это все в ассемблер конечной платформы, и я решил попробовать впихнуть как есть, на си (точнее даже на c++, из которого было использовано только возможность определения переменных в произвольных местах функции, типа "for( int i=0....".
высплыл вопрос - как отлаживать. среда разработки конечной платформы поддерживала стандартные функции C++ чтение/запись файлов  (разумеется только в эмуляторе!!!)

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

оптимизация в компиляторе для конечной платформы оказалась - так себе, хотя через неделю помучившись вяснил, что правильно видоизменив код(не изменяя логики), можно добиться нужного эффекта в ассемблере - практически приблизить к идеалу!
оптимизировал Си, так чтобы после компилятора добиться быстродействия (это уже в среде разработки конечной платформы) контролируя результат по ассемблерным листингам. ассемблер я читаю со словарем, но писать на нем - увольте))))
кончилось тем что быстродействие было получено, причем один и тот же файл мог компилироваться на обоих платформах. (за исключением нескольких функций, оптимизированный вариант которых не компилился на x86 - для них было переопределение через define для разных платформ).

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

на последнем этапе подключал функцию FFT и КИХ-фильтров для конечной платформы, (на x86 - пытался использовать целочисленый аналог). проверял по контрольным точкам соответствие, нашел различия округления. но не принципиальные.

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

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

парень который до этого придумывал аналогичный по функциям алгоритм, писал на асемблере и отлаживал сразу в железке - два месяца смеялся и говорил что как я делаю -  невозможно....
а потом съел собственную шляпу, как обещал) он вообще не верил что такой подход сработает....
хотя я сам не очень ожидал ТАКОГО результата... глаза боятся - руки делают)) а может повезло просто)))

Добавлено через 48 секунд:
PS это я сейчас говорю что это типа TDD. пока делал - у меня и в мыслях этого слова не было... просто альтернатив я не видел)

Добавлено через 3 минуты и 17 секунд:
PPS платформа TMS320x  (Texas Instruments), среда их же - Code Composer Studio.
« Последнее редактирование: 24-10-2010 15:27 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Dale
Блюзмен
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #29 : 24-10-2010 16:32 » 

Я думаю, что у нас число самоучек намного выше получивших соответствующее образование.

Безусловно. Многие - по объективным причинам. Например сам я постигал эти премудрости на вычислительном центре кафедры теоретической и ядерной физики (их по понятным причинам в те годы снабжали техникой несравнимо лучше, чем другие кафедры). О регулярном образовании и речи не шло, исключительно самообразование. Впрочем, что уж обо мне говорить, когда Дейкстра писал в статье "Смиренный программист":

Цитата
Еще два года спустя, в 1957, я женился, и голландский обряд регистрации брака требовал указать профессию; я указал «программист». Но городские власти Амстердама не приняли документы на том основании, что такой профессии не существует. Хотите — верьте, хотите — нет, но в графе «профессия» моего свидетельства о браке значится забавная запись «физик-теоретик»!

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

По этому с теориями знакомимся когда уже столкнемся с ними на практике.

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

Поэтому желательно иметь некоторый запас теории впрок. И данная статья как раз не будет лишней в закромах.
Записан

Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.

Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard

Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
Страниц: [1] 2 3 4   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines