mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-19 04:22:08 +00:00
- Refactored TLS implementation, including Win32 support across DLL bondaries
- on_error now allocates dynamic storage (if enabled) before the stack unwind
This commit is contained in:
@@ -31,30 +31,32 @@ namespace tls
|
||||
// This function may not fail.
|
||||
unsigned read_current_error_id() noexcept;
|
||||
|
||||
// Write p to the TLS for T. The TLS may be allocated dynamically on the
|
||||
// first call to write_ptr_alloc<T>, but subsequent calls must reuse the
|
||||
// same TLS.
|
||||
// Reserve TLS storage for T. The TLS may be allocated dynamically on the
|
||||
// first call to reserve_ptr<T>, but subsequent calls must reuse the same
|
||||
// TLS. On platforms where allocation is not needed, this function is
|
||||
// still defined but does nothing.
|
||||
//
|
||||
// This function may throw on allocation failure.
|
||||
template <class T>
|
||||
void write_ptr_alloc( T * p );
|
||||
void reserve_ptr();
|
||||
|
||||
// Write p to the TLS previously allocated for T by a successful call to
|
||||
// write_ptr_alloc<T>.
|
||||
// Write p to the TLS previously reserved for T by a call to reserve_ptr<T>.
|
||||
// It is illegal to call write_ptr<T> without a prior successful call to
|
||||
// reserve_ptr<T>.
|
||||
//
|
||||
// This function may not fail.
|
||||
template <class T>
|
||||
void write_ptr( T * p ) noexcept;
|
||||
|
||||
// Read the T * value previously written in the TLS for T. Returns nullptr
|
||||
// if TLS for T has not yet been allocated.
|
||||
// if TLS for T has not yet been reserved.
|
||||
//
|
||||
// This function may not fail.
|
||||
template <class T>
|
||||
T * read_ptr() noexcept;
|
||||
}
|
||||
} // namespace tls
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#if defined(BOOST_LEAF_TLS_FREERTOS)
|
||||
# include <boost/leaf/config/tls_freertos.hpp>
|
||||
|
||||
@@ -100,16 +100,16 @@ namespace detail
|
||||
BOOST_LEAF_CFG_TLS_INDEX_TYPE tls_index<T>::idx = BOOST_LEAF_CFG_TLS_ARRAY_START_INDEX + 1;
|
||||
|
||||
template <class T>
|
||||
struct BOOST_LEAF_SYMBOL_VISIBLE alloc_tls_index
|
||||
struct BOOST_LEAF_SYMBOL_VISIBLE reserve_tls_index
|
||||
{
|
||||
static BOOST_LEAF_CFG_TLS_INDEX_TYPE const idx;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_CFG_TLS_INDEX_TYPE const alloc_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next<T>();
|
||||
}
|
||||
BOOST_LEAF_CFG_TLS_INDEX_TYPE const reserve_tls_index<T>::idx = tls_index<T>::idx = index_counter<>::next<T>();
|
||||
} // namespace detail
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -137,12 +137,9 @@ namespace tls
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr_alloc( T * p )
|
||||
BOOST_LEAF_ALWAYS_INLINE void reserve_ptr()
|
||||
{
|
||||
int tls_idx = detail::alloc_tls_index<T>::idx;
|
||||
--tls_idx;
|
||||
write_void_ptr(tls_idx, p);
|
||||
BOOST_LEAF_ASSERT(read_void_ptr(tls_idx) == p);
|
||||
(void) detail::reserve_tls_index<T>::idx;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -165,6 +162,8 @@ namespace tls
|
||||
--tls_idx;
|
||||
return reinterpret_cast<T *>(read_void_ptr(tls_idx));
|
||||
}
|
||||
}
|
||||
} // namespace tls
|
||||
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // #ifndef BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
|
||||
|
||||
@@ -38,15 +38,17 @@ namespace detail
|
||||
template <class T>
|
||||
thread_local T * ptr<T>::p;
|
||||
|
||||
struct current_error_id_storage
|
||||
template <class=void>
|
||||
struct BOOST_LEAF_SYMBOL_VISIBLE current_error_id_storage
|
||||
{
|
||||
static thread_local unsigned x;
|
||||
};
|
||||
|
||||
thread_local unsigned current_error_id_storage::x;
|
||||
}
|
||||
template <class T>
|
||||
thread_local unsigned current_error_id_storage<T>::x;
|
||||
} // namespace detail
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -63,30 +65,7 @@ namespace tls
|
||||
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_current_error_id( unsigned x ) noexcept
|
||||
{
|
||||
detail::current_error_id_storage::x = x;
|
||||
}
|
||||
|
||||
BOOST_LEAF_ALWAYS_INLINE unsigned read_current_error_id() noexcept
|
||||
{
|
||||
return detail::current_error_id_storage::x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr_alloc( T * p )
|
||||
{
|
||||
detail::ptr<T>::p = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr( T * p ) noexcept
|
||||
{
|
||||
detail::ptr<T>::p = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE T * read_ptr() noexcept
|
||||
{
|
||||
return detail::ptr<T>::p;
|
||||
detail::current_error_id_storage<>::x = x;
|
||||
}
|
||||
|
||||
BOOST_LEAF_ALWAYS_INLINE unsigned read_current_error_id() noexcept
|
||||
|
||||
@@ -42,9 +42,9 @@ namespace detail
|
||||
|
||||
template <class T>
|
||||
unsigned current_error_id_storage<T>::x = 0;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -69,29 +69,6 @@ namespace tls
|
||||
return detail::current_error_id_storage<>::x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr_alloc( T * p )
|
||||
{
|
||||
detail::ptr<T>::p = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr( T * p ) noexcept
|
||||
{
|
||||
detail::ptr<T>::p = p;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE T * read_ptr() noexcept
|
||||
{
|
||||
return detail::ptr<T>::p;
|
||||
}
|
||||
|
||||
BOOST_LEAF_ALWAYS_INLINE unsigned read_current_error_id() noexcept
|
||||
{
|
||||
return detail::current_error_id_storage<>::x;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void reserve_ptr()
|
||||
{
|
||||
|
||||
@@ -211,7 +211,7 @@ namespace detail
|
||||
{
|
||||
return error_id_storage_;
|
||||
}
|
||||
};
|
||||
}; // class slot_map
|
||||
|
||||
class module_state
|
||||
{
|
||||
@@ -300,6 +300,7 @@ namespace detail
|
||||
}
|
||||
else if (dwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(sm_ || tls_failures_);
|
||||
if (sm_)
|
||||
{
|
||||
sm_->release();
|
||||
@@ -307,7 +308,7 @@ namespace detail
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}; // class module_state
|
||||
|
||||
template<int = 0>
|
||||
struct module
|
||||
@@ -334,7 +335,7 @@ namespace detail
|
||||
#ifdef _MSC_VER
|
||||
#pragma section(".CRT$XLB", long, read)
|
||||
#pragma data_seg(push, ".CRT$XLB")
|
||||
extern "C" PIMAGE_TLS_CALLBACK boost_leaf_tls_callback = tls_callback;
|
||||
extern "C" __declspec(selectany) PIMAGE_TLS_CALLBACK boost_leaf_tls_callback = tls_callback;
|
||||
#pragma data_seg(pop)
|
||||
#ifdef _WIN64
|
||||
#pragma comment(linker, "/INCLUDE:boost_leaf_tls_callback")
|
||||
@@ -342,11 +343,11 @@ namespace detail
|
||||
#pragma comment(linker, "/INCLUDE:_boost_leaf_tls_callback")
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
extern "C" __attribute__((used)) PIMAGE_TLS_CALLBACK boost_leaf_tls_callback __attribute__((section(".CRT$XLB"))) = tls_callback;
|
||||
extern "C" __attribute__((used, weak)) PIMAGE_TLS_CALLBACK boost_leaf_tls_callback __attribute__((section(".CRT$XLB"))) = tls_callback;
|
||||
#endif
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -377,14 +378,11 @@ namespace tls
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_LEAF_ALWAYS_INLINE void write_ptr_alloc(T * p)
|
||||
BOOST_LEAF_ALWAYS_INLINE void reserve_ptr()
|
||||
{
|
||||
using namespace detail;
|
||||
thread_local DWORD const cached_slot = module<>::state.sm().get(type_hash<T>());
|
||||
DWORD slot = cached_slot;
|
||||
BOOST_LEAF_ASSERT(slot != TLS_OUT_OF_INDEXES);
|
||||
BOOL r = TlsSetValue(slot, p);
|
||||
BOOST_LEAF_ASSERT(r), (void) r;
|
||||
BOOST_LEAF_ASSERT(cached_slot != TLS_OUT_OF_INDEXES), (void) cached_slot;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -412,8 +410,8 @@ namespace tls
|
||||
BOOST_LEAF_ASSERT(GetLastError() == ERROR_SUCCESS);
|
||||
return static_cast<T *>(value);
|
||||
}
|
||||
}
|
||||
} // namespace tls
|
||||
|
||||
} }
|
||||
} } // namespace boost::leaf
|
||||
|
||||
#endif // BOOST_LEAF_CONFIG_TLS_WIN32_HPP_INCLUDED
|
||||
#endif // #ifndef BOOST_LEAF_CONFIG_TLS_WIN32_HPP_INCLUDED
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace detail
|
||||
template <int I, class Tup>
|
||||
struct tuple_for_each
|
||||
{
|
||||
BOOST_LEAF_CONSTEXPR static void activate( Tup & tup )
|
||||
BOOST_LEAF_CONSTEXPR static void activate( Tup & tup ) noexcept
|
||||
{
|
||||
static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
|
||||
tuple_for_each<I-1,Tup>::activate(tup);
|
||||
@@ -286,7 +286,7 @@ class context
|
||||
raii_deactivator & operator=( raii_deactivator const & ) = delete;
|
||||
context * ctx_;
|
||||
public:
|
||||
explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE raii_deactivator(context & ctx):
|
||||
explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE raii_deactivator(context & ctx) noexcept:
|
||||
ctx_(ctx.is_active() ? nullptr : &ctx)
|
||||
{
|
||||
if( ctx_ )
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
return tup_;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR void activate()
|
||||
BOOST_LEAF_CONSTEXPR void activate() noexcept
|
||||
{
|
||||
using namespace detail;
|
||||
BOOST_LEAF_ASSERT(!is_active());
|
||||
@@ -396,7 +396,7 @@ public:
|
||||
template <class R, class... H>
|
||||
BOOST_LEAF_CONSTEXPR R handle_error( error_id, H && ... );
|
||||
|
||||
friend BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE raii_deactivator activate_context(context & ctx)
|
||||
friend BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE raii_deactivator activate_context(context & ctx) noexcept
|
||||
{
|
||||
return raii_deactivator(ctx);
|
||||
}
|
||||
|
||||
@@ -140,10 +140,10 @@ namespace detail
|
||||
BOOST_LEAF_ASSERT(tls::read_ptr<slot<E>>() != this);
|
||||
}
|
||||
|
||||
void activate()
|
||||
void activate() noexcept
|
||||
{
|
||||
prev_ = tls::read_ptr<slot<E>>();
|
||||
tls::write_ptr_alloc<slot<E>>(this);
|
||||
tls::write_ptr<slot<E>>(this);
|
||||
}
|
||||
|
||||
void deactivate() const noexcept
|
||||
@@ -179,18 +179,12 @@ namespace detail
|
||||
{
|
||||
class preloaded_base;
|
||||
|
||||
template <class E>
|
||||
struct capturing_slot_node_allocator;
|
||||
|
||||
class dynamic_allocator:
|
||||
capture_list
|
||||
{
|
||||
dynamic_allocator( dynamic_allocator const & ) = delete;
|
||||
dynamic_allocator & operator=( dynamic_allocator const & ) = delete;
|
||||
|
||||
template <class>
|
||||
friend struct capturing_slot_node_allocator;
|
||||
|
||||
preloaded_base * preloaded_list_;
|
||||
|
||||
class capturing_node:
|
||||
@@ -325,7 +319,7 @@ namespace detail
|
||||
BOOST_LEAF_ASSERT(last_ != nullptr);
|
||||
BOOST_LEAF_ASSERT(*last_ == nullptr);
|
||||
BOOST_LEAF_ASSERT(tls::read_ptr<slot<E>>() == nullptr);
|
||||
capturing_slot_node<E> * csn = capturing_slot_node_allocator<E>::new_(last_);
|
||||
capturing_slot_node<E> * csn = new capturing_slot_node<E>(last_);
|
||||
csn->activate();
|
||||
return csn;
|
||||
}
|
||||
@@ -365,21 +359,6 @@ namespace detail
|
||||
using capture_list::print;
|
||||
}; // class dynamic_allocator
|
||||
|
||||
template <class E>
|
||||
struct capturing_slot_node_allocator
|
||||
{
|
||||
template <class... A>
|
||||
static dynamic_allocator::capturing_slot_node<E> * new_( A && ... a )
|
||||
{
|
||||
return new dynamic_allocator::capturing_slot_node<E>(std::forward<A>(a)...);
|
||||
}
|
||||
|
||||
static void delete_( dynamic_allocator::capturing_slot_node<E> * p ) noexcept
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
class slot<dynamic_allocator>
|
||||
{
|
||||
@@ -389,64 +368,30 @@ namespace detail
|
||||
dynamic_allocator da_;
|
||||
slot * prev_;
|
||||
|
||||
template <class E>
|
||||
inline void dynamic_load_( int err_id, E && e )
|
||||
{
|
||||
if( slot<dynamic_allocator> * sl = tls::read_ptr<slot<dynamic_allocator>>() )
|
||||
if( dynamic_allocator * c = sl->has_value_any_key() )
|
||||
c->dynamic_load(err_id, std::forward<E>(e));
|
||||
else
|
||||
sl->load(err_id).dynamic_load(err_id, std::forward<E>(e));
|
||||
}
|
||||
public:
|
||||
|
||||
template <class E, class F>
|
||||
inline void dynamic_accumulate_( int err_id, F && f )
|
||||
{
|
||||
if( slot<dynamic_allocator> * sl = tls::read_ptr<slot<dynamic_allocator>>() )
|
||||
if( dynamic_allocator * c = sl->has_value(err_id) )
|
||||
(void) std::forward<F>(f)(c->dynamic_load(err_id, E{}));
|
||||
else
|
||||
(void) std::forward<F>(f)(sl->load(err_id).dynamic_load(err_id, E{}));
|
||||
}
|
||||
|
||||
template <bool OnError, class E>
|
||||
inline void dynamic_load( int err_id, E && e ) noexcept(OnError)
|
||||
{
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( OnError )
|
||||
slot() noexcept:
|
||||
prev_(nullptr)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic_load_(err_id, std::forward<E>(e));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
tls::reserve_ptr<slot<dynamic_allocator>>();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
dynamic_load_(err_id, std::forward<E>(e));
|
||||
}
|
||||
|
||||
template <bool OnError, class E, class F>
|
||||
inline void dynamic_load_accumulate( int err_id, F && f ) noexcept(OnError)
|
||||
{
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( OnError )
|
||||
slot( slot && x ) noexcept:
|
||||
da_(std::move(x.da_)),
|
||||
prev_(nullptr)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic_accumulate_<E>(err_id, std::forward<F>(f));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
BOOST_LEAF_ASSERT(x.prev_ == nullptr);
|
||||
}
|
||||
|
||||
~slot() noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT(tls::read_ptr<slot<dynamic_allocator>>() != this);
|
||||
}
|
||||
|
||||
dynamic_allocator const & get() const noexcept
|
||||
{
|
||||
return da_;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
dynamic_accumulate_<E>(err_id, std::forward<F>(f));
|
||||
}
|
||||
}
|
||||
|
||||
dynamic_allocator & get() noexcept
|
||||
{
|
||||
@@ -599,6 +544,38 @@ namespace detail
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if BOOST_LEAF_CFG_CAPTURE
|
||||
class preloaded_base
|
||||
{
|
||||
protected:
|
||||
|
||||
preloaded_base() noexcept:
|
||||
next_(
|
||||
[]( preloaded_base * this_ ) -> preloaded_base *
|
||||
{
|
||||
if( dynamic_allocator * da = get_dynamic_allocator() )
|
||||
return da->link_preloaded_item(this_);
|
||||
return nullptr;
|
||||
}(this))
|
||||
{
|
||||
}
|
||||
|
||||
~preloaded_base() noexcept
|
||||
{
|
||||
if( dynamic_allocator * da = get_dynamic_allocator() )
|
||||
da->unlink_preloaded_item(next_);
|
||||
else
|
||||
BOOST_LEAF_ASSERT(next_ == nullptr);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
preloaded_base * const next_;
|
||||
|
||||
virtual void reserve( dynamic_allocator & ) const = 0;
|
||||
};
|
||||
#endif // #if BOOST_LEAF_CFG_CAPTURE
|
||||
|
||||
inline int current_id() noexcept
|
||||
{
|
||||
unsigned id = tls::read_current_error_id();
|
||||
|
||||
@@ -261,6 +261,13 @@ namespace detail
|
||||
bool moved_ = false;
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_CAPTURE
|
||||
void reserve( dynamic_allocator & da ) const override
|
||||
{
|
||||
tuple_for_each_preload<sizeof...(Item),decltype(p_)>::reserve(p_,da);
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ):
|
||||
|
||||
@@ -238,6 +238,13 @@ if option_enable_unit_tests
|
||||
so_dll_test_lib2 = shared_library('so_dll_test_lib2', 'test/so_dll_lib2.cpp', dependencies: [leaf, dep_so_dll], gnu_symbol_visibility: 'hidden')
|
||||
test('so_dll_test', executable('so_dll_test', 'test/so_dll_test.cpp', dependencies: [leaf, dep_so_dll], link_with: [so_dll_test_lib1, so_dll_test_lib2]))
|
||||
|
||||
# Test that the DLL test works when linked statically as well.
|
||||
# This is to verify that we don't get multiply defined symbol link errors when tls_win32.hpp is included in multiple compilation units..
|
||||
dep_so_dll_static = declare_dependency(compile_args: ['-DBOOST_LEAF_SO_DLL_TEST_STATIC'])
|
||||
so_dll_static_lib1 = static_library('so_dll_static_lib1', 'test/so_dll_lib1.cpp', dependencies: [leaf, dep_so_dll, dep_so_dll_static])
|
||||
so_dll_static_lib2 = static_library('so_dll_static_lib2', 'test/so_dll_lib2.cpp', dependencies: [leaf, dep_so_dll, dep_so_dll_static])
|
||||
test('so_dll_static_test', executable('so_dll_static_test', 'test/so_dll_test.cpp', dependencies: [leaf, dep_so_dll, dep_so_dll_static], link_with: [so_dll_static_lib1, so_dll_static_lib2]))
|
||||
|
||||
endif
|
||||
|
||||
#################################
|
||||
|
||||
@@ -137,6 +137,10 @@ lib so_dll_lib1 : so_dll_lib1.cpp : <link>shared <visibility>hidden <target-os>w
|
||||
lib so_dll_lib2 : so_dll_lib2.cpp : <link>shared <visibility>hidden <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 : : <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 ;
|
||||
run so_dll_test.cpp so_dll_lib1 so_dll_lib2 : : : <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 ;
|
||||
|
||||
lib so_dll_static_lib1 : so_dll_lib1.cpp : <link>static <define>BOOST_LEAF_SO_DLL_TEST_STATIC <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 ;
|
||||
lib so_dll_static_lib2 : so_dll_lib2.cpp : <link>static <define>BOOST_LEAF_SO_DLL_TEST_STATIC <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 ;
|
||||
run so_dll_test.cpp so_dll_static_lib1 so_dll_static_lib2 : : : <define>BOOST_LEAF_SO_DLL_TEST_STATIC <target-os>windows:<define>BOOST_LEAF_CFG_WIN32=2 : so_dll_static_test ;
|
||||
|
||||
compile-fail _compile-fail-arg_boost_error_info_1.cpp ;
|
||||
compile-fail _compile-fail-arg_boost_error_info_2.cpp ;
|
||||
compile-fail _compile-fail-arg_catch_1.cpp ;
|
||||
|
||||
@@ -8,19 +8,17 @@
|
||||
#include "so_dll_test.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef BOOST_LEAF_SO_DLL_TEST_BUILDING_LIB1
|
||||
# ifdef BOOST_LEAF_SO_DLL_TEST_STATIC
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB1_API
|
||||
# elif defined(BOOST_LEAF_SO_DLL_TEST_BUILDING_LIB1)
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB1_API __declspec(dllexport)
|
||||
# else
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB1_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB1_API BOOST_LEAF_SYMBOL_VISIBLE
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB1_API [[gnu::visibility("default")]]
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
template <class T> class result;
|
||||
} }
|
||||
|
||||
BOOST_LEAF_SO_DLL_TEST_LIB1_API boost::leaf::result<void> hidden_result1();
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
@@ -8,19 +8,17 @@
|
||||
#include "so_dll_test.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef BOOST_LEAF_SO_DLL_TEST_BUILDING_LIB2
|
||||
# ifdef BOOST_LEAF_SO_DLL_TEST_STATIC
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB2_API
|
||||
# elif defined(BOOST_LEAF_SO_DLL_TEST_BUILDING_LIB2)
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB2_API __declspec(dllexport)
|
||||
# else
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB2_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB2_API BOOST_LEAF_SYMBOL_VISIBLE
|
||||
# define BOOST_LEAF_SO_DLL_TEST_LIB2_API [[gnu::visibility("default")]]
|
||||
#endif
|
||||
|
||||
namespace boost { namespace leaf {
|
||||
template <class T> class result;
|
||||
} }
|
||||
|
||||
BOOST_LEAF_SO_DLL_TEST_LIB2_API boost::leaf::result<void> hidden_result2();
|
||||
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
@@ -126,7 +126,7 @@ int test_catch(void (*f)())
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // #ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
|
||||
void test_single_thread()
|
||||
{
|
||||
@@ -138,7 +138,7 @@ void test_single_thread()
|
||||
BOOST_TEST_EQ(test_catch(hidden_throw1), 0);
|
||||
BOOST_TEST_EQ(test_exception(hidden_throw2, true), 0);
|
||||
BOOST_TEST_EQ(test_catch(hidden_throw2), 0);
|
||||
#endif
|
||||
#endif // #ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
void test_multithreaded()
|
||||
@@ -212,7 +212,7 @@ void test_multithreaded()
|
||||
for (auto & f : futures)
|
||||
BOOST_TEST_EQ(f.get(), 0);
|
||||
}
|
||||
#endif
|
||||
#endif // #ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// Note, under BOOST_LEAF_CFG_WIN32==2 (using Win32 TLS) we do not need
|
||||
// import/export for error types. We still need default visibility on POSIX.
|
||||
template <int Tag>
|
||||
struct BOOST_LEAF_SYMBOL_VISIBLE my_info
|
||||
struct [[gnu::visibility("default")]] my_info
|
||||
{
|
||||
int value;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user