Allow creating wxSingleInstanceChecker with default name.

This makes it easier to use in common cases: there is no need to come up with
a unique name for the checker any more as sufficiently unique combination of
wxApp::GetAppName() and wxGetUserId() is used if no name was explicitly given.

This is done by calling the new CreateDefault() on demand from
IsAnotherRunning() instead of simply creating the checker with the default
name in the default ctor for compatibility (you had to call Create() after
using the default ctor before and it can only be called once) and because
wxTheApp might not exist yet when wxSingleInstanceChecker is created.

Closes #11166.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61945 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-09-16 12:38:00 +00:00
parent 3c3ead1d15
commit 956b3d92ef
5 changed files with 83 additions and 23 deletions

View File

@@ -15,6 +15,9 @@
#if wxUSE_SNGLINST_CHECKER #if wxUSE_SNGLINST_CHECKER
#include "wx/app.h"
#include "wx/utils.h"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxSingleInstanceChecker // wxSingleInstanceChecker
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -33,9 +36,11 @@ public:
Create(name, path); Create(name, path);
} }
// name must be given and be as unique as possible, it is used as the mutex // notice that calling Create() is optional now, if you don't do it before
// name under Win32 and the lock file name under Unix - // calling IsAnotherRunning(), CreateDefault() is used automatically
// wxTheApp->GetAppName() may be a good value for this parameter //
// name it is used as the mutex name under Win32 and the lock file name
// under Unix so it should be as unique as possible and must be non-empty
// //
// path is optional and is ignored under Win32 and used as the directory to // path is optional and is ignored under Win32 and used as the directory to
// create the lock file in under Unix (default is wxGetHomeDir()) // create the lock file in under Unix (default is wxGetHomeDir())
@@ -44,8 +49,32 @@ public:
// instance is running - use IsAnotherRunning() to check it // instance is running - use IsAnotherRunning() to check it
bool Create(const wxString& name, const wxString& path = wxEmptyString); bool Create(const wxString& name, const wxString& path = wxEmptyString);
// use the default name, which is a combination of wxTheApp->GetAppName()
// and wxGetUserId() for mutex/lock file
//
// this is called implicitly by IsAnotherRunning() if the checker hadn't
// been created until then
bool CreateDefault()
{
wxCHECK_MSG( wxTheApp, false, "must have application instance" );
return Create(wxTheApp->GetAppName() + '-' + wxGetUserId());
}
// is another copy of this program already running? // is another copy of this program already running?
bool IsAnotherRunning() const; bool IsAnotherRunning() const
{
if ( !m_impl )
{
if ( !const_cast<wxSingleInstanceChecker *>(this)->CreateDefault() )
{
// if creation failed, return false as it's better to not
// prevent this instance from starting up if there is an error
return false;
}
}
return DoIsAnotherRunning();
}
// dtor is not virtual, this class is not meant to be used polymorphically // dtor is not virtual, this class is not meant to be used polymorphically
~wxSingleInstanceChecker(); ~wxSingleInstanceChecker();
@@ -54,6 +83,9 @@ private:
// common part of all ctors // common part of all ctors
void Init() { m_impl = NULL; } void Init() { m_impl = NULL; }
// do check if another instance is running, called only if m_impl != NULL
bool DoIsAnotherRunning() const;
// the implementation details (platform specific) // the implementation details (platform specific)
class WXDLLIMPEXP_FWD_BASE wxSingleInstanceCheckerImpl *m_impl; class WXDLLIMPEXP_FWD_BASE wxSingleInstanceCheckerImpl *m_impl;

View File

@@ -23,8 +23,7 @@
@code @code
bool MyApp::OnInit() bool MyApp::OnInit()
{ {
const wxString name = wxString::Format("MyApp-%s", wxGetUserId().c_str()); m_checker = new wxSingleInstanceChecker;
m_checker = new wxSingleInstanceChecker(name);
if ( m_checker-IsAnotherRunning() ) if ( m_checker-IsAnotherRunning() )
{ {
wxLogError(_("Another program instance is already running, aborting.")); wxLogError(_("Another program instance is already running, aborting."));
@@ -48,10 +47,12 @@
} }
@endcode @endcode
Note using wxGetUserId() to construct the name: this allows different user Note that by default wxSingleInstanceChecker::CreateDefault() is used to
to run the application concurrently which is usually the intended goal. create the checker meaning that it will be initialized differently for
If you don't use the user name in the wxSingleInstanceChecker name, only different users and thus will allow different users to run the application
one user would be able to run the application at a time. concurrently which is usually the required behaviour. However if only a
single instance of a program should be running system-wide, you need to
call Create() with a custom name which does @em not include wxGetUserId().
This class is implemented for Win32 and Unix platforms (supporting @c fcntl() This class is implemented for Win32 and Unix platforms (supporting @c fcntl()
system call, but almost all of modern Unix systems do) only. system call, but almost all of modern Unix systems do) only.
@@ -63,43 +64,53 @@ class wxSingleInstanceChecker
{ {
public: public:
/** /**
Default ctor, use Create() after it. Default constructor.
You may call Create() after using it or directly call
IsAnotherRunning() in which case CreateDefault() will be implicitly
used.
*/ */
wxSingleInstanceChecker(); wxSingleInstanceChecker();
/** /**
Like Create() but without error checking. Constructor calling Create().
This constructor does exactly the same thing as Create() but doesn't
allow to check for errors.
*/ */
wxSingleInstanceChecker(const wxString& name, wxSingleInstanceChecker(const wxString& name,
const wxString& path = wxEmptyString); const wxString& path = wxEmptyString);
/** /**
Destructor frees the associated resources. Destructor frees the associated resources.
Note that it is not virtual, this class is not meant to be used polymorphically. Note that it is not virtual, this class is not meant to be used polymorphically.
*/ */
~wxSingleInstanceChecker(); ~wxSingleInstanceChecker();
/** /**
Initialize the object if it had been created using the default constructor. Initialize the object if it had been created using the default constructor.
Note that you can't call Create() more than once, so calling it if the Note that you can't call Create() more than once, so calling it if the
@ref wxSingleInstanceChecker() "non default ctor" had been used is an error. non default ctor had been used is an error.
@param name @param name
Must be given and be as unique as possible. It is used as the Must be given and be as unique as possible. It is used as the
mutex name under Win32 and the lock file name under Unix. mutex name under Win32 and the lock file name under Unix.
GetAppName() and wxGetUserId() are commonly used to construct wxApp::GetAppName() and wxGetUserId() are commonly used to construct
this parameter. this parameter.
@param path @param path
The path is optional and is ignored under Win32 and used as the The path is optional and is ignored under Win32 and used as the
directory to create the lock file in under Unix directory to create the lock file in under Unix
(default is wxGetHomeDir()). (default is wxGetHomeDir()).
@return Returns @false if initialization failed, it doesn't mean that @return
another instance is running - use IsAnotherRunning() to check Returns @false if initialization failed, it doesn't mean that
for it. another instance is running -- use IsAnotherRunning() to check for
it.
@note @note
One of possible reasons while Create may fail on Unix is that the lock One of possible reasons while Create() may fail on Unix is that the lock
file used for checking already exists but was not created by the user. file used for checking already exists but was not created by the user.
Therefore applications shouldn't treat failure of this function as fatal Therefore applications shouldn't treat failure of this function as fatal
condition, because doing so would open them to the possibility of a condition, because doing so would open them to the possibility of a
@@ -111,8 +122,25 @@ public:
const wxString& path = wxEmptyString); const wxString& path = wxEmptyString);
/** /**
Returns @true if another copy of this program is already running, @false Calls Create() with default name.
otherwise.
This method simply calls Create() with a string composed of
wxApp::GetAppName() and wxGetUserId().
Because this method uses wxApp::GetAppName(), it may only be called
after the global application was constructed.
@since 2.9.1
*/
bool CreateDefault();
/**
Returns @true if another copy of this program is already running and
@false otherwise.
Notice that if the object was created using the default constructor
Create() hadn't been called before this method, it will call
CreateDefault() automatically.
*/ */
bool IsAnotherRunning() const; bool IsAnotherRunning() const;
}; };

View File

@@ -113,7 +113,7 @@ bool wxSingleInstanceChecker::Create(const wxString& name,
return m_impl->Create(name); return m_impl->Create(name);
} }
bool wxSingleInstanceChecker::IsAnotherRunning() const bool wxSingleInstanceChecker::DoIsAnotherRunning() const
{ {
wxCHECK_MSG( m_impl, false, wxT("must call Create() first") ); wxCHECK_MSG( m_impl, false, wxT("must call Create() first") );

View File

@@ -117,7 +117,7 @@ bool wxSingleInstanceChecker::Create(const wxString& name,
return m_impl->Create(name); return m_impl->Create(name);
} }
bool wxSingleInstanceChecker::IsAnotherRunning() const bool wxSingleInstanceChecker::DoIsAnotherRunning() const
{ {
wxCHECK_MSG( m_impl, false, wxT("must call Create() first") ); wxCHECK_MSG( m_impl, false, wxT("must call Create() first") );

View File

@@ -371,7 +371,7 @@ bool wxSingleInstanceChecker::Create(const wxString& name,
return m_impl->Create(fullname); return m_impl->Create(fullname);
} }
bool wxSingleInstanceChecker::IsAnotherRunning() const bool wxSingleInstanceChecker::DoIsAnotherRunning() const
{ {
wxCHECK_MSG( m_impl, false, wxT("must call Create() first") ); wxCHECK_MSG( m_impl, false, wxT("must call Create() first") );