Add mechanism for disabling automatic Winsock initialisation.
diff --git a/asio/include/asio/detail/impl/winsock_init.ipp b/asio/include/asio/detail/impl/winsock_init.ipp index ca4c3fc..b5dec69 100644 --- a/asio/include/asio/detail/impl/winsock_init.ipp +++ b/asio/include/asio/detail/impl/winsock_init.ipp
@@ -40,6 +40,14 @@ } } +void winsock_init_base::manual_startup(data& d) +{ + if (::InterlockedIncrement(&d.init_count_) == 1) + { + ::InterlockedExchange(&d.result_, 0); + } +} + void winsock_init_base::cleanup(data& d) { if (::InterlockedDecrement(&d.init_count_) == 0) @@ -48,6 +56,11 @@ } } +void winsock_init_base::manual_cleanup(data& d) +{ + ::InterlockedDecrement(&d.init_count_); +} + void winsock_init_base::throw_on_error(data& d) { long result = ::InterlockedExchangeAdd(&d.result_, 0);
diff --git a/asio/include/asio/detail/winsock_init.hpp b/asio/include/asio/detail/winsock_init.hpp index 404f5d1..0420ce7 100644 --- a/asio/include/asio/detail/winsock_init.hpp +++ b/asio/include/asio/detail/winsock_init.hpp
@@ -38,8 +38,12 @@ ASIO_DECL static void startup(data& d, unsigned char major, unsigned char minor); + ASIO_DECL static void manual_startup(data& d); + ASIO_DECL static void cleanup(data& d); + ASIO_DECL static void manual_cleanup(data& d); + ASIO_DECL static void throw_on_error(data& d); }; @@ -65,7 +69,41 @@ cleanup(data_); } + // This class may be used to indicate that user code will manage Winsock + // initialisation and cleanup. This may be required in the case of a DLL, for + // example, where it is not safe to initialise Winsock from global object + // constructors. + // + // To prevent asio from initialising Winsock, the object must be constructed + // before any Asio's own global objects. With MSVC, this may be accomplished + // by adding the following code to the DLL: + // + // #pragma warning(push) + // #pragma warning(disable:4073) + // #pragma init_seg(lib) + // asio::detail::winsock_init<>::manual manual_winsock_init; + // #pragma warning(pop) + class manual + { + public: + manual() + { + manual_startup(data_); + } + + manual(const manual&) + { + manual_startup(data_); + } + + ~manual() + { + manual_cleanup(data_); + } + }; + private: + friend class manual; static data data_; };