typedef Locker<123> Resource1Locker;
typedef Locker<456> Resource2Locker;
.....
void func1()
{
Resource1Locker lock(false);
// теперь первый ресурс можно безболезненно читать, его не изменят до конца функции
}
void func2()
{
Resource2Locker lock(true);
// теперь второй ресурс можно безболезненно изменять, его не будут читать до конца функции
}
Просто, понятно, работает (!)... Компилится в VC6 (!!). Единственное слабое место — код инициализации . Но тут уж ничего не поделаешь (если кто-то знает способ — опубликуйте, буду благодарен).. Параноикам могу предложить перед началом создовать по штуке объектов каждого класса, тогда этой проблемы не будет. Лично я не настолько параноик, предпочитаю надеяться на лучшее
Делай что должно, и будь что будет
Re: Универсальный блокировщик типа читатели/писатель
Здравствуйте SergH, Вы писали:
SH>Здравствуйте.
SH>Понадобилось мне в нескольких независимых местах блокировать разные ресурсы на чтение/запись. Написал такую штуку:
че то мне не очень нравится код. Например вот это
SH>
А>здесь заняли мутекс. А когда освобождать будем? В деструкторе? А в деструкторе мы его опять ждем! Баг, однако!
Не, не баг, а фича. Фича mutex'ов. Они поддерживают счетчик, сколько раз занял, столько и отпустил. Если ты внимательно посмотришь на деструктор, то увидишь, что "читатели" освобождают mutex один раз, т.к. занимали его один раз, а "писатели" — два раза.
Занимать mutex в деструкторе нужно для того, чтобы уход последнего читателя был атомарной операцией. Т.е. что бы во время этого другие читател не входили, а то плохо может получиться.
Делай что должно, и будь что будет
Re[3]: Универсальный блокировщик типа читатели/писатель
Здравствуйте SergH, Вы писали:
SH>Здравствуйте Алекс, Вы писали:
[]
SH>Не, не баг, а фича. Фича mutex'ов. Они поддерживают счетчик, сколько раз занял, столько и отпустил. Если ты внимательно посмотришь на деструктор, то увидишь, что "читатели" освобождают mutex один раз, т.к. занимали его один раз, а "писатели" — два раза.
SH>Занимать mutex в деструкторе нужно для того, чтобы уход последнего читателя был атомарной операцией. Т.е. что бы во время этого другие читател не входили, а то плохо может получиться.
В смысле между InterlockedDecrement() и SetEvent()? Может быть. Под утро конечно плохо соображается.
И все равно. Плохо что мы не контролируем сами время сброса. Может быть в этой функции (где создается Locker) я еще чего-нибуlь хочу поделать, длительное. Может очень длительное.
Re[4]: Универсальный блокировщик типа читатели/писатель
Здравствуйте Алекс, Вы писали:
А>В смысле между InterlockedDecrement() и SetEvent()?
Угу.
А>И все равно. Плохо что мы не контролируем сами время сброса. Может быть в этой функции (где создается Locker) я еще чего-нибуlь хочу поделать, длительное. Может очень длительное.
Тогда так:
void func()
{
// длительное...
{
// и здесь длительное...
SomeLoker lock(false);
// обращаемся к ресурсу...
}
// опять длительное...
}
Да и вообще, добавить сюда функции типа lock/unlock — элементарно. Просто мне не нужно, было, я и не стал...
Делай что должно, и будь что будет
Re: SRC: Универсальный блокировщик типа читатели/писатель
От:
Аноним
Дата:
18.09.02 09:05
Оценка:
Здравствуйте SergH. Поскольку Вы явно используете этот код в рамках одного процесса, то не проще и понятнее ли пользоваться критическими секциями ? Например, вот так:
Здравствуйте Аноним, Вы писали:
А>Поскольку Вы явно используете этот код в рамках одного процесса, то не проще и понятнее ли пользоваться критическими секциями ? Например, вот так:
[skip]
Я начинал с чего-то подобного. Но такой подход не позволяет отделить читателей от писателей, т.е. несколько читателей не могут читать одновременно. Мне это не подходит.
Заменить mutex на критическую секцию нельзя, т.к. её не передать в WaitForMultipleObjects, а захватывать объекты по одному в данном случае тоже нельзя. Иначе может получиться так, что писатель в конструкторе захватил критическую секцию, и ждёт события, а читатель в деструкторе ждёт критическую секцию...