STLSoft - ... Robust, Lightweight, Cross-platform, Template Software ... ATLSTL - Template Software for the Active Template Library COMSTL - The Standard Template Library meets the Component Object Model .netSTL - Standard Template Library meets the Microsoft.NET Common Language Runtime InetSTL - The Standard Template Library meets WinInet MFCSTL - Template Software for the Microsoft Foundation Classes UNIXSTL - Template Software for the UNIX Operating System WinSTL - where the Standard Template Library meets the Win32 API

Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

winstl_process_mutex.h

Go to the documentation of this file.
00001 /* 
00002  * File:        winstl_process_mutex.h
00003  *
00004  * Purpose:     Inter-process mutext, based on Windows MUTEX.
00005  *
00006  * Date:        15th May 2002
00007  * Updated:     11th September 2004
00008  *
00009  * Home:        http://stlsoft.org/
00010  *
00011  * Copyright (c) 2002-2004, Matthew Wilson and Synesis Software
00012  * All rights reserved.
00013  *
00014  * Redistribution and use in source and binary forms, with or without
00015  * modification, are permitted provided that the following conditions are met:
00016  *
00017  * - Redistributions of source code must retain the above copyright notice, this
00018  *   list of conditions and the following disclaimer.
00019  * - Redistributions in binary form must reproduce the above copyright notice,
00020  *   this list of conditions and the following disclaimer in the documentation
00021  *   and/or other materials provided with the distribution.
00022  * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
00023  *   any contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036  * POSSIBILITY OF SUCH DAMAGE.
00037  *
00038  * 
00039 
00040 
00044 
00045 #ifndef WINSTL_INCL_H_WINSTL_PROCESS_MUTEX
00046 #define WINSTL_INCL_H_WINSTL_PROCESS_MUTEX
00047 
00048 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00049 # define WINSTL_VER_H_WINSTL_PROCESS_MUTEX_MAJOR        2
00050 # define WINSTL_VER_H_WINSTL_PROCESS_MUTEX_MINOR        0
00051 # define WINSTL_VER_H_WINSTL_PROCESS_MUTEX_REVISION     1
00052 # define WINSTL_VER_H_WINSTL_PROCESS_MUTEX_EDIT         23
00053 #endif /* !__STLSOFT_DOCUMENTATION_SKIP_SECTION */
00054 
00055 /* 
00056  * Includes
00057  */
00058 
00059 #ifndef WINSTL_INCL_H_WINSTL
00060 # include "winstl.h"    // Include the WinSTL root header
00061 #endif /* !WINSTL_INCL_H_WINSTL */
00062 
00063 /* 
00064  * Namespace
00065  */
00066 
00067 #ifndef _WINSTL_NO_NAMESPACE
00068 # if defined(_STLSOFT_NO_NAMESPACE) || \
00069      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00070 /* There is no stlsoft namespace, so must define ::winstl */
00071 namespace winstl
00072 {
00073 # else
00074 /* Define stlsoft::winstl_project */
00075 
00076 namespace stlsoft
00077 {
00078 
00079 namespace winstl_project
00080 {
00081 
00082 # endif /* _STLSOFT_NO_NAMESPACE */
00083 #endif /* !_WINSTL_NO_NAMESPACE */
00084 
00085 /* 
00086  * Classes
00087  */
00088 
00089 #ifdef __SYNSOFT_DBS_COMPILER_SUPPORTS_PRAGMA_MESSAGE
00090 # pragma message(_sscomp_fileline_message("This needs to be parameterised with a winstl::system_resource_policy, which would control whether to throw if MX create fails"))
00091 #endif /* __SYNSOFT_DBS_COMPILER_SUPPORTS_PRAGMA_MESSAGE */
00092 
00093 // class process_mutex
00095 class process_mutex
00096 {
00097 public:
00098     typedef process_mutex   class_type;
00099 
00102 public:
00104     process_mutex() winstl_throw_0()
00105         : m_mx(create_mutex_(NULL, false, static_cast<ws_char_a_t const *>(0), m_bCreated))
00106         , m_bAbandoned(false)
00107     {}
00109     ss_explicit_k process_mutex(ws_char_a_t const *name) winstl_throw_0()
00110         : m_mx(create_mutex_(NULL, false, name, m_bCreated))
00111         , m_bAbandoned(false)
00112     {}
00114     ss_explicit_k process_mutex(ws_char_w_t const *name) winstl_throw_0()
00115         : m_mx(create_mutex_(NULL, false, name, m_bCreated))
00116         , m_bAbandoned(false)
00117     {}
00119     ss_explicit_k process_mutex(ws_bool_t bInitialOwer) winstl_throw_0()
00120         : m_mx(create_mutex_(NULL, bInitialOwer, static_cast<ws_char_a_t const *>(0), m_bCreated))
00121         , m_bAbandoned(false)
00122     {}
00124     ss_explicit_k process_mutex(ws_char_a_t const *name, ws_bool_t bInitialOwer) winstl_throw_0()
00125         : m_mx(create_mutex_(NULL, bInitialOwer, name, m_bCreated))
00126         , m_bAbandoned(false)
00127     {}
00129     ss_explicit_k process_mutex(ws_char_w_t const *name, ws_bool_t bInitialOwer) winstl_throw_0()
00130         : m_mx(create_mutex_(NULL, bInitialOwer, name, m_bCreated))
00131         , m_bAbandoned(false)
00132     {}
00134     ss_explicit_k process_mutex(ws_char_a_t const *name, ws_bool_t bInitialOwer, LPSECURITY_ATTRIBUTES psa) winstl_throw_0()
00135         : m_mx(create_mutex_(psa, bInitialOwer, name, m_bCreated))
00136         , m_bAbandoned(false)
00137     {}
00139     ss_explicit_k process_mutex(ws_char_w_t const *name, ws_bool_t bInitialOwer, LPSECURITY_ATTRIBUTES psa) winstl_throw_0()
00140         : m_mx(create_mutex_(psa, bInitialOwer, name, m_bCreated))
00141         , m_bAbandoned(false)
00142     {}
00143 
00145     ~process_mutex() winstl_throw_0()
00146     {
00147         if(m_mx != NULL)
00148         {
00149             ::CloseHandle(m_mx);
00150         }
00151     }
00152 
00153 #if 0
00154     void close() winstl_throw_0()
00155     {
00156         if(m_mx != NULL)
00157         {
00158             CloseHandleSetNull(m_mx);
00159         }
00160     }
00161 #endif /* 0 */
00162 
00164 
00167 public:
00169     void lock() winstl_throw_0()
00170     {
00171         DWORD   dwRes   =   ::WaitForSingleObject(m_mx, INFINITE);
00172 
00173         m_bAbandoned = (dwRes == WAIT_ABANDONED);
00174     }
00176     ws_bool_t lock(ws_dword_t wait) winstl_throw_0()
00177     {
00178         DWORD   dwRes   =   ::WaitForSingleObject(m_mx, wait);
00179 
00180         m_bAbandoned = (dwRes == WAIT_ABANDONED);
00181 
00182         return (dwRes == WAIT_OBJECT_0);
00183     }
00187     ws_bool_t try_lock()
00188     {
00189         return lock(0);
00190     }
00192     void unlock() winstl_throw_0()
00193     {
00194         ::ReleaseMutex(m_mx);
00195     }
00197 
00200 public:
00201     HANDLE  handle()
00202     {
00203         return m_mx;
00204     }
00206 
00209 public:
00215     ws_bool_t created() const
00216     {
00217         return m_bCreated;
00218     }
00219 
00226     ws_bool_t abandoned() const
00227     {
00228         return m_bAbandoned;
00229     }
00230 
00232 
00233 // Implementation
00234 private:
00235     static HANDLE create_mutex_(LPSECURITY_ATTRIBUTES psa, ws_bool_t bInitialOwner, ws_char_a_t const *name, ws_bool_t &bCreated)
00236     {
00237         HANDLE  mx  =   ::CreateMutexA(psa, bInitialOwner, name);
00238 
00239         bCreated = (mx != NULL && ::GetLastError() != ERROR_ALREADY_EXISTS);
00240 
00241         return mx;
00242     }
00243     static HANDLE create_mutex_(LPSECURITY_ATTRIBUTES psa, ws_bool_t bInitialOwner, ws_char_w_t const *name, ws_bool_t &bCreated)
00244     {
00245         HANDLE  mx  =   ::CreateMutexW(psa, bInitialOwner, name);
00246 
00247         bCreated = (mx != NULL && ::GetLastError() != ERROR_ALREADY_EXISTS);
00248 
00249         return mx;
00250     }
00251     static HANDLE open_mutex_(ws_dword_t access, ws_bool_t bInheritHandle, ws_char_a_t const *name, ws_bool_t &bCreated)
00252     {
00253         HANDLE  mx  =   ::OpenMutexA(access, bInheritHandle, name);
00254 
00255         bCreated = (mx != NULL && ::GetLastError() != ERROR_ALREADY_EXISTS);
00256 
00257         return mx;
00258     }
00259     static HANDLE open_mutex_(ws_dword_t access, ws_bool_t bInheritHandle, ws_char_w_t const *name, ws_bool_t &bCreated)
00260     {
00261         HANDLE  mx  =   ::OpenMutexW(access, bInheritHandle, name);
00262 
00263         bCreated = (mx != NULL && ::GetLastError() != ERROR_ALREADY_EXISTS);
00264 
00265         return mx;
00266     }
00267 
00268 // Members
00269 private:
00270     HANDLE      m_mx;           // The underlying mutex object
00271     ws_bool_t   m_bCreated;     // Did this object (thread) create the underlying mutex object
00272     ws_bool_t   m_bAbandoned;   // Did the previous owner abandon the underlying mutex object
00273 
00274 // Not to be implemented
00275 private:
00276     process_mutex(class_type const &rhs);
00277     process_mutex &operator =(class_type const &rhs);
00278 };
00279 
00280 /* 
00281  * Control shims
00282  */
00283 
00284 #ifndef _WINSTL_NO_NAMESPACE
00285 # if defined(_STLSOFT_NO_NAMESPACE) || \
00286      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00287 } // namespace winstl
00288 # else
00289 } // namespace winstl_project
00290 # endif /* _STLSOFT_NO_NAMESPACE */
00291 #endif /* !_WINSTL_NO_NAMESPACE */
00292 
00294 
00297 
00301 
00306 
00310 inline void lock_instance(winstl_ns_qual(process_mutex) &mx)
00311 {
00312     mx.lock();
00313 }
00314 
00318 inline void unlock_instance(winstl_ns_qual(process_mutex) &mx)
00319 {
00320     mx.unlock();
00321 }
00322 
00324 
00325 #ifndef _WINSTL_NO_NAMESPACE
00326 # if defined(_STLSOFT_NO_NAMESPACE) || \
00327      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00328 namespace winstl {
00329 # else
00330 namespace winstl_project {
00331 #  if defined(__STLSOFT_COMPILER_IS_BORLAND)
00332 using ::stlsoft::lock_instance;
00333 using ::stlsoft::unlock_instance;
00334 #  endif /* __STLSOFT_COMPILER_IS_BORLAND */
00335 # endif /* _STLSOFT_NO_NAMESPACE */
00336 #endif /* !_WINSTL_NO_NAMESPACE */
00337 
00338 /* 
00339  * lock_traits (for the compilers that do not support Koenig Lookup)
00340  */
00341 
00342 // class lock_traits
00344 struct process_mutex_lock_traits
00345 {
00346 public:
00348     typedef process_mutex                lock_type;
00349     typedef process_mutex_lock_traits    class_type;
00350 
00351 // Operations
00352 public:
00354     static void lock(process_mutex &c)
00355     {
00356         lock_instance(c);
00357     }
00358 
00360     static void unlock(process_mutex &c)
00361     {
00362         unlock_instance(c);
00363     }
00364 };
00365 
00367 // Unit-testing
00368 
00369 #ifdef STLSOFT_UNITTEST
00370 
00371 namespace unittest
00372 {
00373     ss_bool_t test_winstl_process_mutex(unittest_reporter *r)
00374     {
00375         using stlsoft::unittest::unittest_initialiser;
00376 
00377         ss_bool_t               bSuccess    =   true;
00378 
00379         unittest_initialiser    init(r, "WinSTL", "process_mutex", __FILE__);
00380 
00381         process_mutex   mx_r(true);
00382 
00383         mx_r.lock();
00384         if(!mx_r.try_lock())
00385         {
00386             r->report("process_mutex could not lock recursively ", __LINE__);
00387             bSuccess = false;
00388         }
00389         else
00390         {
00391             mx_r.unlock();
00392         }
00393         mx_r.unlock();
00394 
00395         process_mutex   mx_named("STLSoft.WinSTL.process_mutex");
00396 
00397         mx_named.lock();
00398         if(!mx_named.try_lock())
00399         {
00400             r->report("process_mutex could not lock recursively ", __LINE__);
00401             mx_named.unlock();
00402             bSuccess = false;
00403         }
00404         mx_named.unlock();
00405 
00406         return bSuccess;
00407     }
00408 
00409     unittest_registrar    unittest_winstl_process_mutex(test_winstl_process_mutex);
00410 
00411 } // namespace unittest
00412 
00413 #endif /* STLSOFT_UNITTEST */
00414 
00415 /* 
00416 
00417 #ifndef _WINSTL_NO_NAMESPACE
00418 # if defined(_STLSOFT_NO_NAMESPACE) || \
00419      defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00420 } // namespace winstl
00421 # else
00422 } // namespace winstl_project
00423 } // namespace stlsoft
00424 # endif /* _STLSOFT_NO_NAMESPACE */
00425 #endif /* !_WINSTL_NO_NAMESPACE */
00426 
00427 /* 
00428 
00429 #endif /* !WINSTL_INCL_H_WINSTL_PROCESS_MUTEX */
00430 
00431 /* 

STLSoft Libraries documentation © Synesis Software Pty Ltd, 2001-2004