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