winsock_init.hpp 3.2 KB

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