реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> TEventFlag, Не пойму идеологии :(
gladov
сообщение Nov 11 2010, 09:03
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 169
Регистрация: 10-11-05
Из: Воронеж
Пользователь №: 10 687



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

Вообще идея понятна но смущает то, что выйдя из wait() я не знаю, очищен ли уже флаг или нет. А проверять последующим вызовом IsSignaled() уже нельзя, т.к. ее результат может оказаться невалидным, т.к. между wait() и IsSignaled() может что-то произойти, а в критическую секцию их заключить нельзя т.к. возможно ожидание флага от прерывания. Вот и не срастается у меня в голове идеология - как же правильно по задумке автора(ов) работать с флагами?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 11 2010, 11:07
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(gladov @ Nov 11 2010, 11:03) *
Объясните плз, почему TEventFlag.Wait() работает по-разному (очищает флаг или нет) в зависимости от того взведен флаг на момент запроса или нет? Я для себя никаких плюсов этого не вижу, а сумятицу в голову (в мою конкретно) вносит.
Нет, флаг чистится всегда если есть хоть один ждущий процесс. Будятся все ждущие процессы и чистится флаг.
Цитата(gladov @ Nov 11 2010, 11:03) *
Вообще идея понятна но смущает то, что выйдя из wait() я не знаю, очищен ли уже флаг или нет.
Должен быть очищен. В момент выхода из wait() он может быть уже снова взведен, но в момент пробуждения ждущего процесса он очищается.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
dxp
сообщение Nov 11 2010, 13:08
Сообщение #3


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
gladov
сообщение Nov 11 2010, 15:42
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 169
Регистрация: 10-11-05
Из: Воронеж
Пользователь №: 10 687



Цитата(Сергей Борщ @ Nov 11 2010, 14:07) *
Нет, флаг чистится всегда если есть хоть один ждущий процесс. Будятся все ждущие процессы и чистится флаг.
Должен быть очищен. В момент выхода из wait() он может быть уже снова взведен, но в момент пробуждения ждущего процесса он очищается.


Что-то я не пойму. smile3046.gif

Вот код из ветки https://scmrtos.svn.sourceforge.net/svnroot...os/trunk/Common, 268 revision:
Код
bool OS::TEventFlag::Wait(TTimeout timeout)
{
    TCritSect cs;

    if(Value)                                           // if flag already signaled
    {
        Value = efOff;                                  // clear flag
        return true;
    }
    else
    {
        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
        p->Timeout = timeout;
        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);

        SetPrioTag(ProcessMap, PrioTag);                // put current process to the wait map
        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);    // remove current process from the ready map

        Kernel.Scheduler();

        p->Timeout = 0;

        if( !(ProcessMap & PrioTag) )                   // if waked up by signal() or signal_ISR()
            return true;

        ClrPrioTag(ProcessMap, PrioTag);                // otherwise waked up by timeout or by
        return false;                                   // OS::ForceWakeUpProcess(), remove process from the wait map
    }
}


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

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


Да в общем и целом, конечно понятно. А как разбуженные узнают, кто из них сейчас самый приоритетный ИЗ ОЖИДАЮЩИХ? Ведь самый-самый мог сейчас события и не ждать. Но мой вопрос даже не в том "почему сделано так, а не эдак", а как имея данный механизм корректно вручную из процесса флаг сбрасывать? И почему не сделали сброс внутри wait()? Ведь сам факт побудки процесса с результатом true уже говорит о том, что событие произошло! Зачем мне после выхода еще анализировать что-то и сбрасывать флаг?
Конечно, в самом простом случае, когда один сигналит, а другой ждет, можно тупо всегда после wait() делать сброс, но тогда небольшой оверхед получим.

Посмотрел внимательнее и понял, что флаг не взводится если его уже ждут процессы. А у меня он видимо все-же не "оставался взведенным", а уже сигналил повторно. Думаю, вопрос закрыт...
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 10:41
Рейтинг@Mail.ru


Страница сгенерированна за 0.01709 секунд с 7
ELECTRONIX ©2004-2016