Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизация и мьютексы 
:(
    Опции темы
nerezus
Дата 2.9.2009, 07:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вселенский отказник
****


Профиль
Группа: Участник
Сообщений: 3330
Регистрация: 15.6.2005

Репутация: нет
Всего: 43



Код

class InterProcessLock(object):
    def lock(self, delta=0.01):
        while True:
            try:
                self.lockNoWait()
                break;
            except:
                time.sleep(delta)
    
    def __init__(self, name=None):
        self.mutex = None
        if not name:
            name = sys.argv[0]
        self.name = base64.b64encode(name).replace('=','')

    def lockNoWait(self):
        self.mutex = win32event.CreateMutex(None, 0, self.name)
        if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
            self.mutex.Close()
            self.mutex = None
            raise Exception('acquired')

    def unlock(self):
        self.mutex.Close()




Задача: Нужно сделать многопроцессную крит. секцию.
Предполагаю юзать так:
lock = InterProcessLock('name')
lock.lock()
bebebe()
lock.unlock()

Имеются проблемы, причем неизвестно с чем связанные: в нескольких случаях mutex не определяется и не блокирует, а unlock над ним вызывает исключение.

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

Какие альтернативы есть?


--------------------
Сообщество художников Artsociety.ru
PM MAIL WWW   Вверх
Lazin
Дата 2.9.2009, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



если mutex.Close вызывает CloseHandle, то это ошибка, для того, что-бы освободить мьютекс, нужно вызвать ReleaseMutex
вот мой именованный мьютекс, правда на с++
Код

/** @bfeif RAII idiom 
 *  @param TLock - resource type
 *  @param try_enter - try to acquire lock
 *  @param enter - resource acquire
 *  @param leave - resource release
 */
template< 
    class TLock, 
    void (TLock::*enter)() = &TLock::enter, 
    bool (TLock::*try_enter)() = &TLock::try_enter,
    void (TLock::*leave)() = &TLock::leave
>
class advanced_scoped_lock : boost::noncopyable
{
    TLock* lock_;
public:
    advanced_scoped_lock() : lock_(0)
    {
    }
    advanced_scoped_lock(TLock& lock) : lock_(&lock) 
    { 
        (lock_->*enter)(); 
    }
    ~advanced_scoped_lock() 
    { 
        if(lock_)
            (lock_->*leave)(); 
    }
    void acquire(TLock& lock)
    {
        if (lock_)
            (lock_->*leave)(); 
        lock_ = &lock;
        (lock_->*enter)(); 
    }
    bool try_acquire(TLock& lock)
    {
        if (lock_)
            (lock_->*leave)(); 
        lock_ = &lock;
        return (lock_->*try_enter)();
    }
    void release()
    {
        if(!lock_)
            return;
        (lock_->*leave)();
        lock_ = 0;
    }
};


/** @brief Именованый мьютекс
 */
class named_mutex
{
    HANDLE mutex_;///< object handle
public:
    ///Конструктор.
    /** Создает мьютекс
     *  @param name имя объекта. К имени автоматически добавляется Global\programname.
     */
    named_mutex(const char* name) : mutex_(0)
    {
        std::stringstream mname;
        mname << "Global\\programname." << name << std::ends;
        mutex_ = CreateMutex( NULL, FALSE, mname.str().c_str() );
        if (mutex_ == NULL)
        {
            THROW_SYSTEM_ERROR
        }
    }
    ///Деструктор объекта
    ~named_mutex()
    {
        CloseHandle(mutex_);
    }
    ///Захват ресурса (блокирующий)
    /**
     *  Ф-я блокирует вызвавший поток. Захватывает мьютекс.
     */
    void acquire()
    {
        DWORD result = WaitForSingleObject(mutex_, INFINITE);
        if(result != WAIT_OBJECT_0)
        {
            THROW_SYSTEM_ERROR
        }
    }
    ///Освобождение ресурса
    void release()
    {
        if (!ReleaseMutex(mutex_))
        {
            THROW_SYSTEM_ERROR
        }
    }
    ///Неблокирующий захват ресурса
    bool try_acquire()
    {
        DWORD result = WaitForSingleObject(mutex_, 0);
        if(result == WAIT_FAILED)
        {
            THROW_SYSTEM_ERROR
        }
        return (result == WAIT_OBJECT_0);
    }
    typedef advanced_scoped_lock<named_mutex, &named_mutex::acquire, &named_mutex::try_acquire, &named_mutex::release> scoped_lock;
};




Это сообщение отредактировал(а) Lazin - 2.9.2009, 08:04
PM MAIL Skype GTalk   Вверх
nerezus
Дата 3.9.2009, 04:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вселенский отказник
****


Профиль
Группа: Участник
Сообщений: 3330
Регистрация: 15.6.2005

Репутация: нет
Всего: 43



Lazin, ага, спс.

Я почти уверен, что внутри mutex реализован правильно.
Меня больше интересует факт блокирования в виде крит. секции:
Правильно ли использовать блокировку по таймеру? (метод lock вверху)


--------------------
Сообщество художников Artsociety.ru
PM MAIL WWW   Вверх
Lazin
Дата 3.9.2009, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 8
Всего: 154



nerezus, честно говоря я вообще не понял, зачем нужно каждый раз в методе lockNoWait - пытаться создать мьютекс, а в методе unlock - удалить, а так-же, почему метод lock работает именно так. Если тебе нужен мьютекс, для синхронизации процессов, то ты:
  • в конструкторе, создаешь именованный мьютекс(CreateMutex)
  • в деструкторе - удаляешь (метод Close)
  • в методе lock - вызываешь WaitForSingleObject, в качестве параметра передаешь свой мьютекс
  • в методе unlock - вызываешь ReleaseMutex

PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0906 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.