Перейти к содержанию
    

Небольшая проблема с обработкой сообщений

Доброго времени суток!

 

Организую взаимодействие между двумя процессами с помощью сообщений.

Один процесс отправляет сообщение, другой - принимает.

 

Почему то казалось, что после считывания сообщения оператором = его статус автоматически устанавливается на "пусто".

Поэтому делал так:

//thread 1
command_message.send();
response_message.wait();
...

//thread 2
if (command_message.is_non_empty())
{
	message_placeholder = command_message;
	...
	response_message.send();
	...
}

Оказалось, что это не так, и необходимо после считывания принудительно сбрасывать сообщение функцией reset().

 

Но, может быть, удобнее было бы сделать автоматический сброс флага NonEmpty после отрабатывания оператора присваивания?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброго времени суток!

 

Организую взаимодействие между двумя процессами с помощью сообщений.

Один процесс отправляет сообщение, другой - принимает.

 

Почему то казалось, что после считывания сообщения оператором = его статус автоматически устанавливается на "пусто".

Поэтому делал так:

 

...

 

Оказалось, что это не так, и необходимо после считывания принудительно сбрасывать сообщение функцией reset().

 

Но, может быть, удобнее было бы сделать автоматический сброс флага NonEmpty после отрабатывания оператора присваивания?

Не очень понял, что не получалось. Логика работы OS::message (как и OS::TEventFlag) такова, что внутренний флаг NonEmpty взводится только в случае, если посылается сообщение, которое еще никто не ждет. В этом случае, когда какой-то процесс встанет на ожидание сообщения, он сразу обнаружит, что оно уже послано - по этому внутреннему флагу, в этом случае флаг NonEmpty автоматически сбрасывается. Если при вызове OS::message::send уже были ожидающие этого сообщения процессы, то эти процессы переводятся в состояние готовых к выполнению, а внутренний этот флаг NonEmpty не устанавливается - в этом просто нет необходимости - кто ждал, те и так получат управление в очередности, соответствующей их приоритетам.

 

Таким образом, вам достаточно было дождаться сообщения с помощью функции OS::message::wait, после этого спокойно можно читать тело сообщения. Никаких проверок (is_non_empty и т.п.) не нужно. Это штатный способ использования.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таким образом, вам достаточно было дождаться сообщения с помощью функции OS::message::wait, после этого спокойно можно читать тело сообщения. Никаких проверок (is_non_empty и т.п.) не нужно. Это штатный способ использования.

Да, как работает функция wait() я понял, и к ней претензий нет.

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

 

Поэтому делается проверка на наличие сообщения функцией is_non_empty(), и далее обработка сообщения только в случае его наличия.

 

То есть получается такая ситуация:

1. низкоприоритетный процесс отправляет сообщение высокоприоритетному. Последний в это время ожидает другое событие и не может обработать сообщение, поэтому внутри send() устанавливается флаг NonEmpty.

2. процесс получатель высвобождается и проверяет наличие сообщения, а затем вычитывает его оператором =.

3. Приходится вызовом reset() сбрасывать установленный флаг.

 

Можно ли избежать третьего пункта, добавив в обработчик оператора = сброс NonEmpty?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, как работает функция wait() я понял, и к ней претензий нет.

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

 

Поэтому делается проверка на наличие сообщения функцией is_non_empty(), и далее обработка сообщения только в случае его наличия.

 

То есть получается такая ситуация:

1. низкоприоритетный процесс отправляет сообщение высокоприоритетному. Последний в это время ожидает другое событие и не может обработать сообщение, поэтому внутри send() устанавливается флаг NonEmpty.

2. процесс получатель высвобождается и проверяет наличие сообщения, а затем вычитывает его оператором =.

3. Приходится вызовом reset() сбрасывать установленный флаг.

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

 

Можно ли избежать третьего пункта, добавив в обработчик оператора = сброс NonEmpty?

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется, что у вас тут на уровне проектирования не совсем ладно. У вас получается, что процесс может одновременно ждать несколько сообщений, тогда в этом случае целесообразно применять не message, а channel. Тогда процесс просто ждет любого сообщения из канала, как только оно пришло, вычерпывает его оттуда и обрабатывает. А источники сообщений в своем темпе пихают сообщения в канал.

Ну что же, Вам виднее.

 

А мой процесс занимается загрузкой данных в память и передачей их по DMA.

В качестве сигнала готовности DMA использую event flag. Не дай бог сильно затянуть с реакцией на загрузку DMA, а если тут под ногами ещё будет путаться второстепенное сообщение...

Думаю, что канал в этом случае лишний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну что же, Вам виднее.

...

Думаю, что канал в этом случае лишний.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не используется ожидание сообщения, то какой смысл в применении сообщения вообще?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если не используется ожидание сообщения, то какой смысл в применении сообщения вообще?

Управление процессом. Передача комманд\ответов управляющему процессу.

Очень удобно, так как формат сообщений произвольный, и может содержать сложную структуру.

 

Процесс может находиться в двух режимах - idle и working.

В idle висим на ожидании сообщения (команды).

В working применяю поллинг, так как управляющее сообщение имеет низший приоритет, и время реакции на него не критично.

 

По моему вполне логично.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Управление процессом. Передача комманд\ответов управляющему процессу.

Очень удобно, так как формат сообщений произвольный, и может содержать сложную структуру.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Да, можно сделать общение процессов и не используя ОС.

Если самому позаботиться о синхронизации и совместном доступе.

 

Но, осваивая свою первую в жизни ОС, всё таки хочется пользоваться её сервисами :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Но, осваивая свою первую в жизни ОС, всё таки хочется пользоваться её сервисами :)

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

 

Да, можно сделать общение процессов и не используя ОС.

Если самому позаботиться о синхронизации и совместном доступе.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Без ОС придется повозиться с организацией как общего потока управления, так и частного кода, осуществляющего поллинг.

Ну вот поэтому я и выбрал поллинг с помощью ОС - ведь такая возможность в ней заложена.

 

А вот нелогичность с вычитыванием сообщения и несбросом флага "пусто", как Вы объяснили, это жертва того, что одно сообщение могут ожидать несколько процессов одновременно.

Тут бы, в идеале, для каждого процесса должно быть своё собственное сообщение, так как отдельные процессы знать не знают и не хотят про другие...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут бы, в идеале, для каждого процесса должно быть своё собственное сообщение, так как отдельные процессы знать не знают и не хотят про другие...
В следующей версии вы сможете написать такой сервис самостоятельно.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Сервисы ОС должны иметь минимальный функционал и интерфейс, позволяющий пользователю реализовать то, что тому нужно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне просто было интересно, почему авторы не предусмотрели сброс флага.

Теперь это понятно.

Спасибо за оперативную помощь.

 

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

А дальше пока не стал копать, в принципе, вполне устраивает и так :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...