$search
00001 // 00002 // win_mutex.hpp 00003 // ~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 00011 #ifndef ASIO_DETAIL_WIN_MUTEX_HPP 00012 #define ASIO_DETAIL_WIN_MUTEX_HPP 00013 00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 00015 # pragma once 00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 00017 00018 #include "asio/detail/push_options.hpp" 00019 00020 #include "asio/detail/push_options.hpp" 00021 #include <boost/config.hpp> 00022 #include "asio/detail/pop_options.hpp" 00023 00024 #if defined(BOOST_WINDOWS) 00025 00026 #include "asio/error.hpp" 00027 #include "asio/system_error.hpp" 00028 #include "asio/detail/noncopyable.hpp" 00029 #include "asio/detail/socket_types.hpp" 00030 #include "asio/detail/scoped_lock.hpp" 00031 00032 #include "asio/detail/push_options.hpp" 00033 #include <boost/throw_exception.hpp> 00034 #include "asio/detail/pop_options.hpp" 00035 00036 namespace asio { 00037 namespace detail { 00038 00039 class win_mutex 00040 : private noncopyable 00041 { 00042 public: 00043 typedef asio::detail::scoped_lock<win_mutex> scoped_lock; 00044 00045 // Constructor. 00046 win_mutex() 00047 { 00048 int error = do_init(); 00049 if (error != 0) 00050 { 00051 asio::system_error e( 00052 asio::error_code(error, 00053 asio::error::get_system_category()), 00054 "mutex"); 00055 boost::throw_exception(e); 00056 } 00057 } 00058 00059 // Destructor. 00060 ~win_mutex() 00061 { 00062 ::DeleteCriticalSection(&crit_section_); 00063 } 00064 00065 // Lock the mutex. 00066 void lock() 00067 { 00068 int error = do_lock(); 00069 if (error != 0) 00070 { 00071 asio::system_error e( 00072 asio::error_code(error, 00073 asio::error::get_system_category()), 00074 "mutex"); 00075 boost::throw_exception(e); 00076 } 00077 } 00078 00079 // Unlock the mutex. 00080 void unlock() 00081 { 00082 ::LeaveCriticalSection(&crit_section_); 00083 } 00084 00085 private: 00086 // Initialisation must be performed in a separate function to the constructor 00087 // since the compiler does not support the use of structured exceptions and 00088 // C++ exceptions in the same function. 00089 int do_init() 00090 { 00091 #if defined(__MINGW32__) 00092 // Not sure if MinGW supports structured exception handling, so for now 00093 // we'll just call the Windows API and hope. 00094 ::InitializeCriticalSection(&crit_section_); 00095 return 0; 00096 #else 00097 __try 00098 { 00099 ::InitializeCriticalSection(&crit_section_); 00100 } 00101 __except(GetExceptionCode() == STATUS_NO_MEMORY 00102 ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 00103 { 00104 return ERROR_OUTOFMEMORY; 00105 } 00106 00107 return 0; 00108 #endif 00109 } 00110 00111 // Locking must be performed in a separate function to lock() since the 00112 // compiler does not support the use of structured exceptions and C++ 00113 // exceptions in the same function. 00114 int do_lock() 00115 { 00116 #if defined(__MINGW32__) 00117 // Not sure if MinGW supports structured exception handling, so for now 00118 // we'll just call the Windows API and hope. 00119 ::EnterCriticalSection(&crit_section_); 00120 return 0; 00121 #else 00122 __try 00123 { 00124 ::EnterCriticalSection(&crit_section_); 00125 } 00126 __except(GetExceptionCode() == STATUS_INVALID_HANDLE 00127 || GetExceptionCode() == STATUS_NO_MEMORY 00128 ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 00129 { 00130 if (GetExceptionCode() == STATUS_NO_MEMORY) 00131 return ERROR_OUTOFMEMORY; 00132 return ERROR_INVALID_HANDLE; 00133 } 00134 00135 return 0; 00136 #endif 00137 } 00138 00139 ::CRITICAL_SECTION crit_section_; 00140 }; 00141 00142 } // namespace detail 00143 } // namespace asio 00144 00145 #endif // defined(BOOST_WINDOWS) 00146 00147 #include "asio/detail/pop_options.hpp" 00148 00149 #endif // ASIO_DETAIL_WIN_MUTEX_HPP