SRC: Универсальный блокировщик типа читатели/писатель
От: SergH Россия  
Дата: 18.09.02 00:05
Оценка:
Здравствуйте.

Понадобилось мне в нескольких независимых местах блокировать разные ресурсы на чтение/запись. Написал такую штуку:

#ifndef LOCKER_H
#define LOCKER_H

template<int magic>
class Locker
{
public:
    Locker(bool write) 
    {
        init();

        m_write = write;

        if (!m_write)
        {
            WaitForSingleObject(mutex, INFINITE);

            if (!readers)
            {
                ResetEvent(event);
            }

            InterlockedIncrement(&readers);

            ReleaseMutex(mutex);
        }
        else
        {
            HANDLE h[] = {event, mutex};

            WaitForMultipleObjects(2, h, TRUE, INFINITE);
        }
    }

    ~Locker() 
    {
        WaitForSingleObject(mutex, INFINITE);

        if (!m_write)
        {
            InterlockedDecrement(&readers);

            if (!readers)
            {
                SetEvent(event);
            }
        }
        else
        {
            ReleaseMutex(mutex);
        }

        ReleaseMutex(mutex);
    };

private:

    void init()
    {
        if (!first) return;
        first = false;
        mutex = CreateMutex(NULL, FALSE, NULL);
        event = CreateEvent(NULL, TRUE, TRUE, NULL);
    }

    static bool   first;
    static HANDLE mutex;
    static HANDLE event;
    static LONG   readers;

    bool m_write;
};

template<int magic>
bool Locker<magic>::first = true;

template<int magic>
HANDLE Locker<magic>::mutex = NULL;

template<int magic>
HANDLE Locker<magic>::event = NULL;

template<int magic>
LONG Locker<magic>::readers = 0;

#endif //LOCKER_H


Пример использования:

typedef Locker<123> Resource1Locker;
typedef Locker<456> Resource2Locker;

.....

void func1()
{
    Resource1Locker lock(false);
    // теперь первый ресурс можно безболезненно читать, его не изменят до конца функции
}

void func2()
{
    Resource2Locker lock(true);
    // теперь второй ресурс можно безболезненно изменять, его не будут читать до конца функции
}


Просто, понятно, работает (!)... Компилится в VC6 (!!). Единственное слабое место — код инициализации . Но тут уж ничего не поделаешь (если кто-то знает способ — опубликуйте, буду благодарен).. Параноикам могу предложить перед началом создовать по штуке объектов каждого класса, тогда этой проблемы не будет. Лично я не настолько параноик, предпочитаю надеяться на лучшее
Делай что должно, и будь что будет
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.