diff --git a/beast/Arithmetic.h b/beast/Arithmetic.h index edc285731..2add9c460 100644 --- a/beast/Arithmetic.h +++ b/beast/Arithmetic.h @@ -26,8 +26,6 @@ #include -#include - #include #include #include diff --git a/beast/chrono/RelativeTime.h b/beast/chrono/RelativeTime.h index 0e42e4144..76809b4a0 100644 --- a/beast/chrono/RelativeTime.h +++ b/beast/chrono/RelativeTime.h @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/beast/chrono/chrono_io.h b/beast/chrono/chrono_io.h index c17fe96fa..b9dfacdfb 100644 --- a/beast/chrono/chrono_io.h +++ b/beast/chrono/chrono_io.h @@ -29,7 +29,6 @@ #include -#include #include #include diff --git a/beast/config/compiler/VisualC.h b/beast/config/compiler/VisualC.h index 84b47018c..e360cdd6b 100644 --- a/beast/config/compiler/VisualC.h +++ b/beast/config/compiler/VisualC.h @@ -22,5 +22,4 @@ #ifndef BEAST_CONFIG_COMPILER_VISUALC_H_INCLUDED #define BEAST_CONFIG_COMPILER_VISUALC_H_INCLUDED -#include #endif diff --git a/beast/crypto/detail/mac_facade.h b/beast/crypto/detail/mac_facade.h index 6dd7ff8b8..c30217431 100644 --- a/beast/crypto/detail/mac_facade.h +++ b/beast/crypto/detail/mac_facade.h @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/beast/crypto/detail/ripemd_context.h b/beast/crypto/detail/ripemd_context.h index 391fd3d4e..0b89921bb 100644 --- a/beast/crypto/detail/ripemd_context.h +++ b/beast/crypto/detail/ripemd_context.h @@ -20,7 +20,6 @@ #ifndef BEAST_CRYPTO_RIPEMD_CONTEXT_H_INCLUDED #define BEAST_CRYPTO_RIPEMD_CONTEXT_H_INCLUDED -#include #include #include #include diff --git a/beast/crypto/detail/sha2_context.h b/beast/crypto/detail/sha2_context.h index 4cb3449fd..6786fca92 100644 --- a/beast/crypto/detail/sha2_context.h +++ b/beast/crypto/detail/sha2_context.h @@ -20,7 +20,6 @@ #ifndef BEAST_CRYPTO_SHA512_CONTEXT_H_INCLUDED #define BEAST_CRYPTO_SHA512_CONTEXT_H_INCLUDED -#include #include #include diff --git a/beast/hash/fnv1a.h b/beast/hash/fnv1a.h index eec288018..0e465d65f 100644 --- a/beast/hash/fnv1a.h +++ b/beast/hash/fnv1a.h @@ -21,7 +21,6 @@ #ifndef BEAST_HASH_FNV1A_H_INCLUDED #define BEAST_HASH_FNV1A_H_INCLUDED -#include #include #include #include // diff --git a/beast/hash/hash_append.h b/beast/hash/hash_append.h index 6a5365ac9..bcb953d69 100644 --- a/beast/hash/hash_append.h +++ b/beast/hash/hash_append.h @@ -24,7 +24,6 @@ #include // for constexpr #include #include -#include #include #include #include diff --git a/beast/hash/siphash.h b/beast/hash/siphash.h index eeabfdcae..e4a4b363f 100644 --- a/beast/hash/siphash.h +++ b/beast/hash/siphash.h @@ -21,7 +21,6 @@ #ifndef BEAST_HASH_SIPHASH_H_INCLUDED #define BEAST_HASH_SIPHASH_H_INCLUDED -#include #include #include diff --git a/beast/hash/xxhasher.h b/beast/hash/xxhasher.h index c17d5ef5c..5525a8450 100644 --- a/beast/hash/xxhasher.h +++ b/beast/hash/xxhasher.h @@ -28,7 +28,6 @@ #include #include -#include #include // #include diff --git a/beast/http/URL.h b/beast/http/URL.h index 459e5a668..dd7fd8072 100644 --- a/beast/http/URL.h +++ b/beast/http/URL.h @@ -52,22 +52,7 @@ public: URL& operator= (URL const& other) = default; /** Move construct a URL. */ -#ifdef _MSC_VER - URL (URL&& other) - : m_scheme(std::move(other.m_scheme)) - , m_host(std::move(other.m_host)) - , m_port(other.m_port) - , m_port_string(std::move(other.m_port_string)) - , m_path(std::move(other.m_path)) - , m_query(std::move(other.m_query)) - , m_fragment(std::move(other.m_fragment)) - , m_userinfo(std::move(other.m_userinfo)) - { - } - -#else URL (URL&& other) = default; -#endif /** Returns `true` if this is an empty URL. */ bool diff --git a/beast/http/basic_parser.h b/beast/http/basic_parser.h index a0397f49c..d0ee4dcff 100644 --- a/beast/http/basic_parser.h +++ b/beast/http/basic_parser.h @@ -27,7 +27,6 @@ #include #include #include -#include namespace beast { diff --git a/beast/http/impl/basic_parser.cpp b/beast/http/impl/basic_parser.cpp index a31a14b4b..0d02380b3 100644 --- a/beast/http/impl/basic_parser.cpp +++ b/beast/http/impl/basic_parser.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include namespace beast { diff --git a/beast/http/message.h b/beast/http/message.h index 4d859d14a..85dfe1913 100644 --- a/beast/http/message.h +++ b/beast/http/message.h @@ -76,16 +76,9 @@ public: template message(); -#if defined(_MSC_VER) && _MSC_VER <= 1800 - message (message&& other); - message& operator= (message&& other); - -#else message (message&& other) = default; message& operator= (message&& other) = default; -#endif - // Memberspace beast::http::headers headers; @@ -220,38 +213,6 @@ message::message() { } -#if defined(_MSC_VER) && _MSC_VER <= 1800 -inline -message::message (message&& other) - : request_ (other.request_) - , method_ (std::move(other.method_)) - , url_ (std::move(other.url_)) - , status_ (other.status_) - , reason_ (std::move(other.reason_)) - , version_ (other.version_) - , keep_alive_ (other.keep_alive_) - , upgrade_ (other.upgrade_) - , headers (std::move(other.headers)) -{ -} - -inline -message& -message::operator= (message&& other) -{ - request_ = other.request_; - method_ = std::move(other.method_); - url_ = std::move(other.url_); - status_ = other.status_; - reason_ = std::move(other.reason_); - version_ = other.version_; - keep_alive_ = other.keep_alive_; - upgrade_ = other.upgrade_; - headers = std::move(other.headers); - return *this; -} -#endif - //------------------------------------------------------------------------------ template diff --git a/beast/http/parser.h b/beast/http/parser.h index 2619d050a..36f784c63 100644 --- a/beast/http/parser.h +++ b/beast/http/parser.h @@ -66,14 +66,8 @@ public: message_.get().request(request); } -#if defined(_MSC_VER) && _MSC_VER <= 1800 - parser& operator= (parser&& other); - -#else parser& operator= (parser&& other) = default; -#endif - private: template void @@ -141,18 +135,6 @@ private: }; //------------------------------------------------------------------------------ - -#if defined(_MSC_VER) && _MSC_VER <= 1800 -inline -parser& -parser::operator= (parser&& other) -{ - basic_parser::operator= (std::move(other)); - message_ = std::move (other.message_); - return *this; -} -#endif - template void parser::do_start() diff --git a/beast/module/core/diagnostic/FatalError.cpp b/beast/module/core/diagnostic/FatalError.cpp index e8d7b2f7e..146041b77 100644 --- a/beast/module/core/diagnostic/FatalError.cpp +++ b/beast/module/core/diagnostic/FatalError.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -27,49 +28,38 @@ namespace beast { //------------------------------------------------------------------------------ +[[noreturn]] void -FatalError (char const* message, char const* file, int line) +FatalError ( + char const* message, + char const* file, + int line) noexcept { - static std::atomic error_count (0); - static std::recursive_mutex gate; + static std::mutex gate; // We only allow one thread to report a fatal error. Other threads that // encounter fatal errors while we are reporting get blocked here. - std::lock_guard lock(gate); + std::lock_guard lock(gate); - // If we encounter a recursive fatal error, then we want to terminate - // unconditionally. - if (error_count++ != 0) - return std::terminate (); + std::cerr << "An error has occurred. The application will terminate.\n"; - // We protect this entire block of code since writing to cerr might trigger - // exceptions. - try + if (message != nullptr && message [0] != 0) + std::cerr << "Message: " << message << '\n'; + + if (file != nullptr && file [0] != 0) + std::cerr << " File: " << file << ":" << line << '\n'; + + auto const backtrace = getStackBacktrace (); + + if (!backtrace.empty ()) { - std::cerr << "An error has occurred. The application will terminate.\n"; + std::cerr << " Stack:" << std::endl; - if (message != nullptr && message [0] != 0) - std::cerr << "Message: " << message << '\n'; - - if (file != nullptr && file [0] != 0) - std::cerr << " File: " << file << ":" << line << '\n'; - - auto const backtrace = getStackBacktrace (); - - if (!backtrace.empty ()) - { - std::cerr << " Stack:" << std::endl; - - for (auto const& frame : backtrace) - std::cerr << " " << frame << '\n'; - } - } - catch (...) - { - // nothing we can do - just fall through and terminate + for (auto const& frame : backtrace) + std::cerr << " " << frame << '\n'; } - return std::terminate (); + std::abort (); } } // beast diff --git a/beast/module/core/diagnostic/FatalError.h b/beast/module/core/diagnostic/FatalError.h index cd6250fd4..15ee3ba1e 100644 --- a/beast/module/core/diagnostic/FatalError.h +++ b/beast/module/core/diagnostic/FatalError.h @@ -35,8 +35,12 @@ namespace beast If multiple threads raise an error, only one will succeed while the others will be blocked before the process terminates. */ +[[noreturn]] void -FatalError (char const* message, char const* file = nullptr, int line = 0); +FatalError ( + char const* message, + char const* file = nullptr, + int line = 0) noexcept; } // beast diff --git a/beast/module/core/diagnostic/SemanticVersion.h b/beast/module/core/diagnostic/SemanticVersion.h index b55a4ef6b..9fa8e57a1 100644 --- a/beast/module/core/diagnostic/SemanticVersion.h +++ b/beast/module/core/diagnostic/SemanticVersion.h @@ -23,8 +23,6 @@ #include #include -#include - namespace beast { /** A Semantic Version number. diff --git a/beast/module/core/files/File.cpp b/beast/module/core/files/File.cpp index 23bd032d5..613c44bde 100644 --- a/beast/module/core/files/File.cpp +++ b/beast/module/core/files/File.cpp @@ -21,7 +21,6 @@ */ //============================================================================== -#include #include #include @@ -29,8 +28,8 @@ namespace beast { File const& File::nonexistent() { - static beast::static_initializer instance; - return *instance; + static File const instance; + return instance; } //------------------------------------------------------------------------------ diff --git a/beast/module/core/thread/DeadlineTimer.cpp b/beast/module/core/thread/DeadlineTimer.cpp index 740b97e23..60ff3fc56 100644 --- a/beast/module/core/thread/DeadlineTimer.cpp +++ b/beast/module/core/thread/DeadlineTimer.cpp @@ -17,8 +17,6 @@ */ //============================================================================== -#include - namespace beast { @@ -47,8 +45,8 @@ public: Manager& instance() { - static beast::static_initializer m; - return *m; + static Manager m; + return m; } // Okay to call on an active timer. diff --git a/beast/net/IPAddress.h b/beast/net/IPAddress.h index 1f42ab41a..fddd7d6cd 100644 --- a/beast/net/IPAddress.h +++ b/beast/net/IPAddress.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/beast/nudb/detail/gentex.h b/beast/nudb/detail/gentex.h index b64da8088..c0f960cf8 100644 --- a/beast/nudb/detail/gentex.h +++ b/beast/nudb/detail/gentex.h @@ -20,7 +20,6 @@ #ifndef BEAST_NUDB_DETAIL_GENTEX_H_INCLUDED #define BEAST_NUDB_DETAIL_GENTEX_H_INCLUDED -#include #include #include #include diff --git a/beast/threads/SpinLock.h b/beast/threads/SpinLock.h index 4d517da23..2311fd541 100644 --- a/beast/threads/SpinLock.h +++ b/beast/threads/SpinLock.h @@ -25,7 +25,6 @@ #define BEAST_THREADS_SPINLOCK_H_INCLUDED #include -#include #include #include #include diff --git a/beast/unit_test/suite.h b/beast/unit_test/suite.h index 6a309423e..6671d5732 100644 --- a/beast/unit_test/suite.h +++ b/beast/unit_test/suite.h @@ -22,7 +22,6 @@ #include -#include #include #include diff --git a/beast/unit_test/thread.h b/beast/unit_test/thread.h index b2ac684a7..fb1fc50cc 100644 --- a/beast/unit_test/thread.h +++ b/beast/unit_test/thread.h @@ -20,7 +20,6 @@ #ifndef BEAST_UNIT_TEST_THREAD_H_INCLUDED #define BEAST_UNIT_TEST_THREAD_H_INCLUDED -#include #include #include #include diff --git a/beast/utility/Utility.unity.cpp b/beast/utility/Utility.unity.cpp index d4313c28a..5eef323fe 100644 --- a/beast/utility/Utility.unity.cpp +++ b/beast/utility/Utility.unity.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/beast/utility/empty_base_optimization.h b/beast/utility/empty_base_optimization.h index 4ab904b47..22e19e0d3 100644 --- a/beast/utility/empty_base_optimization.h +++ b/beast/utility/empty_base_optimization.h @@ -21,7 +21,6 @@ #ifndef BEAST_UTILITY_EMPTY_BASE_OPTIMIZATION_H_INCLUDED #define BEAST_UTILITY_EMPTY_BASE_OPTIMIZATION_H_INCLUDED -#include #include #include diff --git a/beast/utility/impl/Journal.cpp b/beast/utility/impl/Journal.cpp index ec674f691..6f261614e 100644 --- a/beast/utility/impl/Journal.cpp +++ b/beast/utility/impl/Journal.cpp @@ -18,7 +18,6 @@ //============================================================================== #include -#include namespace beast { @@ -60,8 +59,8 @@ public: Journal::Sink& Journal::getNullSink () { - static beast::static_initializer sink; - return *sink; + static NullJournalSink sink; + return sink; } //------------------------------------------------------------------------------ diff --git a/beast/utility/noexcept.h b/beast/utility/noexcept.h deleted file mode 100644 index 03e177425..000000000 --- a/beast/utility/noexcept.h +++ /dev/null @@ -1,39 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Portions of this file are from JUCE. - Copyright (c) 2013 - Raw Material Software Ltd. - Please visit http://www.juce.com - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_UTILITY_NOEXCEPT_H_INCLUDED -#define BEAST_UTILITY_NOEXCEPT_H_INCLUDED - -#ifdef _MSC_VER -# if _MSC_VER < 1900 -# ifdef noexcept -# undef noexcept -# endif -# define noexcept throw() -# endif -# if _MSC_VER > 1600 && ! _ALLOW_KEYWORD_MACROS -# define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining) -# endif -#endif - -#endif diff --git a/beast/utility/static_initializer.h b/beast/utility/static_initializer.h deleted file mode 100644 index 99917f19a..000000000 --- a/beast/utility/static_initializer.h +++ /dev/null @@ -1,258 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_UTILITY_STATIC_INITIALIZER_H_INCLUDED -#define BEAST_UTILITY_STATIC_INITIALIZER_H_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#include -#include -#include -#include -#include -#endif - -namespace beast { - -/** Returns an object with static storage duration. - This is a workaround for Visual Studio 2013 and earlier non-thread - safe initialization of function local objects with static storage duration. - - Usage: - @code - my_class& foo() - { - static static_initializer instance; - return *instance; - } - @endcode -*/ -#ifdef _MSC_VER -template < - class T, - class Tag = void -> -class static_initializer -{ -private: - struct data_t - { - // 0 = unconstructed - // 1 = constructing - // 2 = constructed - long volatile state; - - typename std::aligned_storage ::value>::type storage; - }; - - struct destroyer - { - T* t_; - explicit destroyer (T* t) : t_(t) { } - ~destroyer() { t_->~T(); } - }; - - static - data_t& - data() noexcept; - -public: - template - explicit static_initializer (Args&&... args); - - T& - get() noexcept; - - T const& - get() const noexcept - { - return const_cast(*this).get(); - } - - T& - operator*() noexcept - { - return get(); - } - - T const& - operator*() const noexcept - { - return get(); - } - - T* - operator->() noexcept - { - return &get(); - } - - T const* - operator->() const noexcept - { - return &get(); - } -}; - -//------------------------------------------------------------------------------ - -template -auto -static_initializer ::data() noexcept -> - data_t& -{ - static data_t _; // zero-initialized - return _; -} - -template -template -static_initializer ::static_initializer (Args&&... args) -{ - data_t& _(data()); - - // Double Checked Locking Pattern - - if (_.state != 2) - { - T* const t (reinterpret_cast(&_.storage)); - - for(;;) - { - long prev; - prev = _InterlockedCompareExchange(&_.state, 1, 0); - if (prev == 0) - { - try - { - ::new(t) T (std::forward(args)...); - static destroyer on_exit (t); - _InterlockedIncrement(&_.state); - } - catch(...) - { - // Constructors that throw exceptions are unsupported - std::terminate(); - } - } - else if (prev == 1) - { - std::this_thread::yield(); - } - else - { - assert(prev == 2); - break; - } - } - } -} - -template -T& -static_initializer ::get() noexcept -{ - data_t& _(data()); - for(;;) - { - if (_.state == 2) - break; - std::this_thread::yield(); - } - return *reinterpret_cast(&_.storage); -} - -#else -template < - class T, - class Tag = void -> -class static_initializer -{ -private: - T* instance_; - -public: - template - explicit - static_initializer (Args&&... args); - - static_initializer (); - - T& - get() noexcept - { - return *instance_; - } - - T const& - get() const noexcept - { - return const_cast(*this).get(); - } - - T& - operator*() noexcept - { - return get(); - } - - T const& - operator*() const noexcept - { - return get(); - } - - T* - operator->() noexcept - { - return &get(); - } - - T const* - operator->() const noexcept - { - return &get(); - } -}; - -template -static_initializer ::static_initializer () -{ - static T t; - instance_ = &t; -} - -template -template -static_initializer ::static_initializer (Args&&... args) -{ - static T t (std::forward(args)...); - instance_ = &t; -} - -#endif - -} - -#endif diff --git a/beast/utility/tagged_integer.h b/beast/utility/tagged_integer.h index 49033167c..fb79a5741 100644 --- a/beast/utility/tagged_integer.h +++ b/beast/utility/tagged_integer.h @@ -22,8 +22,6 @@ #include -#include - #include #include #include diff --git a/beast/utility/tests/static_initializer.test.cpp b/beast/utility/tests/static_initializer.test.cpp deleted file mode 100644 index 61159c343..000000000 --- a/beast/utility/tests/static_initializer.test.cpp +++ /dev/null @@ -1,209 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#include -#include -#include -#include -#include -#include - -namespace beast { - -static_assert(__alignof(long) >= 4, ""); - -class static_initializer_test : public unit_test::suite -{ -public: - // Used to create separate instances for each test - struct cxx11_tag { }; - struct beast_tag { }; - template - struct Case - { - enum { count = N }; - using type = Tag; - }; - - struct Counts - { - Counts() - : calls (0) - , constructed (0) - , access (0) - { - } - - // number of calls to the constructor - std::atomic calls; - - // incremented after construction completes - std::atomic constructed; - - // increment when class is accessed before construction - std::atomic access; - }; - - /* This testing singleton detects two conditions: - 1. Being accessed before getting fully constructed - 2. Getting constructed twice - */ - template - class Test; - - template - static - void - run_many (std::size_t n, Function f); - - template - void - test (cxx11_tag); - - template - void - test (beast_tag); - - template - void - test(); - - void - run (); -}; - -//------------------------------------------------------------------------------ - -template -class static_initializer_test::Test -{ -public: - explicit - Test (Counts& counts); - - void - operator() (Counts& counts); -}; - -template -static_initializer_test::Test::Test (Counts& counts) -{ - ++counts.calls; - std::this_thread::sleep_for (std::chrono::milliseconds (10)); - ++counts.constructed; -} - -template -void -static_initializer_test::Test::operator() (Counts& counts) -{ - if (! counts.constructed) - ++counts.access; -} - -//------------------------------------------------------------------------------ - -template -void -static_initializer_test::run_many (std::size_t n, Function f) -{ - std::atomic start (false); - std::vector threads; - - threads.reserve (n); - - for (auto i (n); i-- ;) - { - threads.emplace_back([&]() - { - while (! start.load()) - std::this_thread::yield(); - f(); - }); - } - std::this_thread::sleep_for (std::chrono::milliseconds (10)); - std::this_thread::yield(); - start.store (true); - for (auto& thread : threads) - thread.join(); -} - -template -void -static_initializer_test::test (cxx11_tag) -{ - testcase << "cxx11 " << Tag::count << " threads"; - - Counts counts; - - run_many (Tag::count, [&]() - { - static Test t (counts); - t(counts); - }); - -#if defined(_MSC_VER) && _MSC_VER < 1900 - // Visual Studio 2013 and earlier can exhibit both double - // construction, and access before construction when function - // local statics are initialized concurrently. - // - expect (counts.constructed > 1 || counts.access > 0); - -#else - expect (counts.constructed == 1 && counts.access == 0); - -#endif -} - -template -void -static_initializer_test::test (beast_tag) -{ - testcase << "beast " << Tag::count << " threads"; - - Counts counts; - - run_many (Tag::count, [&counts]() - { - static static_initializer > t (counts); - (*t)(counts); - }); - - expect (counts.constructed == 1 && counts.access == 0); -} - -template -void -static_initializer_test::test() -{ - test (typename Tag::type {}); -} - -void -static_initializer_test::run () -{ - test > (); - test > (); -} - -//------------------------------------------------------------------------------ - -BEAST_DEFINE_TESTSUITE(static_initializer,utility,beast); - -}