Воскресенье, 19.05.2024, 01:45
Приветствую Вас Guest Member

Windows XP / 7 .

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 2 из 2
  • «
  • 1
  • 2
Архив - только для чтения
Форум <<Помощь по компьютерам>> » Низкоуровневое программирование » Исходные коды » Исходные коды: С++ (Исходные коды: С++)
Исходные коды: С++
MafiozikOДата: Воскресенье, 23.08.2009, 10:14 | Сообщение # 16
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
В этом примере показано взаимодействие двух параллельных процессов: сценарий передает процессу Т сообщение целого типа, а процесс Т принимает его и отображает принятое значение. Обмен сообщениями реализован в библиотеке на основе понятия "канал". Канал - это параметризованный экземпляр класса, порожденного от базового класса ТКанал. Канал формирует собственную очередь сообщений. Сообщения ставятся в очередь в порядке их поступления (дисциплина FIFO). Канал является типизируемой структурой данных - это означает, что тип сообщений, который канал может обрабатывать, явно определен и известен на момент компиляции. Для декларации канала используются шаблоны (templates). Синтаксис декларации канала следующий:
Code

ТКанал<тип_сообщения> имя_канала;

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


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:15 | Сообщение # 17
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Для канала определены две основных операции: передать в канал << и принять из канала >>. В обоих случаях в левой части операторов должно стоять имя канала, а в правой части - имя переменной, тип которой соответствует типу канала.

Семантика оператора >> (принять) состоит в следующем: вначале проверяется, есть ли в очереди канала сообщения: если есть, то из очереди выбирается первое сообщение и процесс, выполнивший операцию приема, продолжает выполняться дальше без задержки. Если же очередь канала пуста, то процесс переводится из очереди готовых процессов в очередь ожидания событий. Отметим, что ожидать сообщения в канале в один момент времени может только один процесс, попытка выполнения операции приема из канала, в котором уже ожидает некоторый процесс, является ошибкой и приведет к аварийному завершению программы с выдачей диагностического сообщения. Семантика оператора << (передать) состоит в том, что сообщение упаковывается в конверт и ставится в конец очереди сообщений канала. Процесс, выполнивший операцию передачи при этом не приостанавливается, а продолжает выполняться дальше. Длина очереди канала не ограничена. При выполнении оператора передачи проверяется, есть ли у канала ожидающий процесс, если есть, то он активизируется, т.е. переводится в очередь готовых процессов. Таким образом, каналы предоставляют процессам буферизованный несимметричный механизм взаимодействия, в котором получатель сообщения приостанавливается при отсутствии сообщений, а процесс, передающий сообщение, всегда выполняется без приостановки.

Кроме основных операций << (передачи) и >> (приема) для канала определена также операция <<= (передача в начало канала). В отличие от операции <<, которая записывает сообщения в конец очереди канала, операция <<= записывает сообщения в начало очереди канала. Таким образом, структура канала является промежуточной между очередью и деком: в такую очередь можно записывать данные с обоих концов, а удалять только из начала. Операция <<= может быть использована для различных целей, например:


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:15 | Сообщение # 18
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
* для посылки особо приоритетных сообщений,
* для возврата полученного сообщения обратно в канал для последующей обработки,
* для возврата полученного и модифицированного сообщения в канал. Возврат сообщений удобно использовать в программах, управляемых событиями.

Кроме того, канал предоставляет еще несколько сервисных функций:

* функция корреспондент() возвращает указатель на процесс, передавший данное сообщение,
* функция пуст() возвращает логическую 1 при отсутствии сообщений в канале,
* функция таймаут() позволяет задать предельное время ожидания сообщения в канале, например, вызов: канал.таймаут(1000); будет устанавливать время таймаута, равное 1 секунде. Это означает, что если процесс, выполнивший операции >> (принять) ждет сообщения больше 1 секунды, то он активизируется, причем значение переменной - приемника сообщения не изменяется. Для реализации этой возможности оператор >> возвращает логическую 1, если прием сообщения был удачным и 0, если зафиксирован таймаут. Например:


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:15 | Сообщение # 19
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Code
if (канал >> i)
   cout << "Принято сообщение " << i << '\n';
else
   cout << "Таймаут\n";


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:15 | Сообщение # 20
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Введение таймаута позволяет элегантно решать задачи, возникающие при приеме сообщений от потенциально ненадежного источника сообщений без зависания программы.

Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:16 | Сообщение # 21
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Программа 7
Quote

enum ТТег { целое, строка };
struct ТКонтейнер_Целого { int значение; };
struct ТКонтейнер_Строки { char значение[10]; };

ТКанал<ТТег> канал_тега;
ТКанал<ТКонтейнер_Целого> канал_целых;
ТКанал<ТКонтейнер_Строки> канал_строк;

простой_процесс(ТГенератор_Целых)
{
ТТег тег = целое;
ТКонтейнер_Целого контейнер;
контейнер.значение = 123;
пауза(случайное_число(10, 60));
канал_тега << тег;
канал_целых << контейнер;
}

простой_процесс(ТГенератор_Строк)
{
ТТег тег = строка;
ТКонтейнер_Строки контейнер;
strcpy(контейнер.значение, "ABCDEF");
пауза(случайное_число(10, 60));
канал_тега << тег;
канал_строк << контейнер;
}

static ТГенератор_Строк генератор_строк;
static ТГенератор_Целых генератор_целых;

void ТСценарий::тело_процесса(void)
{
ТТег тег;
ТКонтейнер_Целого контейнер_целого;
ТКонтейнер_Строки контейнер_строки;
канал_тега.таймаут(30);
if (канал_тега >> тег)
{
switch (тег)
{
case целое:
канал_целых >> контейнер_целого;
break;
case строка:
канал_строк >> контейнер_строки;
break;
}
}
else
cout << "Таймаут\n";
}



Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:16 | Сообщение # 22
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Этот пример демонстрирует реализацию операции недетерминированного ожидания (ее семантика напоминает семантику оператора select языка Ада или блока ALT языка Оккам). В программе определяются следующие объекты:

* два статических процесса, генерирующих сообщения разного типа: целого и строки;
* два канала для передачи сообщений указанных типов;
* один канал для передачи тега - типа сообщения. Для этого канала вводится ограничение по таймауту в 30 миллисекунд;
* процесс-сценарий, принимающий сообщения.

Каждый из статических процессов заполняет свои контейнеры сообщений и передает их в соответствующие каналы. Кроме того, передача контейнера сообщения сопровождается передачей типа сообщения в канал тега. Время передачи определяется случайным числом в диапазоне от 10 до 60 миллисекунд. Сценарий принимает тип сообщения из канала тега и, в зависимости от того, какое из трех событий (2 сообщения и таймаут) наступило быстрее, выполняет то или иное действие.

В этом примере используется техника сильной типизации сообщений: вместо предопределенных типов "int" и "char[]" сообщения определяются как записи (struct), содержащие всего по одному элементу. Отметим также, что все каналы создаются как самостоятельные объекты (не принадлежащие конкретному процессу).

Для определения процессов в примере используется макроопределение "простой_процесс()", аргумент которого - имя типа процесса. Это макроопределение позволяет более лаконично записывать декларацию типа процесса и его тела в часто используемом случае, когда процесс переопределяет только одну функцию базового класса: тело_процесса(). Таким образом, лаконичное определение процесса Т:


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:16 | Сообщение # 23
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Code
простой_процесс(Т)
{
   пауза(1000);
}


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:16 | Сообщение # 24
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
полностью эквивалентно такому явному определению:
Code

class Т : public ТПроцесс
{
   public:
     void тело_процесса(void);
};

void Т::тело_процесса(void)
{
   пауза(1000);
}


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:17 | Сообщение # 25
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Программа 8

Code
ТРандеву<int> рандеву;

простой_процесс(ТПроизводитель)
{
   int i = 0;
   for (;;)
   {
     пауза(случайное_число(1000, 6000));
     рандеву << ++i;
   }
}

простой_процесс(ТПотребитель)
{
   int i;
   for (;;)
   {
     пауза(3000);
     рандеву >> i;
   }
}

static ТПроизводитель производитель;
static ТПотребитель потребитель;

void ТСценарий::тело_процесса(void)
{
   пауза(20000);
}


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:17 | Сообщение # 26
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
В этом примере иллюстрируется взаимодействие двух асинхронно выполняемых процессов - процесса-производителя, готового к взаимодействию через случайный промежуток времени в диапазоне от 1 до 6 секунд и процесса-потребителя, который готов к взаимодействию не ранее, чем через 3 секунды после взаимодействия с процессом-производителем. Взаимодействие выполняется на основе механизма "рандеву", синхронизирующего взаимодействие двух параллельных процессов. Семантика рандеву такова: если к взаимодействию готов только один процесс, то он приостанавливает свое выполнение (переводится в очередь ожидания событий) до того момента, когда к взаимодействию будет готов второй процесс, после чего оба процесса обмениваются данными и продолжают выполняться асинхронно. Рандеву обеспечивает небуферизованное симметричное взаимодействие процессов - оба процесса выступают как равноправные, в отличие несимметричного обмена сообщениями через канал.

Синтаксис рандеву аналогичен синтаксису обмена сообщениями с тем отличием, что вместо канала используется параметризованный объект класса, порожденного от базового класса ТРандеву. Синтаксис операторов приема и передачи тот же. Для рандеву также можно ограничивать время ожидания, используя функцию таймаут().


Админ
 
MafiozikOДата: Воскресенье, 23.08.2009, 10:17 | Сообщение # 27
~Web master~
Группа: Gold пользователь
Зарегистрирован: 10.04.2009
Откуда: Kharkiv
Пол: Мужчина
Сообщений: 366
Статус: Вне сайта
Программа 9

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


Админ
 
Форум <<Помощь по компьютерам>> » Низкоуровневое программирование » Исходные коды » Исходные коды: С++ (Исходные коды: С++)
  • Страница 2 из 2
  • «
  • 1
  • 2
Поиск: