1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/os2/snglinst.cpp
3 // Purpose:     implements wxSingleInstanceChecker class for OS/2 using
4 //              named mutexes
5 // Author:      Vadim Zeitlin
6 // Modified by: Lauri Nurmi (modified for OS/2)
7 // Created:     08.02.2009
8 // Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 // ============================================================================
13 // declarations
14 // ============================================================================
15 
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26 
27 #if wxUSE_SNGLINST_CHECKER
28 
29 #ifndef WX_PRECOMP
30     #include "wx/string.h"
31     #include "wx/log.h"
32 #endif //WX_PRECOMP
33 
34 #include "wx/snglinst.h"
35 
36 #define INCL_DOSSEMAPHORES
37 #define INCL_DOSERRORS
38 #include <os2.h>
39 
40 #include "wx/os2/private.h"
41 
42 // ----------------------------------------------------------------------------
43 // wxSingleInstanceCheckerImpl: the real implementation class
44 // ----------------------------------------------------------------------------
45 
46 class WXDLLEXPORT wxSingleInstanceCheckerImpl
47 {
48 public:
wxSingleInstanceCheckerImpl()49     wxSingleInstanceCheckerImpl()
50     {
51         m_hMutex = NULL;
52         m_anotherRunning = false;
53     }
54 
Create(const wxString & name)55     bool Create(const wxString& name)
56     {
57         wxString semName;
58         semName.Printf(wxT("\\SEM32\\%s"), name.c_str());
59         int rc = DosCreateMutexSem(semName.c_str(), &m_hMutex, DC_SEM_SHARED, 1);
60 
61         if ( rc == NO_ERROR ) {
62             m_anotherRunning = false;
63             return true;
64         } else if ( rc == ERROR_DUPLICATE_NAME ) {
65             m_anotherRunning = true;
66             return true;
67         } else {
68             m_anotherRunning = false;  // we don't know for sure in this case
69             wxLogLastError(wxT("DosCreateMutexSem"));
70             return false;
71         }
72     }
73 
IsAnotherRunning() const74     bool IsAnotherRunning() const
75     {
76         return m_anotherRunning;
77     }
78 
~wxSingleInstanceCheckerImpl()79     ~wxSingleInstanceCheckerImpl()
80     {
81         if ( m_hMutex )
82         {
83             if ( !::DosCloseMutexSem(m_hMutex) )
84             {
85                 wxLogLastError(wxT("DosCloseMutexSem"));
86             }
87         }
88     }
89 
90 private:
91     // if true, creating the mutex either succeeded
92     // or we know it failed because another app is running.
93     bool m_anotherRunning;
94 
95     // the mutex handle, may be NULL
96     HMTX m_hMutex;
97 
98     DECLARE_NO_COPY_CLASS(wxSingleInstanceCheckerImpl)
99 };
100 
101 // ============================================================================
102 // wxSingleInstanceChecker implementation
103 // ============================================================================
104 
Create(const wxString & name,const wxString & WXUNUSED (path))105 bool wxSingleInstanceChecker::Create(const wxString& name,
106                                      const wxString& WXUNUSED(path))
107 {
108     wxASSERT_MSG( !m_impl,
109                   wxT("calling wxSingleInstanceChecker::Create() twice?") );
110 
111     // creating unnamed mutex doesn't have the same semantics!
112     wxASSERT_MSG( !name.empty(), wxT("mutex name can't be empty") );
113 
114     m_impl = new wxSingleInstanceCheckerImpl;
115 
116     return m_impl->Create(name);
117 }
118 
DoIsAnotherRunning() const119 bool wxSingleInstanceChecker::DoIsAnotherRunning() const
120 {
121     wxCHECK_MSG( m_impl, false, wxT("must call Create() first") );
122 
123     return m_impl->IsAnotherRunning();
124 }
125 
~wxSingleInstanceChecker()126 wxSingleInstanceChecker::~wxSingleInstanceChecker()
127 {
128     delete m_impl;
129 }
130 
131 #endif // wxUSE_SNGLINST_CHECKER
132