Пишу обёртку вокруг семафора (semaphore.h)

Модератор: Модераторы разделов

Аватара пользователя
Zeus
Сообщения: 694

Пишу обёртку вокруг семафора

Сообщение Zeus »

"Обёртка" - это класс с очень простым интерфейсом:

Код: Выделить всё

class Semaphore
{
public:
 Semaphore ();
 ~Semaphore();
 int post ();
 int wait (bool blocking=true);
 int getValue (int& val);
 int getValue (int* val);
private:
 bool is_init;
 sem_t _sem_;
};


Проблема вот в чём:
в деструкторе, для корректного разрушения объекта, нужно "освободить" все потоки, которые могут "висеть" заблокированными на wait'е.
Для этого я анализирую код возврата функции sem_destroy и если она возвращает код "семафор занят", то вызываю sem_post.
Потом опять sem_destroy и если ошибка, то sem_post - т.е. по идее после отработки деструктора все потоки должны разблокироваться.
Однако этого не происходит.
sem_destroy не возвращает код ошибки, хотя я уверен, что на семафоре "висит" поток.
Более того, для отладки я блокировал на семафоре поток и в деструкторе вызывал sem_post безо всяких условий - просто перед sem_destroy.
Поток не проснулся! :unsure:
Если же вызывать метод post класса ДО разрушения объекта (delete mySemaphore), то поток разблокируется.
Код в контексте деструктора работает как-то особенно?
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Пишу обёртку вокруг семафора

Сообщение v04bvs »

Zeus писал(а):
16.09.2007 20:17
Код в контексте деструктора работает как-то особенно?


Нет.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

Ну и данные-члены класса объекта (в моём случае - _sem_) освобождаются после работы деструктора - это я тоже не глючу?
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Пишу обёртку вокруг семафора

Сообщение sergio »

Zeus писал(а):
16.09.2007 21:32
Ну и данные-члены класса объекта (в моём случае - _sem_) освобождаются после работы деструктора - это я тоже не глючу?

Поск инициализируются до входа в блок ктора, то и деинициализироваться/разрушаться должны после дтора. :)
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

В общем, провернул такую же проверку с "обёрткой" для мьютекса.

Похоже проблема в том, что функции разрушения (pthread_mutex_destroy и sem_destroy) не возвращают ошибку EBUSY при уничтожении объекта на котором заблокирован поток.
Как так? :unsure:
Спасибо сказали:
sergio
Сообщения: 436
Статус: Интересующийся новичок
ОС: Debian GNU/Linux 4 & 5

Re: Пишу обёртку вокруг семафора

Сообщение sergio »

Zeus писал(а):
16.09.2007 23:37
Как так? :unsure:

Не, в семафорах я не рублю пока. Я принес немного программистского оффтопика, чтоб не так скушна и тосклива с семафорами было (GCC шутит): :tongue:

Код: Выделить всё

Command.cpp:76: error: ‘<expression error>’ cannot be used as a member pointer, since it is of type ‘<type error>’
Debian GNU/Linux 4 -- AMD Athlon64 3000+ / Asus 7600GS -- Gnome
Debian GNU/Linux 5 -- Dell (Vostro) 500 (Celeron M560 / iGM965) -- Gnome
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

Продолжение иксперимента:
залез в /usr/include/bits/pthreadtypes.h, где определён pthread_mutex_t.
Это - структура, в которой есть счётчик глубины рекурсии запирания мьютекса __m_count.
Как я понимаю pthread_mutex_destroy должен анализировать как-раз этот счётчик (и больше ничего - как говорят man'ы).
Но счётчик тоже постоянно равен нулю, хотя на мьютексе заблокирован не один поток.
Ниччё не понимаю :unsure:
Спасибо сказали:
dronord
Сообщения: 40
ОС: slackware

Re: Пишу обёртку вокруг семафора

Сообщение dronord »

Да не убивай ты семафор, пока не пройдешь узкое место.
А если убьешь - программа дальше сможет нормально работать?
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

dronord писал(а):
18.09.2007 09:38
Да не убивай ты семафор, пока не пройдешь узкое место.
А если убьешь - программа дальше сможет нормально работать?

Так а как мне узнать-то, что на семафоре или мьютексе кто-то спит?
Функции *_destroy это и должны сообщать.
А они всегда возвращают 0 :unsure:
Спасибо сказали:
andy128k
Сообщения: 28
ОС: GNU/Linux

Re: Пишу обёртку вокруг семафора

Сообщение andy128k »

Zeus писал(а):
18.09.2007 10:20
Так а как мне узнать-то, что на семафоре или мьютексе кто-то спит?
Функции *_destroy это и должны сообщать.
А они всегда возвращают 0 :unsure:

sem_trywait и pthread_mutex_trylock.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

andy128k писал(а):
18.09.2007 10:40
sem_trywait

Эта функция - неблокирующий вариант sem_wait: уменьшает счётчик семафора на 1.
Ну "скажет" она, что счётчик семафора равен нулю - и что?
Это же не значит, что на нём кто-то "спит".

andy128k писал(а):
18.09.2007 10:40
pthread_mutex_trylock.

Аналогично: функция сообщит, залочишься ли ты на мьютексе, если вызовешь pthread_mutex_lock, но не сообщит, спит ли уже на мьютексе поток или нет.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

А под Fedora 5 всё работает.
Ясно, что для переносимости на функции destroy лучше не затачиваться.
Буду контролировать количество "клиентов" класса-обёртки самостоятельно.
Спасибо сказали:
andy128k
Сообщения: 28
ОС: GNU/Linux

Re: Пишу обёртку вокруг семафора

Сообщение andy128k »

Zeus писал(а):
18.09.2007 12:28
andy128k писал(а):
18.09.2007 10:40
pthread_mutex_trylock.

Аналогично: функция сообщит, залочишься ли ты на мьютексе, если вызовешь pthread_mutex_lock, но не сообщит, спит ли уже на мьютексе поток или нет.


В том то и дело, если ты залочил, значит никто lock не вызвал.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

Ну, в общем да - он сообщит, вызывал ли кто-нибудь до тебя lock для этого мьютекса.

Но вывод всё-равно сделан: destroy-функции сильно зависят от реализации и полагаться на них нельзя.
Спасибо сказали:
andy128k
Сообщения: 28
ОС: GNU/Linux

Re: Пишу обёртку вокруг семафора

Сообщение andy128k »

Zeus писал(а):
19.09.2007 11:24
Ну, в общем да - он сообщит, вызывал ли кто-нибудь до тебя lock для этого мьютекса.

Но вывод всё-равно сделан: destroy-функции сильно зависят от реализации и полагаться на них нельзя.


Раз нельзя полагаться на destroy, значит нужно полагаться на trylock :)
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Пишу обёртку вокруг семафора

Сообщение Zeus »

И опять про убийство "мьютекса":
проверяю я не занят ли мьютекс, прежде чем его разрушить - выяснилось, что занят. Например, единственный поток его залочил и выполняется, захватив какой-то ресурс.
А что мне делать? unlock и разрушать? Тогда этот поток вызовет метод unlock на несуществующем объекте.
Или самому залочиться на мьютексе и ждать его освобождения, чтобы разрушить? А если тот поток намертво зациклился? А всё это в деструкторе происходит...
Можно исключение выбросить, чтобы сообщить вызывающему коду, о заблокированном мьютексе, но объект-то всё-равно будет разрушен.
Как красивше поступить?

Я склоняюсь к разблокировке всех заблокированных потоков и - выходу. Может быть с исключением.
Что уж там произойдёт при unlock'е пусть программёр решает, который взялся сдуру разрушать занятый мьютекс.
Спасибо сказали: