winsock_init.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. //
  2. // winsock_init.hpp
  3. // ~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2008 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/push_options.hpp>
  16. #include <boost/asio/detail/push_options.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/system/system_error.hpp>
  19. #include <boost/asio/detail/pop_options.hpp>
  20. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  21. #include <boost/asio/detail/push_options.hpp>
  22. #include <boost/shared_ptr.hpp>
  23. #include <boost/throw_exception.hpp>
  24. #include <boost/asio/detail/pop_options.hpp>
  25. #include <boost/asio/error.hpp>
  26. #include <boost/asio/detail/noncopyable.hpp>
  27. #include <boost/asio/detail/socket_types.hpp>
  28. namespace boost {
  29. namespace asio {
  30. namespace detail {
  31. template <int Major = 2, int Minor = 0>
  32. class winsock_init
  33. : private noncopyable
  34. {
  35. private:
  36. // Structure to perform the actual initialisation.
  37. struct do_init
  38. {
  39. do_init()
  40. {
  41. WSADATA wsa_data;
  42. result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data);
  43. }
  44. ~do_init()
  45. {
  46. ::WSACleanup();
  47. }
  48. int result() const
  49. {
  50. return result_;
  51. }
  52. // Helper function to manage a do_init singleton. The static instance of the
  53. // winsock_init object ensures that this function is always called before
  54. // main, and therefore before any other threads can get started. The do_init
  55. // instance must be static in this function to ensure that it gets
  56. // initialised before any other global objects try to use it.
  57. static boost::shared_ptr<do_init> instance()
  58. {
  59. static boost::shared_ptr<do_init> init(new do_init);
  60. return init;
  61. }
  62. private:
  63. int result_;
  64. };
  65. public:
  66. // Constructor.
  67. winsock_init()
  68. : ref_(do_init::instance())
  69. {
  70. // Check whether winsock was successfully initialised. This check is not
  71. // performed for the global instance since there will be nobody around to
  72. // catch the exception.
  73. if (this != &instance_ && ref_->result() != 0)
  74. {
  75. boost::system::system_error e(
  76. boost::system::error_code(ref_->result(),
  77. boost::asio::error::get_system_category()),
  78. "winsock");
  79. boost::throw_exception(e);
  80. }
  81. }
  82. // Destructor.
  83. ~winsock_init()
  84. {
  85. }
  86. private:
  87. // Instance to force initialisation of winsock at global scope.
  88. static winsock_init instance_;
  89. // Reference to singleton do_init object to ensure that winsock does not get
  90. // cleaned up until the last user has finished with it.
  91. boost::shared_ptr<do_init> ref_;
  92. };
  93. template <int Major, int Minor>
  94. winsock_init<Major, Minor> winsock_init<Major, Minor>::instance_;
  95. } // namespace detail
  96. } // namespace asio
  97. } // namespace boost
  98. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  99. #include <boost/asio/detail/pop_options.hpp>
  100. #endif // BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP