Page 1 of 1

Использование мьютексов для зап

Posted: Sun Mar 15, 2009 2:17 pm
by SmileGobo
Понадобилось тут лабы выполнить по учебе, наконец то можно блеснуть знаниями о замечательной либе wxWidgets :D. В лабе один из пунктов задания: использования мьютексов для запуска одной копии программы. Полез в доку нашел эти мьютексы, объявил глобально в хидере:

Code: Select all

#ifndef TEST2APP_H
#define TEST2APP_H

#include <wx/app.h>
#include <wx/thread.h>
wxMutex myflag1;
class test2App : public wxApp
{
    public:
        virtual bool OnInit();
};

#endif // TEST2APP_H
Компилирую после чего вылазит месаг:
Image
По нажатию ДА ошибка на стадии линковки:

Code: Select all

-------------- Build: Release in test2 ---------------

Linking executable: bin\Release\test2.exe
obj\Release\test2Main.o:test2Main.cpp:(.bss+0x78): multiple definition of `_myflag1'
obj\Release\test2App.o:test2App.cpp:(.bss+0x4): first defined here
collect2: ld returned 1 exit status
Process terminated with status 1 (0 minutes, 0 seconds)
0 errors, 0 warnings

Re: Использование мьютексов для з

Posted: Sun Mar 15, 2009 10:31 pm
by Kolya
Переменная wxMutex myflag1 обявлена в заголовочном файле и включается в два cpp файла - test2Main.cpp и test2App.cpp. Из-за этого появляются ошибки в линковке.

Что бы этого избежать в заголовочном файле нобходимо написать:

Code: Select all

extern wxMutex myflag1;
И в одном из cpp файлов

Code: Select all

wxMutex myflag1;
Но мютексы лучше не использовать для проверки на запуск одного экземпляра приложения, поскольку другой пользователь может злоумышленно создать мютекс с таким же именем и приложение не запустится ни разу. Лучше в таких случаях создавать файл в temp каталоге пользователя и блокировать его.

Posted: Mon Mar 16, 2009 9:07 pm
by SmileGobo
Спасибо, завелось. Но все равно не лочится. Использование мьютексов один из пунктов лаб работы так что ничо не попишешь.

Правильно ли я лочу:

Code: Select all

bool test2App::OnInit()
{
    wxString dmsg=wxString(this->argv[1]);
    test2Dialog* dlg = new test2Dialog(0L, _("wxWidgets Application Template"));
    wxMutexLocker lock(myflag1);
    if (myflag1.TryLock()==wxMUTEX_NO_ERROR ){
        dlg->Alert(dmsg);
    }
    //dlg->Alert()
    dlg->SetIcon(wxICON(aaaa)); // To Set App Icon
    dlg->Show();
    return true;
}
Соответственно при повторном запуске программа не должна выдавать Окошка с месагой(метод Alert);

Posted: Tue Mar 17, 2009 5:52 pm
by Kolya
Мютекс должен лочится на все время работы приложения, а не только на время инициализации, т.е. wxMutexLocker должен быть в методе OnRun(), а не OnInit().

Вызывать метод TryLock второй раз не надо, поскольку это делает wxMutexLocker

И самая главная проблема в том, что в каждом запущенном приложении должен быть один и тот же мютекс. В данном случае создаются каждый раз при запуске новые мютексы и обойти это можно использованием именованых мютексов. А они есть не на всех платформах, если я правильно понимаю, и соответственно нет в wxWidgets. Но можно выковырять мютекс wxMutexInternal из под wxMSW и использовать его:
http://svn.wxwidgets.org/svn/wx/wxWidge ... thread.cpp
Здесь надо придумать и передать придуманное имя в третий параметр ::CreateMutex

Posted: Tue Mar 17, 2009 6:45 pm
by SmileGobo
Ну собственно пока не получалось сделал следующее, учитывая что пишу под винды:

Code: Select all

#include <windows.h>

bool Alone(){
    HANDLE hMutex = CreateMutex(0,TRUE,"UniqueMutex!");
    if(GetLastError() == ERROR_ALREADY_EXISTS){
        CloseHandle(hMutex);
        return false;
    }
    return true;
}

bool test2App::OnInit()
{
    wxString dmsg=wxString(this->argv[1]);
    test2Dialog* dlg = new test2Dialog(0L, _("wxWidgets Application Template"));
    if (!Alone()){
        dlg->Close();
    }
    dlg->SetIcon(wxICON(aaaa)); // To Set App Icon
    dlg->Show();
    return true;
}
Собственно работает и при вызове в OnInit возможно это криво, но мне оказалось более доступно для понимания

Posted: Wed Mar 18, 2009 7:31 am
by Kolya
Случайно нашел

Code: Select all

wxSingleInstanceChecker
Который использует мютексы под виндой для проверки на запуск одного экземпляра приложения. Под юниксами он использует правильный путь блокировки файла в домашнем каталоге.

Если там еще покопатся, то можно найти много чего интерестного :).

Posted: Wed Mar 18, 2009 9:36 pm
by SmileGobo
Возьму на вооружение! :D