1// 2// detail/impl/win_static_mutex.ipp 3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4// 5// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6// 7// Distributed under the Boost Software License, Version 1.0. (See accompanying 8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9// 10 11#ifndef ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 12#define ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 13 14#if defined(_MSC_VER) && (_MSC_VER >= 1200) 15# pragma once 16#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18#include "asio/detail/config.hpp" 19 20#if defined(ASIO_WINDOWS) 21 22#include <cstdio> 23#include "asio/detail/throw_error.hpp" 24#include "asio/detail/win_static_mutex.hpp" 25#include "asio/error.hpp" 26 27#include "asio/detail/push_options.hpp" 28 29namespace asio { 30namespace detail { 31 32void win_static_mutex::init() 33{ 34 int error = do_init(); 35 asio::error_code ec(error, 36 asio::error::get_system_category()); 37 asio::detail::throw_error(ec, "static_mutex"); 38} 39 40int win_static_mutex::do_init() 41{ 42 using namespace std; // For sprintf. 43 wchar_t mutex_name[128]; 44#if defined(ASIO_HAS_SECURE_RTL) 45 swprintf_s( 46#else // defined(ASIO_HAS_SECURE_RTL) 47 _snwprintf( 48#endif // defined(ASIO_HAS_SECURE_RTL) 49 mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p", 50 static_cast<unsigned int>(::GetCurrentProcessId()), this); 51 52#if defined(ASIO_WINDOWS_APP) 53 HANDLE mutex = ::CreateMutexExW(0, mutex_name, CREATE_MUTEX_INITIAL_OWNER, 0); 54#else // defined(ASIO_WINDOWS_APP) 55 HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name); 56#endif // defined(ASIO_WINDOWS_APP) 57 DWORD last_error = ::GetLastError(); 58 if (mutex == 0) 59 return ::GetLastError(); 60 61 if (last_error == ERROR_ALREADY_EXISTS) 62 { 63#if defined(ASIO_WINDOWS_APP) 64 ::WaitForSingleObjectEx(mutex, INFINITE, false); 65#else // defined(ASIO_WINDOWS_APP) 66 ::WaitForSingleObject(mutex, INFINITE); 67#endif // defined(ASIO_WINDOWS_APP) 68 } 69 70 if (initialised_) 71 { 72 ::ReleaseMutex(mutex); 73 ::CloseHandle(mutex); 74 return 0; 75 } 76 77#if defined(__MINGW32__) 78 // Not sure if MinGW supports structured exception handling, so for now 79 // we'll just call the Windows API and hope. 80# if defined(UNDER_CE) 81 ::InitializeCriticalSection(&crit_section_); 82# else 83 if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) 84 { 85 last_error = ::GetLastError(); 86 ::ReleaseMutex(mutex); 87 ::CloseHandle(mutex); 88 return last_error; 89 } 90# endif 91#else 92 __try 93 { 94# if defined(UNDER_CE) 95 ::InitializeCriticalSection(&crit_section_); 96# elif defined(ASIO_WINDOWS_APP) 97 ::InitializeCriticalSectionEx(&crit_section_, 0x80000000, 0); 98# else 99 if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) 100 { 101 last_error = ::GetLastError(); 102 ::ReleaseMutex(mutex); 103 ::CloseHandle(mutex); 104 return last_error; 105 } 106# endif 107 } 108 __except(GetExceptionCode() == STATUS_NO_MEMORY 109 ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 110 { 111 ::ReleaseMutex(mutex); 112 ::CloseHandle(mutex); 113 return ERROR_OUTOFMEMORY; 114 } 115#endif 116 117 initialised_ = true; 118 ::ReleaseMutex(mutex); 119 ::CloseHandle(mutex); 120 return 0; 121} 122 123} // namespace detail 124} // namespace asio 125 126#include "asio/detail/pop_options.hpp" 127 128#endif // defined(ASIO_WINDOWS) 129 130#endif // ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP 131