Мьютекс с таймаутом.

81 views
Skip to first unread message

Чуйкин Андрей

unread,
Feb 28, 2014, 4:46:30 AM2/28/14
to scmrt...@googlegroups.com
Добрый день.

Предлагаю внести в ось мьютекс, обеспечивающий операцию захвата с таймаутом.

Обоснование.

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

Другой пример.
Для стека lwIP нужны объекты блокировки с таймаутом по захвату.

В прищепке вариант реализации.
sys_service.h

Harry Zhurov

unread,
Feb 28, 2014, 6:40:36 AM2/28/14
to scmrt...@googlegroups.com
28.02.2014 16:46, Чуйкин Андрей пишет:
> Предлагаю внести в ось мьютекс, обеспечивающий операцию захвата с
> таймаутом.

Ну, а для чего мы переработали в четвертной версии потроха с целью
возможности добавления расширений? И директорию специально завели -
Extensions (и пример там уже даже есть). :) Как раз для подобных
случаев. Придумал полезную штуку - клади её туда, не надо спрашивать
чьего-то разрешения, ведь это не тянет за собой какой-то
несовместимости, никому не мешает. При этом, конечно, хорошо бы
поделиться об этим с остальными - как ты уже сделал.

Кстати, насколько помню, сама идея с введением механизма расширений и
родилась у Сергея Борща (ух, как давно это было! :) ), когда он хотел
вот подобный сервис - мутекс с таймаутом. Т.ч. развитие идёт как
положено - по спирали. :)

--
HZ


Sergey A. Borshch

unread,
Feb 28, 2014, 10:01:35 AM2/28/14
to scmrt...@googlegroups.com
On 28.02.2014 13:40, Harry Zhurov wrote:
> Кстати, насколько помню, сама идея с введением механизма расширений и родилась у
> Сергея Борща (ух, как давно это было! :) ), когда он хотел вот подобный сервис -
> мутекс с таймаутом. Т.ч. развитие идёт как положено - по спирали. :)
Нет, я хотел мутекс с освобождением в прерывании. И было это давно, да. А
используется до сих пор.

А может нам вообще все сервисы вынести в Extensions каждый в свой файл?
В паке проекта можно будет хранить заголовочный файл services.h, в который
пользователь будет вставлять #include <> нужных в конкретном проекте сервисов.
А может и не нужно...


--
Regards,
Sergey A. Borshch mailto: sb...@sourceforge.net
SB ELDI ltd. Riga, Latvia

Anton Gusev

unread,
Mar 2, 2014, 1:39:14 AM3/2/14
to scmrt...@googlegroups.com
Hi, Чуйкин Андрей!
You wrote on 28.02.2014 15:46

> Предлагаю внести в ось мьютекс, обеспечивающий операцию захвата с таймаутом.

О, отличная штука, давно мечтал о такой! Одобрям! :)


Чуйкин Андрей

unread,
Mar 3, 2014, 12:22:15 AM3/3/14
to scmrt...@googlegroups.com
А ..., забыл совсем.
Но все же в голове сидит маленькая нестыковочка.
TMutex и TTimedMutex суть одно и тоже. Почему они должны находится в разных местах? Т.к. TTimedMutex полностью повторяет функциональность TMutex, то оставить можно только TTimedMutex, переименовав его в TMutex. Короче, надо добавить функциональность таймаута в штатный мьютекс :). Но это мое личное желание, вызванное удобством использования и обратной совместимости.
Но и extensions тоже вариант.

Если никто еще не выскажется, выложу как extension.

пятница, 28 февраля 2014 г., 18:40:36 UTC+7 пользователь Harry Zhurov написал:

Harry Zhurov

unread,
Mar 3, 2014, 12:55:46 AM3/3/14
to scmrt...@googlegroups.com
Greeting All!

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

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

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

--
HZ


Sergey A. Borshch

unread,
Mar 3, 2014, 2:25:37 AM3/3/14
to scmrt...@googlegroups.com
On 28.02.2014 11:46, Чуйкин Андрей wrote:
> Предлагаю внести в ось мьютекс, обеспечивающий операцию захвата с таймаутом.

Внимательно просмотрел исходник. Мысли следующие:

1) почему наследование от TService сделано публичным? Какие функции TService
предполагается использовать снаружи?
2) Не нравится мне возможность вызова со значением по-умолчанию и вот почему:
вызывая mutex.lock() без параметров программист предполагает, что выход из этой
функции будет со 100% гарантией захвата. И старая реализация без параметра это
обеспечивала. В новой же, если во время ожидания захвата будет вызвана
force_wake_up() - lock() вернется с незахваченным ресурсом. А весь предыдущий код
написан с учетом того, что она void и проверки захвата не содержит. И хотя я
пока еще не использовал wakeup() и force_wake_up(), все же сделал бы отдельную
функцию для захвата с таймаутом и отдельную для безусловного захвата, т.е. без
параметра. И если развивать эту логику, то lock() с параметром, равным 0
переадресовывал бы в lock_softly().


>
> Обоснование.
>
> Пример из жизни.
> Использую я в проекте файловую систему FatFs (поклон Антохе), которая для
> обеспечения реентрантности требует реализации пары функций, в которых надо
> захватить объект блокировки и, соответственно, освободить. Для scmRTOS это
> тривиально решается мьютексом. Но, если есть процесс, длительно работающий с
> файлом, то все остальные процессы будут ждать, вместо того чтобы заняться
> чем-нибудь полезным и получить доступ к файловой системе позднее.
>
> Другой пример.
> Для стека lwIP нужны объекты блокировки с таймаутом по захвату.
>
> В прищепке вариант реализации.

Anton Gusev

unread,
Mar 3, 2014, 2:43:27 AM3/3/14
to scmrt...@googlegroups.com
Hi, Sergey A. Borshch!
You wrote on 3 мар 2014 г. 13:25

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

Может быть тогда просто добавим в TMutex метод lock_timed(timeout)?
Или даже просто lock(timeout_t timeout = 0).
Тогда все старые вызовы гарантированно будут работать по-старому, а
вызов с параметром обеспечит новый полезный функционал.
Ы?



Anton Gusev

unread,
Mar 3, 2014, 2:45:09 AM3/3/14
to scmrt...@googlegroups.com
Anton Gusev wrote on 3 мар 2014 г. 13:43
> Или даже просто lock(timeout_t timeout = 0).
Упс, этот вариант конечно же без значения по умолчанию.


Чуйкин Андрей

unread,
Mar 3, 2014, 3:02:08 AM3/3/14
to scmrt...@googlegroups.com

> Внимательно просмотрел исходник. Мысли следующие:

>

> 1) почему наследование от TService сделано публичным? Какие функции

> TService предполагается использовать снаружи?

 

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


 

> 2) Не нравится мне возможность вызова со значением по-умолчанию и вот

> почему:

> вызывая mutex.lock() без параметров программист предполагает, что

> выход из этой функции будет со 100% гарантией захвата. И старая

> реализация без параметра это обеспечивала. В новой же, если во время

> ожидания захвата будет вызвана

> force_wake_up() - lock() вернется с незахваченным ресурсом. А весь

> предыдущий код написан с учетом того, что она void и проверки захвата не

> содержит. И хотя я пока еще не использовал wakeup() и force_wake_up(),

> все же сделал бы отдельную функцию для захвата с таймаутом и

> отдельную для безусловного захвата, т.е. без параметра. И если развивать

> эту логику, то lock() с параметром, равным 0 переадресовывал бы в

> lock_softly().

 

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

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

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

 

Sergey A. Borshch

unread,
Mar 3, 2014, 4:49:05 AM3/3/14
to scmrt...@googlegroups.com
On 03.03.2014 10:02, Чуйкин Андрей wrote:
> По аналогии с штатным TMutex. Он тоже с публичным наследованием. Т.к. я
> никогда не размышлял глубоко над потрохами scmRTOS, то максимально повторял
> уже существующий код.
Спасибо. Посмотрел глубже - там все protected или private. Так что
некриминально. Но некрасиво. Надо будет поправить.

> Буду рад, если кто-то, например, Сергей Борщ, возьмется за реализацию
> TTimedMutex.

Сейчас мы с Гарии еще немного повоюем за включение нового функционала в старый
сервис и добавим.

Sergey A. Borshch

unread,
Mar 3, 2014, 4:53:52 AM3/3/14
to scmrt...@googlegroups.com
On 03.03.2014 09:43, Anton Gusev wrote:

>> все же сделал бы отдельную
>> функцию для захвата с таймаутом и отдельную для безусловного захвата, т.е. без
>> параметра. И если развивать эту логику, то lock() с параметром, равным 0
>> переадресовывал бы в lock_softly().
>
> Может быть тогда просто добавим в TMutex метод lock_timed(timeout)?
> Или даже просто lock(timeout_t timeout).
> Тогда все старые вызовы гарантированно будут работать по-старому, а вызов с
> параметром обеспечит новый полезный функционал.
> Ы?

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

Anton Gusev

unread,
Mar 3, 2014, 5:01:11 AM3/3/14
to scmrt...@googlegroups.com
Hi, Sergey A. Borshch!
You wrote on 3 мар 2014 г. 15:49

> Спасибо. Посмотрел глубже - там все protected или private. Так что
> некриминально. Но некрасиво. Надо будет поправить.

Зачем? Вот захочет кто-то унаследоваться не от TService, а от TMutex, и
не сможет, потому что наследование не публичное и методы TService в
TMutex недоступны. Придётся наследоваться от TService, и дублировать
функционал TMutex в новом классе. Вот это будет действительно некрасиво.
ИМХО, в TService всё что ненужно и так отлично спрятано, ничего лишнего
наружу не вылазит.


Sergey A. Borshch

unread,
Mar 3, 2014, 5:26:29 AM3/3/14
to scmrt...@googlegroups.com
On 03.03.2014 12:01, Anton Gusev wrote:
> Hi, Sergey A. Borshch!
> You wrote on 3 мар 2014 г. 15:49
>
>> Спасибо. Посмотрел глубже - там все protected или private. Так что
>> некриминально. Но некрасиво. Надо будет поправить.
>
> Зачем? Вот захочет кто-то унаследоваться не от TService, а от TMutex, и не
> сможет, потому что наследование не публичное и методы TService в TMutex
> недоступны. Придётся наследоваться от TService, и дублировать функционал TMutex
> в новом классе. Вот это будет действительно некрасиво.
Сделать в сервисах наследование от TService protected - оно не будет мешать
наследоваться от сервисов, но будет ясно показывать, что из предков ничего
наружу не торчит и искать там нечего. "Я так думаю".

> ИМХО, в TService всё что ненужно и так отлично спрятано, ничего лишнего наружу
> не вылазит.

Anton Gusev

unread,
Mar 3, 2014, 5:42:48 AM3/3/14
to scmrt...@googlegroups.com
Hi, Sergey A. Borshch!
You wrote on 3 мар 2014 г. 16:26

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

На protected - согласен:)


Harry Zhurov

unread,
Mar 3, 2014, 5:52:14 AM3/3/14
to scmrt...@googlegroups.com
03.03.2014 16:53, Sergey A. Borshch пишет:
>> Может быть тогда просто добавим в TMutex метод
>> lock_timed(timeout)? Или даже просто lock(timeout_t timeout). Тогда
>> все старые вызовы гарантированно будут работать по-старому, а вызов
>> с параметром обеспечит новый полезный функционал. Ы?
>
> Вот и я за это. За добавление новой функци-члена. Осталось убедить
> Гарри. Или пусть придумывает новое название для наследника, который
> такой же, но с перламутровыми пуговицами... ой, еще умеет лочить за
> указанное время.

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

--
HZ


Anton Gusev

unread,
Mar 3, 2014, 6:22:31 AM3/3/14
to scmrt...@googlegroups.com
Hi, Harry Zhurov!
You wrote on 3 мар 2014 г. 16:52

> Я только за. :)

Осталось придумать имя функции:)
Я предлагал два варианта:
lock_timed(timeout_t timeout = 0)
lock(timeout_t timeout)
Ещё можно try_to_lock(timeout_t timeout = 0)

Мне нравится второй вариант. Хотя с точки зрения соответствия названия
выполняемому действию точнее подходит третий.


Чуйкин Андрей

unread,
Mar 3, 2014, 6:31:37 AM3/3/14
to scmrt...@googlegroups.com
try_lock

понедельник, 3 марта 2014 г., 18:22:31 UTC+7 пользователь Anton Gusev написал:

Sergey A. Borshch

unread,
Mar 3, 2014, 7:20:48 AM3/3/14
to scmrt...@googlegroups.com
У нас там есть готовая lock_softly(), которая делает то же самое, но с нулевым
таймаутом (т.е. сразу). Как насчет того, чтобы добавить ей параметр со значением
= 0 по умолчанию?
> --
> --
> Страница группы -- http://groups.google.com/group/scmrtos-ru
> ---
> Вы получили это сообщение, поскольку подписаны на группу scmrtos-ru.
>
> Чтобы отказаться от подписки на эту группу и перестать получать из нее
> сообщения, отправьте электронное письмо на адрес
> scmrtos-ru+...@googlegroups.com.
> Настройки подписки и доставки писем: https://groups.google.com/groups/opt_out.

Anton Gusev

unread,
Mar 3, 2014, 7:43:55 AM3/3/14
to scmrt...@googlegroups.com
Hi, Sergey A. Borshch!
You wrote on 03.03.2014 18:20

> У нас там есть готовая lock_softly(), которая делает то же самое, но с нулевым
> таймаутом (т.е. сразу). Как насчет того, чтобы добавить ей параметр со значением
> = 0 по умолчанию?

Хм. Так вроде бы параметр 0 - это бесконечное ожидание?
Хотя бесконечное ожидание обеспечивает обычный lock()...

Не, всё же думаю, что так не надо. Во всех функциях оси параметр 0 в
тайм-ауте означает бесконечное ожидание. Здесь пусть останется так же.
то есть, будет старый lock(), и к нему lock_softly(), который
захватывает мутекс только если он свободен, и try_lock(timeout_t timeout
= 0), который захватывает с тайм-аутом.
Да, получится, что try_lock() без параметра эквивалентен lock(), но это
фиг с ним (имхо).

(Название пусть будет как Андрей сказал, он - автор:))

Чуйкин Андрей

unread,
Mar 3, 2014, 8:43:43 PM3/3/14
to scmrt...@googlegroups.com
Если бы решал только я, то я бы назвал так:
lock() - безусловный лок.
try_lock() - лок, если мьютекс еще не занят.
timed_lock() - лок с таймаутом.
 - именно такие имена использует boost. А т.к. я предпочитаю удобства обратной свосместимости, то я бы без зазрения совести выполнил рефакторинг. Но, понимая мотивы Гарри насчет совместимости, предлагаю так:
lock()
lock_softly()
+ timed_lock()
потому что try_lock интуитивно неоднозначно.

понедельник, 3 марта 2014 г., 19:43:55 UTC+7 пользователь Anton Gusev написал:

Harry Zhurov

unread,
Mar 4, 2014, 3:43:47 AM3/4/14
to scmrt...@googlegroups.com
04.03.2014 8:43, Чуйкин Андрей пишет:
> Если бы решал только я, то я бы назвал так: lock() - безусловный
> лок. try_lock() - лок, если мьютекс еще не занят. timed_lock() - лок
> с таймаутом. - именно такие имена использует boost. А т.к. я
> предпочитаю удобства обратной свосместимости, то я бы без зазрения
> совести выполнил рефакторинг. Но, понимая мотивы Гарри насчет
> совместимости, предлагаю так: lock() lock_softly() + timed_lock()
> потому что try_lock интуитивно неоднозначно.

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

Сейчас, к сожалению, убрать его так просто нельзя. Но можно сделать так:
переименовать lock_softly в try_lock, добавить lock_softly (для
обпеспечения совместимости), которая вызывает try_lock, в документации
заменить lock_softly на try_lock.

Мнения?

--
HZ


Sergey A. Borshch

unread,
Mar 4, 2014, 4:27:35 AM3/4/14
to scmrt...@googlegroups.com
On 04.03.2014 10:43, Harry Zhurov wrote:
> Сейчас, к сожалению, убрать его так просто нельзя. Но можно сделать так:
> переименовать lock_softly в try_lock, добавить lock_softly (для обпеспечения
> совместимости), которая вызывает try_lock, в документации заменить lock_softly
> на try_lock.
>
> Мнения?
Я за.

Anton Gusev

unread,
Mar 4, 2014, 5:29:21 AM3/4/14
to scmrt...@googlegroups.com
Hi, Harry Zhurov!
You wrote on 04.03.2014 14:43

> Мнения?

Одобрям. А новую функцию тогда назовём timed_lock()?


Harry Zhurov

unread,
Mar 5, 2014, 4:15:08 AM3/5/14
to scmrt...@googlegroups.com
04.03.2014 17:29, Anton Gusev пишет:
>
> Одобрям. А новую функцию тогда назовём timed_lock()?

Тут можно повыбирать. Варианты:

--------------------
timed_lock();

--------------------
tlock();

имхо, неплохой вариант - коротко и чётко.

--------------------
lock_with_timeout();

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

---------------------
lock_timeouted();

похож не предыдущий вариант

+ короче
+ в недрах оси уже есть похожее именование (с _timeouted)
- чуть менее читебелен


Ещё варианты?

Обсуждаем, голосуем.

--
HZ


Чуйкин Андрей

unread,
Mar 5, 2014, 5:10:19 AM3/5/14
to scmrt...@googlegroups.com
+1 timed_lock()

Sergey A. Borshch

unread,
Mar 5, 2014, 7:57:19 AM3/5/14
to scmrt...@googlegroups.com
On 05.03.2014 11:15, Harry Zhurov wrote:
> Ещё варианты?

Так вроде бы решили try_lock() сделать две штуки - без параметра (бывшая
lock_softly) и с параметром таймаута.

Все варианты с timeouted, timed мне интуитивно непонятны - я прочитав такое
название подумал бы, что это именно захват мутекса на определенное время, через
которое он автоматически освободится. Я понимаю, что практического смысла в
таком поведении нет, но название наталкивает именно на такую трактовку. Может я
неправильно понимаю. Если решите timed_lock() - то пусть будет так.

> + в недрах оси уже есть похожее именование (с _timeouted)
Там оно как раз уместно - там речь идет о тех, у кого таймаут истек.

Harry Zhurov

unread,
Mar 5, 2014, 11:32:47 PM3/5/14
to scmrt...@googlegroups.com
05.03.2014 19:57, Sergey A. Borshch пишет:
>> + в недрах оси уже есть похожее именование (с _timeouted)
> Там оно как раз уместно - там речь идет о тех, у кого таймаут истек.

Я что-то потерялся уже. А тут разве не так (освобождение мутекса по
истечении таймаута)?

--
HZ


Sergey A. Borshch

unread,
Mar 6, 2014, 2:25:13 AM3/6/14
to scmrt...@googlegroups.com
Нет. Тут таймаут на захват. Или удалось захватить, или "не шмогла".

Harry Zhurov

unread,
Mar 6, 2014, 5:33:41 AM3/6/14
to scmrt...@googlegroups.com
06.03.2014 14:25, Sergey A. Borshch пишет:
> Нет. Тут таймаут на захват. Или удалось захватить, или "не шмогла".

А-а. Тогда timed_lock() мне не нравится - не видно из названия
функциональности. Тогда действительно нужно

try_lock()
try_lock(timeout_t)

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

--
HZ


Sergey A. Borshch

unread,
Mar 6, 2014, 5:54:22 AM3/6/14
to scmrt...@googlegroups.com
Да, с этим согласен полностью. Если других возражений в ближайшее время не будет
- реализуем так.

Sergey A. Borshch

unread,
Mar 11, 2014, 4:52:23 AM3/11/14
to scmrt...@googlegroups.com
On 06.03.2014 12:54, Sergey A. Borshch wrote:
> Да, с этим согласен полностью. Если других возражений в ближайшее время не будет
> - реализуем так.
>

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

Предлагаю Андрею, как автору идеи, проверить его работоспособность и дать отмашку.

try_lock() без параметра делает попытку захвата без ожидания, try_lock(timeout)
с нулевым параметром может ждать бесконечно.
try_lock.diff

Чуйкин Андрей

unread,
Mar 11, 2014, 6:42:09 AM3/11/14
to scmrt...@googlegroups.com
Привет.
Проверил. Работает. Но INLINE перед try_lock в определении класса надо убрать.

вторник, 11 марта 2014 г., 15:52:23 UTC+7 пользователь Sergey Borshch написал:
Reply all
Reply to author
Forward
0 new messages