1 // 2 // detail/winsock_init.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2017 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_WINSOCK_INIT_HPP 12 #define ASIO_DETAIL_WINSOCK_INIT_HPP 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) || defined(__CYGWIN__) 21 22 #include "asio/detail/push_options.hpp" 23 24 namespace asio { 25 namespace detail { 26 27 class winsock_init_base 28 { 29 protected: 30 // Structure to track result of initialisation and number of uses. POD is used 31 // to ensure that the values are zero-initialised prior to any code being run. 32 struct data 33 { 34 long init_count_; 35 long result_; 36 }; 37 38 ASIO_DECL static void startup(data& d, 39 unsigned char major, unsigned char minor); 40 41 ASIO_DECL static void manual_startup(data& d); 42 43 ASIO_DECL static void cleanup(data& d); 44 45 ASIO_DECL static void manual_cleanup(data& d); 46 47 ASIO_DECL static void throw_on_error(data& d); 48 }; 49 50 template <int Major = 2, int Minor = 0> 51 class winsock_init : private winsock_init_base 52 { 53 public: winsock_init(bool allow_throw=true)54 winsock_init(bool allow_throw = true) 55 { 56 startup(data_, Major, Minor); 57 if (allow_throw) 58 throw_on_error(data_); 59 } 60 winsock_init(const winsock_init &)61 winsock_init(const winsock_init&) 62 { 63 startup(data_, Major, Minor); 64 throw_on_error(data_); 65 } 66 ~winsock_init()67 ~winsock_init() 68 { 69 cleanup(data_); 70 } 71 72 // This class may be used to indicate that user code will manage Winsock 73 // initialisation and cleanup. This may be required in the case of a DLL, for 74 // example, where it is not safe to initialise Winsock from global object 75 // constructors. 76 // 77 // To prevent asio from initialising Winsock, the object must be constructed 78 // before any Asio's own global objects. With MSVC, this may be accomplished 79 // by adding the following code to the DLL: 80 // 81 // #pragma warning(push) 82 // #pragma warning(disable:4073) 83 // #pragma init_seg(lib) 84 // asio::detail::winsock_init<>::manual manual_winsock_init; 85 // #pragma warning(pop) 86 class manual 87 { 88 public: manual()89 manual() 90 { 91 manual_startup(data_); 92 } 93 manual(const manual &)94 manual(const manual&) 95 { 96 manual_startup(data_); 97 } 98 ~manual()99 ~manual() 100 { 101 manual_cleanup(data_); 102 } 103 }; 104 105 private: 106 friend class manual; 107 static data data_; 108 }; 109 110 template <int Major, int Minor> 111 winsock_init_base::data winsock_init<Major, Minor>::data_; 112 113 // Static variable to ensure that winsock is initialised before main, and 114 // therefore before any other threads can get started. 115 static const winsock_init<>& winsock_init_instance = winsock_init<>(false); 116 117 } // namespace detail 118 } // namespace asio 119 120 #include "asio/detail/pop_options.hpp" 121 122 #if defined(ASIO_HEADER_ONLY) 123 # include "asio/detail/impl/winsock_init.ipp" 124 #endif // defined(ASIO_HEADER_ONLY) 125 126 #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) 127 128 #endif // ASIO_DETAIL_WINSOCK_INIT_HPP 129