2
0
mirror of https://github.com/boostorg/leaf.git synced 2026-01-19 04:22:08 +00:00

Support FreeRTOS ond for other TLS array APIs

This commit is contained in:
Emil Dotchevski
2022-01-05 17:30:30 -08:00
parent 996edca175
commit 394d6d7762
64 changed files with 906 additions and 305 deletions

1
.gitignore vendored
View File

@@ -16,3 +16,4 @@ subprojects/*/
.vscode/c_cpp_properties.json
benchmark/tl/*
test/leaf.hpp
doc/leaf.html

6
.vscode/tasks.json vendored
View File

@@ -44,7 +44,7 @@
"dependsOn": [
"Generate leaf.hpp"
],
"command": "cd ${workspaceRoot}/bld/debug && meson test && cd ${workspaceRoot}/bld/debug_leaf_hpp && meson test",
"command": "cd ${workspaceRoot}/bld/debug && ninja && meson test && cd ${workspaceRoot}/bld/debug_leaf_hpp && ninja && meson test",
"problemMatcher": {
"base": "$gcc",
"fileLocation": [
@@ -60,7 +60,7 @@
"dependsOn": [
"Generate leaf.hpp"
],
"command": "cd ${workspaceRoot}/bld/release && meson test && cd ${workspaceRoot}/bld/release_leaf_hpp && meson test",
"command": "cd ${workspaceRoot}/bld/release && ninja && meson test && cd ${workspaceRoot}/bld/release_leaf_hpp && ninja && meson test",
"problemMatcher": {
"base": "$gcc",
"fileLocation": [
@@ -95,7 +95,7 @@
},
"label": "Test current editor file",
"type": "shell",
"command": "cd ${workspaceRoot}/bld/debug && { meson test ${fileBasenameNoExtension} || cat ./meson-logs/testlog.txt }",
"command": "cd ${workspaceRoot}/bld/debug && { ninja && meson test ${fileBasenameNoExtension} || cat ./meson-logs/testlog.txt }",
"problemMatcher": {
"base": "$gcc",
"fileLocation": [

View File

@@ -62,7 +62,7 @@ LEAF is designed with a strong bias towards the common use case where callers of
LEAF requires only {CPP}11, but is tested on many compiler versions and C++ standards.
The library uses thread-local storage, except when multi-threading is disabled (e.g. on some embedded platforms). See <<configuration>>.
The library uses thread-local storage for pointers only. By default, this is implemented via the {CPP}11 `thread_local` storage class specifier, however it is easy to use a platform-specific TLS API instead; for example LEAF ships with built-in support for FreeRTOS. See <<configuration>>.
[[distribution]]
== Distribution
@@ -5928,29 +5928,67 @@ Assuming the current working directory is `<boostroot>/libs/leaf`:
----
[[configuration]]
== Configuration Macros
== Configuration
The following configuration macros are recognized:
* `BOOST_LEAF_DIAGNOSTICS`: Defining this macro to `0` stubs out both <<diagnostic_info>> and <<verbose_diagnostic_info>>, which could improve the performance of the error path in some programs (if the macro is left undefined, LEAF defines it as `1`).
* `BOOST_LEAF_NO_EXCEPTIONS`: Disables all exception handling support. If left undefined, LEAF defines it based on the compiler configuration (e.g. `-fno-exceptions`).
* `BOOST_LEAF_NO_THREADS`: Disables all multi-thread support.
* `BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR`: Disables the `std::error_code` / `std::error_condition` integration. In this case LEAF does not `#include <system_error>`, which is considered too heavy for embedded platforms.
* `BOOST_LEAF_DISABLE_STD_STRING`: Disables all use of `std::string` (available only under `BOOST_LEAF_DIAGNOSTICS=0`). In this case LEAF does not `#include <string>` which is considered too heavy for embedded platforms.
* `BOOST_LEAF_DIAGNOSTICS`: Defining this macro as `0` stubs out both <<diagnostic_info>> and <<verbose_diagnostic_info>> (if the macro is left undefined, LEAF defines it as `1`).
* `BOOST_LEAF_USE_STD_SYSTEM_ERROR`: Defining this macro as `0` disables the `std::error_code` / `std::error_condition` integration. In this case LEAF does not `#include <system_error>`, which may be too heavy for embedded platforms (if the macro is left undefined, LEAF defines it as `1`).
* `BOOST_LEAF_USE_STD_STRING`: Defining this macro as `0` disables all use of `std::string` (this requires `BOOST_LEAF_DIAGNOSTICS=0` as well). In this case LEAF does not `#include <string>` which may be too heavy for embedded platforms (if the macro is left undefined, LEAF defines it as `1`).
* `BOOST_LEAF_NO_EXCEPTIONS`: Disables all exception handling support. If left undefined, LEAF defines it automatically based on the compiler configuration (e.g. `-fno-exceptions`).
* `BOOST_LEAF_NO_THREADS`: Disables all thread safety in LEAF.
In addition, defining `BOOST_LEAF_EMBEDDED` is equivalent to the following:
=== Embedded Platforms
Defining `BOOST_LEAF_EMBEDDED` is equivalent to the following:
[source,c++]
----
#define BOOST_LEAF_NO_EXCEPTIONS
#define BOOST_LEAF_DIAGNOSTICS 0
#define BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#define BOOST_LEAF_DISABLE_STD_STRING
#ifndef BOOST_LEAF_NO_EXCEPTIONS
# define BOOST_LEAF_NO_EXCEPTIONS
#endif
#ifndef BOOST_LEAF_DIAGNOSTICS
# define BOOST_LEAF_DIAGNOSTICS 0
#endif
#ifndef BOOST_LEAF_USE_STD_SYSTEM_ERROR
# define BOOST_LEAF_USE_STD_SYSTEM_ERROR 0
#endif
#ifndef BOOST_LEAF_USE_STD_STRING
# define BOOST_LEAF_USE_STD_STRING 0
#endif
----
== Limitations
LEAF supports FreeRTOS out of the box, please define `BOOST_LEAF_TLS_FREERTOS` (in which case LEAF automatically defines `BOOST_LEAF_EMBEDDED` if it is not defined already).
LEAF requires {CPP}11, including `thread_local` support, except when compiled with `BOOST_LEAF_NO_THREADS` (which can be useful on some embedded platforms).
For other embedded platforms, please define `BOOST_LEAF_TLS_ARRAY` and make sure your project defines the following two functions to implement TLS pointer access:
[source,c++]
----
namespace boost { namespace leaf {
namespace tls
{
void * read_void_ptr( int tls_index ) noexcept;
void write_void_ptr( int tls_index, void * p ) noexcept;
}
} }
----
TIP: For efficiency, `read_void_ptr` and `write_void_ptr` should be defined `inline`.
Under `BOOST_LEAF_TLS_ARRAY` (which includes `BOOST_LEAF_TLS_FREERTOS`):
* Each error type is assigned a unique index in the TLS pointer array. By default, assigned TLS indices start from `0`; this can be changed by defining `BOOST_LEAF_TLS_ARRAY_START_INDEX`.
* If `BOOST_LEAF_TLS_ARRAY_SIZE` is defined, LEAF will use it to `BOOST_LEAF_ASSERT` that TLS indices are within bounds (which is of course deactivated under `NDEBUG`).
* Under `BOOST_LEAF_TLS_FREERTOS`, `BOOST_LEAF_TLS_ARRAY_SIZE` defaults to https://www.freertos.org/a00110.html#configNUM_THREAD_LOCAL_STORAGE_POINTERS[`configNUM_THREAD_LOCAL_STORAGE_POINTERS`].
If your program does not use concurrency at all, simply define `BOOST_LEAF_NO_THREADS`, which requires no TLS support at all (but is NOT thread-safe).
== Limitations
When using dynamic linking, it is required that error types are declared with `default` visibility, e.g.:

View File

@@ -110,7 +110,7 @@ namespace leaf_detail
{
BOOST_LEAF_ASSERT(ctx_->captured_id_);
auto active_context = activate_context(*ctx_);
id_factory<>::current_id = ctx_->captured_id_.value();
tls::write_uint32<tls_tag_id_factory_current_id>(ctx_->captured_id_.value());
std::rethrow_exception(ex_);
}

View File

@@ -18,7 +18,7 @@
#include <boost/leaf/detail/demangle.hpp>
#include <iosfwd>
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
# include <string>
#endif
#include <cerrno>
@@ -37,19 +37,19 @@ namespace boost { namespace leaf {
struct BOOST_LEAF_SYMBOL_VISIBLE e_api_function { char const * value; };
#ifdef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
struct BOOST_LEAF_SYMBOL_VISIBLE e_file_name
{
constexpr static char const * const value = "<unavailable>";
BOOST_LEAF_CONSTEXPR explicit e_file_name( char const * ) { }
std::string value;
};
#else
struct BOOST_LEAF_SYMBOL_VISIBLE e_file_name
{
std::string value;
constexpr static char const * const value = "<unavailable>";
BOOST_LEAF_CONSTEXPR explicit e_file_name( char const * ) { }
};
#endif

View File

@@ -24,14 +24,63 @@
////////////////////////////////////////
#ifdef BOOST_LEAF_EMBEDDED
# define BOOST_LEAF_NO_EXCEPTIONS
# define BOOST_LEAF_DIAGNOSTICS 0
# define BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
# define BOOST_LEAF_DISABLE_STD_STRING
#ifdef BOOST_LEAF_TLS_FREERTOS
# ifndef BOOST_LEAF_EMBEDDED
# define BOOST_LEAF_EMBEDDED
# endif
#endif
#if BOOST_LEAF_DIAGNOSTICS && defined(BOOST_LEAF_DISABLE_STD_STRING)
////////////////////////////////////////
#ifdef BOOST_LEAF_EMBEDDED
# ifndef BOOST_LEAF_NO_EXCEPTIONS
# define BOOST_LEAF_NO_EXCEPTIONS
# endif
# ifndef BOOST_LEAF_DIAGNOSTICS
# define BOOST_LEAF_DIAGNOSTICS 0
# endif
# ifndef BOOST_LEAF_USE_STD_SYSTEM_ERROR
# define BOOST_LEAF_USE_STD_SYSTEM_ERROR 0
# endif
# ifndef BOOST_LEAF_USE_STD_STRING
# define BOOST_LEAF_USE_STD_STRING 0
# endif
#endif
////////////////////////////////////////
#ifndef BOOST_LEAF_DIAGNOSTICS
# define BOOST_LEAF_DIAGNOSTICS 1
#endif
#ifndef BOOST_LEAF_USE_STD_SYSTEM_ERROR
# define BOOST_LEAF_USE_STD_SYSTEM_ERROR 1
#endif
#ifndef BOOST_LEAF_USE_STD_STRING
# define BOOST_LEAF_USE_STD_STRING 1
#endif
#if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1
# error BOOST_LEAF_DIAGNOSTICS must be 0 or 1.
#endif
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR!=0 && BOOST_LEAF_USE_STD_SYSTEM_ERROR!=1
# error BOOST_LEAF_USE_STD_SYSTEM_ERROR must be 0 or 1.
#endif
#if BOOST_LEAF_USE_STD_STRING!=0 && BOOST_LEAF_USE_STD_STRING!=1
# error BOOST_LEAF_USE_STD_STRING must be 0 or 1.
#endif
#if BOOST_LEAF_DIAGNOSTICS && !BOOST_LEAF_USE_STD_STRING
# error BOOST_LEAF_DIAGNOSTICS requires the use of std::string
#endif
@@ -139,16 +188,6 @@
////////////////////////////////////////
#ifndef BOOST_LEAF_DIAGNOSTICS
# define BOOST_LEAF_DIAGNOSTICS 1
#endif
#if BOOST_LEAF_DIAGNOSTICS!=0 && BOOST_LEAF_DIAGNOSTICS!=1
# error BOOST_LEAF_DIAGNOSTICS must be 0 or 1.
#endif
////////////////////////////////////////
#ifdef _MSC_VER
# define BOOST_LEAF_ALWAYS_INLINE __forceinline
#else
@@ -207,9 +246,8 @@
////////////////////////////////////////
#ifdef BOOST_LEAF_NO_THREADS
# define BOOST_LEAF_DISABLE_CAPTURE
#endif
// Configure TLS access
#include <boost/leaf/config/tls.hpp>
////////////////////////////////////////

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED
#define BOOST_LEAF_CONFIG_TLS_HPP_INCLUDED
/// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
/// Distributed under the Boost Software License, Version 1.0. (See accompanying
/// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if defined(BOOST_LEAF_TLS_FREERTOS)
# include <boost/leaf/config/tls_freertos.hpp>
#endif
#if defined BOOST_LEAF_TLS_ARRAY
# include <boost/leaf/config/tls_array.hpp>
#elif defined(BOOST_LEAF_NO_THREADS)
# include <boost/leaf/config/tls_globals.hpp>
#else
# include <boost/leaf/config/tls_cpp11.hpp>
#endif
#endif

View File

@@ -0,0 +1,163 @@
#ifndef BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
#define BOOST_LEAF_CONFIG_TLS_ARRAY_HPP_INCLUDED
/// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
/// Copyright (c) 2022 Khalil Estell
/// Distributed under the Boost Software License, Version 1.0. (See accompanying
/// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// LEAF requires thread local storage support for pointers and for uin32_t values.
// This header implements thread local storage for pointers and for uint32_t
// values for platforms that support thread local pointers by index.
#ifndef BOOST_LEAF_ENABLE_WARNINGS ///
# if defined(_MSC_VER) ///
# pragma warning(push,1) ///
# elif defined(__clang__) ///
# pragma clang system_header ///
# elif (__GNUC__*100+__GNUC_MINOR__>301) ///
# pragma GCC system_header ///
# endif ///
#endif ///
////////////////////////////////////////
#ifndef BOOST_LEAF_TLS_INDEX_TYPE
# define BOOST_LEAF_TLS_INDEX_TYPE int
#endif
#ifndef BOOST_LEAF_TLS_ARRAY_START_INDEX
# define BOOST_LEAF_TLS_ARRAY_START_INDEX 0
#endif
static_assert(BOOST_LEAF_TLS_ARRAY_START_INDEX >= 0,
"Bad BOOST_LEAF_TLS_ARRAY_START_INDEX");
#ifdef BOOST_LEAF_TLS_ARRAY_SIZE
static_assert(BOOST_LEAF_TLS_ARRAY_SIZE > 0,
"Bad BOOST_LEAF_TLS_ARRAY_SIZE");
static_assert(BOOST_LEAF_TLS_ARRAY_START_INDEX < BOOST_LEAF_TLS_ARRAY_SIZE,
"Bad BOOST_LEAF_TLS_ARRAY_START_INDEX");
#endif
#include <atomic>
#include <cstdint>
////////////////////////////////////////
namespace boost { namespace leaf {
namespace tls
{
// The TLS support defined in this header requires the following two
// functions to be defined elsewhere:
void * read_void_ptr( int tls_index ) noexcept;
void write_void_ptr( int tls_index, void * ) noexcept;
}
} }
////////////////////////////////////////
namespace boost { namespace leaf {
namespace leaf_detail
{
using atomic_unsigned_int = std::atomic<unsigned int>;
}
namespace tls
{
template <class=void>
class BOOST_LEAF_SYMBOL_VISIBLE index_counter
{
static BOOST_LEAF_TLS_INDEX_TYPE c;
public:
template <class T>
static BOOST_LEAF_TLS_INDEX_TYPE get_index() noexcept
{
BOOST_LEAF_TLS_INDEX_TYPE idx = c++;
#ifdef BOOST_LEAF_TLS_ARRAY_SIZE
BOOST_LEAF_ASSERT(idx < BOOST_LEAF_TLS_ARRAY_SIZE);
#endif
// Set breakpoint here to inspect TLS index assignment.
return idx;
}
};
template <class T>
BOOST_LEAF_TLS_INDEX_TYPE index_counter<T>::c = BOOST_LEAF_TLS_ARRAY_START_INDEX;
template <class T>
struct BOOST_LEAF_SYMBOL_VISIBLE index
{
static BOOST_LEAF_TLS_INDEX_TYPE const idx;
};
template <class T>
BOOST_LEAF_TLS_INDEX_TYPE const index<T>::idx = index_counter<>::get_index<T>();
////////////////////////////////////////
template <class T>
T * read_ptr() noexcept
{
int const tls_index = index<T>::idx;
BOOST_LEAF_ASSERT(tls_index >= BOOST_LEAF_TLS_ARRAY_START_INDEX);
#ifdef BOOST_LEAF_TLS_ARRAY_SIZE
BOOST_LEAF_ASSERT(tls_index < BOOST_LEAF_TLS_ARRAY_SIZE);
#endif
return reinterpret_cast<T *>(read_void_ptr(tls_index));
}
template <class T>
void write_ptr( T * p ) noexcept
{
int const tls_index = index<T>::idx;
BOOST_LEAF_ASSERT(tls_index >= BOOST_LEAF_TLS_ARRAY_START_INDEX);
#ifdef BOOST_LEAF_TLS_ARRAY_SIZE
BOOST_LEAF_ASSERT(tls_index < BOOST_LEAF_TLS_ARRAY_SIZE);
#endif
write_void_ptr(tls_index, p);
BOOST_LEAF_ASSERT(read_void_ptr(tls_index) == p);
}
////////////////////////////////////////
template <class Tag>
std::uint32_t read_uint32() noexcept
{
Tag * p = read_ptr<Tag>();
return (std::intptr_t)(void *)p;
}
template <class Tag>
void write_uint32( std::uint32_t x ) noexcept
{
write_ptr<Tag>((Tag *)x);
}
template <class Tag>
void uint32_increment() noexcept
{
write_uint32<Tag>(read_uint32<Tag>() + 1);
}
template <class Tag>
void uint32_decrement() noexcept
{
write_uint32<Tag>(read_uint32<Tag>() - 1);
}
}
} }
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
#pragma warning(pop) ///
#endif ///
#endif

View File

@@ -0,0 +1,99 @@
#ifndef BOOST_LEAF_CONFIG_TLS_CPP11_HPP_INCLUDED
#define BOOST_LEAF_CONFIG_TLS_CPP11_HPP_INCLUDED
/// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
/// Distributed under the Boost Software License, Version 1.0. (See accompanying
/// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// LEAF requires thread local storage support for pointers and for uin32_t values.
// This header implements thread local storage for pointers and for uint32_t
// values using the C++11 built-in thread_local storage class specifier.
#ifndef BOOST_LEAF_ENABLE_WARNINGS ///
# if defined(_MSC_VER) ///
# pragma warning(push,1) ///
# elif defined(__clang__) ///
# pragma clang system_header ///
# elif (__GNUC__*100+__GNUC_MINOR__>301) ///
# pragma GCC system_header ///
# endif ///
#endif ///
#include <cstdint>
#include <atomic>
namespace boost { namespace leaf {
namespace leaf_detail
{
using atomic_unsigned_int = std::atomic<unsigned int>;
}
namespace tls
{
template <class T>
struct BOOST_LEAF_SYMBOL_VISIBLE ptr
{
static thread_local T * p;
};
template <class T>
thread_local T * ptr<T>::p;
template <class T>
T * read_ptr() noexcept
{
return ptr<T>::p;
}
template <class T>
void write_ptr( T * p ) noexcept
{
ptr<T>::p = p;
}
////////////////////////////////////////
template <class Tag>
struct BOOST_LEAF_SYMBOL_VISIBLE tagged_uint32
{
static thread_local std::uint32_t x;
};
template <class Tag>
thread_local std::uint32_t tagged_uint32<Tag>::x;
template <class Tag>
std::uint32_t read_uint32() noexcept
{
return tagged_uint32<Tag>::x;
}
template <class Tag>
void write_uint32( std::uint32_t x ) noexcept
{
tagged_uint32<Tag>::x = x;
}
template <class Tag>
void uint32_increment() noexcept
{
++tagged_uint32<Tag>::x;
}
template <class Tag>
void uint32_decrement() noexcept
{
--tagged_uint32<Tag>::x;
}
}
} }
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
#pragma warning(pop) ///
#endif ///
#endif

View File

@@ -0,0 +1,67 @@
#ifndef BOOST_LEAF_CONFIG_TLS_FREERTOS_HPP_INCLUDED
#define BOOST_LEAF_CONFIG_TLS_FREERTOS_HPP_INCLUDED
/// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
/// Copyright (c) 2022 Khalil Estell
/// Distributed under the Boost Software License, Version 1.0. (See accompanying
/// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// LEAF requires thread local storage support for pointers and for uin32_t values.
// This header implements thread local storage for pointers and for uint32_t
// values via the FreeRTOS API, as an alternative to the default implementation
// (found in tls_cpp11.hpp) which relies on C++11 thread_local support.
// See https://www.freertos.org/thread-local-storage-pointers.html.
#ifndef BOOST_LEAF_ENABLE_WARNINGS ///
# if defined(_MSC_VER) ///
# pragma warning(push,1) ///
# elif defined(__clang__) ///
# pragma clang system_header ///
# elif (__GNUC__*100+__GNUC_MINOR__>301) ///
# pragma GCC system_header ///
# endif ///
#endif ///
#include <task.h>
#ifndef BOOST_LEAF_TLS_ARRAY
# define BOOST_LEAF_TLS_ARRAY
#endif
#ifndef BOOST_LEAF_TLS_INDEX_TYPE
# define BOOST_LEAF_TLS_INDEX_TYPE BaseType_t
#endif
#ifndef BOOST_LEAF_TLS_ARRAY_SIZE
# define BOOST_LEAF_TLS_ARRAY_SIZE configNUM_THREAD_LOCAL_STORAGE_POINTERS
#endif
static_assert(
BOOST_LEAF_TLS_ARRAY_SIZE <= configNUM_THREAD_LOCAL_STORAGE_POINTERS,
"Bad BOOST_LEAF_TLS_ARRAY_SIZE");
namespace boost { namespace leaf {
namespace tls
{
inline void * read_void_ptr( int tls_index ) noexcept
{
return pvTaskGetThreadLocalStoragePointer(0, tls_index);
}
inline void write_void_ptr( int tls_index, void * p ) noexcept
{
vTaskSetThreadLocalStoragePointer(0, tls_index, p);
}
}
} }
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
#pragma warning(pop) ///
#endif ///
#endif

View File

@@ -0,0 +1,98 @@
#ifndef BOOST_LEAF_CONFIG_TLS_GLOBALS_HPP_INCLUDED
#define BOOST_LEAF_CONFIG_TLS_GLOBALS_HPP_INCLUDED
/// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
/// Distributed under the Boost Software License, Version 1.0. (See accompanying
/// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// LEAF requires thread local storage support for pointers and for uin32_t values.
// This header implements "thread local" storage for pointers and for uint32_t
// values using globals, which is suitable for single thread environments.
#ifndef BOOST_LEAF_ENABLE_WARNINGS ///
# if defined(_MSC_VER) ///
# pragma warning(push,1) ///
# elif defined(__clang__) ///
# pragma clang system_header ///
# elif (__GNUC__*100+__GNUC_MINOR__>301) ///
# pragma GCC system_header ///
# endif ///
#endif ///
#include <cstdint>
namespace boost { namespace leaf {
namespace leaf_detail
{
using atomic_unsigned_int = unsigned int;
}
namespace tls
{
template <class T>
struct BOOST_LEAF_SYMBOL_VISIBLE ptr
{
static T * p;
};
template <class T>
T * ptr<T>::p;
template <class T>
T * read_ptr() noexcept
{
return ptr<T>::p;
}
template <class T>
void write_ptr( T * p ) noexcept
{
ptr<T>::p = p;
}
////////////////////////////////////////
template <class Tag>
struct BOOST_LEAF_SYMBOL_VISIBLE tagged_uint32
{
static std::uint32_t x;
};
template <class Tag>
std::uint32_t tagged_uint32<Tag>::x;
template <class Tag>
std::uint32_t read_uint32() noexcept
{
return tagged_uint32<Tag>::x;
}
template <class Tag>
void write_uint32( std::uint32_t x ) noexcept
{
tagged_uint32<Tag>::x = x;
}
template <class Tag>
void uint32_increment() noexcept
{
++tagged_uint32<Tag>::x;
}
template <class Tag>
void uint32_decrement() noexcept
{
--tagged_uint32<Tag>::x;
}
}
} }
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
#pragma warning(pop) ///
#endif ///
#endif

View File

@@ -17,6 +17,9 @@
#endif ///
#include <boost/leaf/error.hpp>
#if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
# include <thread>
#endif
namespace boost { namespace leaf {
@@ -333,7 +336,7 @@ public:
tuple_for_each<std::tuple_size<Tup>::value,Tup>::activate(tup_);
#if BOOST_LEAF_DIAGNOSTICS
if( unexpected_requested<Tup>::value )
++tl_unexpected_enabled<>::counter;
tls::uint32_increment<tls_tag_unexpected_enabled_counter>();
#endif
#if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
thread_id_ = std::this_thread::get_id();
@@ -352,7 +355,7 @@ public:
#endif
#if BOOST_LEAF_DIAGNOSTICS
if( unexpected_requested<Tup>::value )
--tl_unexpected_enabled<>::counter;
tls::uint32_decrement<tls_tag_unexpected_enabled_counter>();
#endif
tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_);
}

View File

@@ -25,7 +25,7 @@
# endif ///
#endif ///
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#include <cstring>
namespace boost { namespace leaf {
@@ -70,21 +70,6 @@ char const * t =
////////////////////////////////////////
#ifdef BOOST_LEAF_DISABLE_STD_STRING
namespace boost { namespace leaf {
inline char const * demangle( char const * name )
{
return name;
}
} }
#else
#include <string>
#if defined(__has_include) && ((__GNUC__ + 0) >= 5)
# if __has_include(<cxxabi.h>)
# define BOOST_LEAF_HAS_CXXABI_H
@@ -105,6 +90,10 @@ namespace boost { namespace leaf {
# endif
#endif
#if BOOST_LEAF_USE_STD_STRING
#include <string>
namespace boost { namespace leaf {
namespace leaf_detail
@@ -139,7 +128,7 @@ namespace leaf_detail
scoped_demangled_name& operator= ( scoped_demangled_name const& ) = delete;
};
#if defined(BOOST_LEAF_HAS_CXXABI_H) and !defined(BOOST_LEAF_DISABLE_STD_STRING)
#ifdef BOOST_LEAF_HAS_CXXABI_H
inline char const * demangle_alloc( char const * name ) noexcept
{
@@ -183,10 +172,24 @@ namespace leaf_detail
} }
#ifdef BOOST_LEAF_HAS_CXXABI_H
# undef BOOST_LEAF_HAS_CXXABI_H
#else
namespace boost { namespace leaf {
namespace leaf_detail
{
inline char const * demangle( char const * name )
{
return name;
}
}
} }
#endif
#ifdef BOOST_LEAF_HAS_CXXABI_H
# undef BOOST_LEAF_HAS_CXXABI_H
#endif
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///

View File

@@ -16,7 +16,7 @@
# endif ///
#endif ///
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#include <utility>
#include <new>

View File

@@ -30,7 +30,7 @@
# include <set>
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
# include <system_error>
#endif
@@ -64,6 +64,9 @@ class error_id;
namespace leaf_detail
{
struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_unexpected_enabled_counter;
struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id;
struct inject_loc
{
char const * const file;
@@ -116,32 +119,6 @@ BOOST_LEAF_NORETURN void throw_exception( T const & e )
////////////////////////////////////////
#ifdef BOOST_LEAF_NO_THREADS
# define BOOST_LEAF_THREAD_LOCAL
namespace boost { namespace leaf {
namespace leaf_detail
{
using atomic_unsigned_int = unsigned int;
}
} }
#else
# include <atomic>
# include <thread>
# define BOOST_LEAF_THREAD_LOCAL BOOST_LEAF_SYMBOL_VISIBLE thread_local
namespace boost { namespace leaf {
namespace leaf_detail
{
using atomic_unsigned_int = std::atomic<unsigned int>;
}
} }
#endif
////////////////////////////////////////
namespace boost { namespace leaf {
#if BOOST_LEAF_DIAGNOSTICS
@@ -223,14 +200,6 @@ namespace leaf_detail
BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, e_unexpected_info const &) noexcept { }
};
template <class=void>
struct BOOST_LEAF_SYMBOL_VISIBLE tl_unexpected_enabled
{
static BOOST_LEAF_THREAD_LOCAL int counter;
};
template <class T>
BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled<T>::counter;
}
#endif
@@ -259,54 +228,38 @@ struct BOOST_LEAF_SYMBOL_VISIBLE e_source_location
namespace leaf_detail
{
template <class E>
class slot;
template <class E>
struct BOOST_LEAF_SYMBOL_VISIBLE tl_slot_ptr
{
static BOOST_LEAF_THREAD_LOCAL slot<E> * p;
};
template <class E>
BOOST_LEAF_THREAD_LOCAL slot<E> * tl_slot_ptr<E>::p;
template <class E>
class slot:
class BOOST_LEAF_SYMBOL_VISIBLE slot:
optional<E>
{
slot( slot const & ) = delete;
slot & operator=( slot const & ) = delete;
using impl = optional<E>;
slot<E> * * top_;
slot<E> * prev_;
public:
BOOST_LEAF_CONSTEXPR slot() noexcept:
top_(0)
prev_(0)
{
}
BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept:
optional<E>(std::move(x)),
top_(0)
prev_(0)
{
BOOST_LEAF_ASSERT(x.top_==0);
BOOST_LEAF_ASSERT(x.prev_==0);
}
BOOST_LEAF_CONSTEXPR void activate() noexcept
{
BOOST_LEAF_ASSERT(top_==0 || *top_!=this);
top_ = &tl_slot_ptr<E>::p;
prev_ = *top_;
*top_ = this;
prev_ = tls::read_ptr<slot<E>>();
tls::write_ptr<slot<E>>(this);
}
BOOST_LEAF_CONSTEXPR void deactivate() noexcept
{
BOOST_LEAF_ASSERT(top_!=0 && *top_==this);
*top_ = prev_;
tls::write_ptr<slot<E>>(prev_);
}
BOOST_LEAF_CONSTEXPR void propagate() noexcept;
@@ -341,7 +294,7 @@ namespace leaf_detail
template <class E>
BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept
{
if( slot<e_unexpected_count> * sl = tl_slot_ptr<e_unexpected_count>::p )
if( slot<e_unexpected_count> * sl = tls::read_ptr<slot<e_unexpected_count>>() )
if( e_unexpected_count * unx = sl->has_value(err_id) )
++unx->count;
else
@@ -351,7 +304,7 @@ namespace leaf_detail
template <class E>
BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept
{
if( slot<e_unexpected_info> * sl = tl_slot_ptr<e_unexpected_info>::p )
if( slot<e_unexpected_info> * sl = tls::read_ptr<slot<e_unexpected_info>>() )
if( e_unexpected_info * unx = sl->has_value(err_id) )
unx->add(std::forward<E>(e));
else
@@ -370,7 +323,6 @@ namespace leaf_detail
template <class E>
BOOST_LEAF_CONSTEXPR inline void slot<E>::propagate() noexcept
{
BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this));
if( prev_ )
{
impl & that_ = *prev_;
@@ -383,7 +335,7 @@ namespace leaf_detail
#if BOOST_LEAF_DIAGNOSTICS
else
{
int c = tl_unexpected_enabled<>::counter;
int c = tls::read_uint32<tls_tag_unexpected_enabled_counter>();
BOOST_LEAF_ASSERT(c>=0);
if( c )
if( int err_id = impl::key() )
@@ -399,12 +351,12 @@ namespace leaf_detail
static_assert(!std::is_same<typename std::decay<E>::type, error_id>::value, "Error objects of type error_id are not allowed");
using T = typename std::decay<E>::type;
BOOST_LEAF_ASSERT((err_id&3)==1);
if( slot<T> * p = tl_slot_ptr<T>::p )
if( slot<T> * p = tls::read_ptr<slot<T>>() )
(void) p->put(err_id, std::forward<E>(e));
#if BOOST_LEAF_DIAGNOSTICS
else
{
int c = tl_unexpected_enabled<>::counter;
int c = tls::read_uint32<tls_tag_unexpected_enabled_counter>();
BOOST_LEAF_ASSERT(c>=0);
if( c )
load_unexpected(err_id, std::forward<E>(e));
@@ -420,7 +372,7 @@ namespace leaf_detail
using E = typename std::decay<fn_arg_type<F,0>>::type;
static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed");
BOOST_LEAF_ASSERT((err_id&3)==1);
if( auto sl = tl_slot_ptr<E>::p )
if( auto sl = tls::read_ptr<slot<E>>() )
if( auto v = sl->has_value(err_id) )
(void) std::forward<F>(f)(*v);
else
@@ -437,7 +389,6 @@ namespace leaf_detail
struct BOOST_LEAF_SYMBOL_VISIBLE id_factory
{
static atomic_unsigned_int counter;
static BOOST_LEAF_THREAD_LOCAL unsigned current_id;
BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept
{
@@ -450,12 +401,9 @@ namespace leaf_detail
template <class T>
atomic_unsigned_int id_factory<T>::counter(-3);
template <class T>
BOOST_LEAF_THREAD_LOCAL unsigned id_factory<T>::current_id(0);
inline int current_id() noexcept
{
auto id = id_factory<>::current_id;
auto id = tls::read_uint32<tls_tag_id_factory_current_id>();
BOOST_LEAF_ASSERT(id==0 || (id&3)==1);
return id;
}
@@ -463,7 +411,8 @@ namespace leaf_detail
inline int new_id() noexcept
{
auto id = id_factory<>::generate_next_id();
return id_factory<>::current_id = id;
tls::write_uint32<tls_tag_id_factory_current_id>(id);
return id;
}
}
@@ -507,7 +456,7 @@ namespace leaf_detail
////////////////////////////////////////
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
namespace leaf_detail
{
class leaf_category final: public std::error_category
@@ -585,7 +534,7 @@ public:
{
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
error_id( std::error_code const & ec ) noexcept:
value_(leaf_detail::import_error_code(ec))
{
@@ -785,8 +734,6 @@ struct is_result_type<R const>: is_result_type<R>
} }
#undef BOOST_LEAF_THREAD_LOCAL
#if defined(_MSC_VER) && !defined(BOOST_LEAF_ENABLE_WARNINGS) ///
#pragma warning(pop) ///
#endif ///

View File

@@ -32,7 +32,7 @@ class BOOST_LEAF_SYMBOL_VISIBLE error_info
#ifndef BOOST_LEAF_NO_EXCEPTIONS
static error_id unpack_error_id( std::exception const * ex ) noexcept
{
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
if( std::system_error const * se = dynamic_cast<std::system_error const *>(ex) )
if( is_error_id(se->code()) )
return leaf_detail::make_error_id(se->code().value());
@@ -379,7 +379,7 @@ namespace leaf_detail
}
};
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <>
struct peek_exception<std::error_code const, true>
{

View File

@@ -107,7 +107,7 @@ namespace leaf_detail
public:
BOOST_LEAF_CONSTEXPR preloaded_item( E && e ):
s_(tl_slot_ptr<decay_E>::p),
s_(tls::read_ptr<slot<decay_E>>()),
e_(std::forward<E>(e))
{
}
@@ -123,7 +123,7 @@ namespace leaf_detail
#if BOOST_LEAF_DIAGNOSTICS
else
{
int c = tl_unexpected_enabled<>::counter;
int c = tls::read_uint32<tls_tag_unexpected_enabled_counter>();
BOOST_LEAF_ASSERT(c>=0);
if( c )
load_unexpected(err_id, std::move(e_));
@@ -142,7 +142,7 @@ namespace leaf_detail
public:
BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept:
s_(tl_slot_ptr<E>::p),
s_(tls::read_ptr<slot<E>>()),
f_(std::forward<F>(f))
{
}
@@ -158,7 +158,7 @@ namespace leaf_detail
#if BOOST_LEAF_DIAGNOSTICS
else
{
int c = tl_unexpected_enabled<>::counter;
int c = tls::read_uint32<tls_tag_unexpected_enabled_counter>();
BOOST_LEAF_ASSERT(c>=0);
if( c )
load_unexpected(err_id, std::forward<E>(f_()));
@@ -180,7 +180,7 @@ namespace leaf_detail
public:
BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept:
s_(tl_slot_ptr<E>::p),
s_(tls::read_ptr<slot<E>>()),
f_(std::forward<F>(f))
{
}

View File

@@ -60,7 +60,7 @@ namespace leaf_detail
////////////////////////////////////////
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class E, class Enum = E>
struct condition
{
@@ -93,7 +93,7 @@ namespace leaf_detail
using type = T;
};
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class Enum>
struct match_enum_type<condition<Enum, Enum>>
{
@@ -121,7 +121,7 @@ struct match
}
};
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_enum_type<condition<Enum, Enum>>), V1, V)>
struct match<condition<Enum, Enum>, V1, V...>
{
@@ -150,7 +150,7 @@ namespace leaf_detail
using type = typename std::remove_reference<decltype(std::declval<E>().value)>::type;
};
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class E, class Enum>
struct match_value_enum_type<condition<E, Enum>>
{
@@ -177,7 +177,7 @@ struct match_value
}
};
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class E, class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_value_enum_type<condition<E, Enum>>), V1, V)>
struct match_value<condition<E, Enum>, V1, V...>
{

View File

@@ -191,7 +191,7 @@ class result
#else
{
error_id captured_id = r_.ctx_->propagate_captured_errors();
leaf_detail::id_factory<>::current_id = captured_id.value();
tls::write_uint32<leaf_detail::tls_tag_id_factory_current_id>(captured_id.value());
return captured_id;
}
#endif
@@ -352,7 +352,7 @@ public:
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
result( std::error_code const & ec ) noexcept:
what_(error_id(ec))
{
@@ -520,7 +520,7 @@ public:
{
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
result( std::error_code const & ec ) noexcept:
base(ec)
{

View File

@@ -98,9 +98,7 @@ endif
dep_thread = dependency('threads')
includes = [ include_directories('include') ]
leaf = declare_dependency( include_directories: includes, compile_args: defines )
leaf = declare_dependency( include_directories: 'include', compile_args: defines )
#################################
@@ -168,6 +166,7 @@ if option_enable_unit_tests
'result_load_test',
'result_ref_test',
'result_state_test',
'tls_array_test',
'try_catch_error_id_test',
'try_catch_system_error_test',
'try_catch_test',

View File

@@ -99,6 +99,7 @@ run result_load_test.cpp ;
run result_ref_test.cpp ;
run result_state_test.cpp ;
run context_deduction_test.cpp ;
run tls_array_test.cpp ;
run try_catch_error_id_test.cpp ;
run try_catch_test.cpp ;
run try_exception_and_result_test.cpp ;

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || !defined(BOOST_LEAF_BOOST_AVAILABLE)
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || defined(BOOST_LEAF_NO_THREADS)
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || defined(BOOST_LEAF_NO_THREADS)
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_THREADS
#include <iostream>

View File

@@ -6,7 +6,7 @@
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
# include "leaf.hpp"
#else
# include <boost/leaf/detail/config.hpp>
# include <boost/leaf/config.hpp>
# include <boost/leaf/context.hpp>
# include <boost/leaf/pred.hpp>
# include <boost/leaf/handle_errors.hpp>
@@ -116,13 +116,13 @@ void not_called_on_purpose()
test< std::tuple<info<1>,info<2>,info<3>> >( expd([]( info<1> ){ }, []( info<2>, info<3> ){ }, []( info<3> ){ }) );
test< std::tuple<my_error_code> >( expd([]( leaf::match<my_error_code, my_error_code::error1> ){ }) );
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
test< std::tuple<std::error_code> >( expd([]( leaf::match<leaf::condition<cond_x>, cond_x::x00> ){ }) );
#endif
test< std::tuple<info<1>> >( expd([]( leaf::match_value<info<1>,42> ){ }) );
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
test< std::tuple<std::error_code> >( expd([]( leaf::match<leaf::condition<my_error_condition>, my_error_condition::cond1> ){ }) );
#if __cplusplus >= 201703L
test< std::tuple<std::error_code> >( expd([]( leaf::match<std::error_code, my_error_code::error1> ){ }) );

View File

@@ -52,7 +52,7 @@ int main()
[]( info<42> const & i42, leaf::diagnostic_info const & di )
{
BOOST_TEST_EQ(i42.value, 42);
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << di;
std::string s = ss.str();
std::cout << s;

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -6,7 +6,7 @@
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
# include "leaf.hpp"
#else
# include <boost/leaf/detail/config.hpp>
# include <boost/leaf/config.hpp>
# include <boost/leaf/handle_errors.hpp>
# include <boost/leaf/result.hpp>
# include <boost/leaf/common.hpp>
@@ -104,7 +104,7 @@ int main()
leaf::e_errno,
leaf::error_info const & unmatched )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << unmatched;
std::string s = st.str();
@@ -142,7 +142,7 @@ int main()
leaf::e_errno,
leaf::diagnostic_info const & unmatched )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << unmatched;
std::string s = st.str();
@@ -194,7 +194,7 @@ int main()
leaf::e_errno,
leaf::verbose_diagnostic_info const & di )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << di;
std::string s = st.str();
@@ -252,7 +252,7 @@ int main()
leaf::e_errno,
leaf::error_info const & unmatched )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << unmatched;
std::string s = st.str();
@@ -288,7 +288,7 @@ int main()
leaf::e_errno,
leaf::diagnostic_info const & unmatched )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << unmatched;
std::string s = st.str();
@@ -340,7 +340,7 @@ int main()
leaf::e_errno,
leaf::verbose_diagnostic_info const & di )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::ostringstream st;
st << di;
std::string s = st.str();

View File

@@ -31,7 +31,7 @@ namespace leaf = boost::leaf;
int main()
{
SetLastError(ERROR_FILE_NOT_FOUND);
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss;
ss << leaf::windows::e_LastError{};
BOOST_TEST(ss.str().find("The system cannot find the file specified") != std::string::npos);

View File

@@ -19,7 +19,7 @@ namespace leaf = boost::leaf;
int main()
{
errno = ENOENT;
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss;
ss << leaf::e_errno{};
BOOST_TEST(ss.str().find(std::strerror(ENOENT)) != std::string::npos);

View File

@@ -3,8 +3,9 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#ifdef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#include <boost/leaf/config.hpp>
#if !BOOST_LEAF_USE_STD_SYSTEM_ERROR
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,8 +3,9 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#ifdef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#include <boost/leaf/config.hpp>
#if !BOOST_LEAF_USE_STD_SYSTEM_ERROR
#include <iostream>

View File

@@ -28,7 +28,7 @@ enum class my_error_code
struct e_my_error_code { my_error_code value; };
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
struct e_std_error_code { std::error_code value; };
#endif
@@ -41,7 +41,7 @@ leaf::result<R> f( my_error_code ec )
return leaf::new_error(ec, e_my_error_code{ec}, info<1>{1}, info<2>{2}, info<3>{3});
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class R, class Errc>
leaf::result<R> f_errc( Errc ec )
{
@@ -109,7 +109,7 @@ int main()
BOOST_TEST_EQ(c, 1);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_all (failure), match cond_x (single enum value)
{
int c=0;
@@ -142,7 +142,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_all (failure), match cond_x (wrapped std::error_code)
{
int c=0;
@@ -338,7 +338,7 @@ int main()
BOOST_TEST_EQ(r, 1);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// int, try_handle_all (failure), match cond_x (single enum value)
{
int r = leaf::try_handle_all(
@@ -366,7 +366,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// int, try_handle_all (failure), match cond_x (wrapped std::error_code)
{
int r = leaf::try_handle_all(
@@ -537,7 +537,7 @@ int main()
BOOST_TEST_EQ(r.value, 1);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// move_only, try_handle_all (failure), match cond_x (single enum value)
{
move_only r = leaf::try_handle_all(
@@ -565,7 +565,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// move_only, try_handle_all (failure), match cond_x (wrapped std::error_code)
{
move_only r = leaf::try_handle_all(

View File

@@ -6,7 +6,7 @@
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
# include "leaf.hpp"
#else
# include <boost/leaf/detail/config.hpp>
# include <boost/leaf/config.hpp>
# include <boost/leaf/handle_errors.hpp>
# include <boost/leaf/pred.hpp>
# include <boost/leaf/result.hpp>

View File

@@ -3,8 +3,9 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#ifdef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#include <boost/leaf/config.hpp>
#if !BOOST_LEAF_USE_STD_SYSTEM_ERROR
#include <iostream>

View File

@@ -28,7 +28,7 @@ enum class my_error_code
struct e_my_error_code { my_error_code value; };
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
struct e_std_error_code { std::error_code value; };
#endif
@@ -41,7 +41,7 @@ leaf::result<R> f( my_error_code ec )
return leaf::new_error(ec, e_my_error_code{ec}, info<1>{1}, info<2>{2}, info<3>{3});
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
template <class R, class Errc>
leaf::result<R> f_errc( Errc ec )
{
@@ -99,7 +99,7 @@ int main()
BOOST_TEST(r);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, matched), match cond_x (single enum value)
{
int c=0;
@@ -123,7 +123,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, matched), match cond_x (wrapped std::error_code)
{
int c=0;
@@ -293,7 +293,7 @@ int main()
BOOST_TEST_EQ(c, 2);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, initially not matched), match cond_x (single enum value)
{
int c=0;
@@ -333,7 +333,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, initially not matched), match cond_x (wrapped std::error_code)
{
int c=0;
@@ -563,7 +563,7 @@ int main()
BOOST_TEST_EQ(c, 1);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, initially matched), match cond_x (single enum value)
{
int c=0;
@@ -603,7 +603,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// void, try_handle_some (failure, initially matched), match cond_x (wrapped std::error_code)
{
int c=0;
@@ -831,7 +831,7 @@ int main()
BOOST_TEST_EQ(*r, 1);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// int, try_handle_some (failure, matched), match cond_x (single enum value)
{
leaf::result<int> r = leaf::try_handle_some(
@@ -980,7 +980,7 @@ int main()
BOOST_TEST_EQ(r, 2);
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
// int, try_handle_some (failure, initially not matched), match cond_x (single enum value)
{
int r = leaf::try_handle_all(

View File

@@ -3,7 +3,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#include "boost/core/lightweight_test.hpp"
#include <exception>

View File

@@ -33,7 +33,7 @@ enum class my_error { e1=1, e2, e3 };
struct e_my_error { my_error value; };
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
struct e_error_code { std::error_code value; };
#endif
@@ -65,7 +65,7 @@ int main()
BOOST_TEST(( test<leaf::match_member<&e_my_error::value, my_error::e2, my_error::e1>>(e) ));
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
{
e_error_code e = { errc_a::a0 };

View File

@@ -80,7 +80,7 @@ int main()
BOOST_TEST(( !test<leaf::if_not<leaf::match<my_error, my_error::e2, my_error::e1>>>(e) ));
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
{
std::error_code e = errc_a::a0;

View File

@@ -21,7 +21,7 @@ enum class my_error { e1=1, e2, e3 };
struct e_my_error { my_error value; };
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
struct e_error_code { std::error_code value; };
#endif
@@ -53,7 +53,7 @@ int main()
BOOST_TEST(( test<leaf::match_value<e_my_error, my_error::e2, my_error::e1>>(e) ));
}
#ifndef BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR
#if BOOST_LEAF_USE_STD_SYSTEM_ERROR
{
e_error_code e = { errc_a::a0 };

View File

@@ -3,7 +3,7 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#include <boost/leaf/handle_errors.hpp>
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER

View File

@@ -39,7 +39,7 @@ void test( G && g )
[]( info<42> const & i42, leaf::diagnostic_info const & di )
{
BOOST_TEST_EQ(i42.value, 42);
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << di;
std::string s = ss.str();
std::cout << s;

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || defined(BOOST_LEAF_NO_THREADS)
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#if BOOST_LEAF_DIAGNOSTICS==0
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -595,7 +595,7 @@ int main()
}
BOOST_TEST_EQ(val::count, 0);
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
{ // Initialization forwarding constructor
leaf::result<std::string> r = "hello";
BOOST_TEST(r);
@@ -603,7 +603,7 @@ int main()
}
#endif
#ifndef BOOST_LEAF_DISABLE_STD_STRING
#if BOOST_LEAF_USE_STD_STRING
{ // Initialization forwarding constructor
leaf::result<std::string> r; r = "hello";
BOOST_TEST(r);

98
test/tls_array_test.cpp Normal file
View File

@@ -0,0 +1,98 @@
// Copyright (c) 2018-2021 Emil Dotchevski and Reverge Studios, Inc.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_LEAF_NO_EXCEPTIONS
#define BOOST_LEAF_USE_STD_SYSTEM_ERROR 0
#define BOOST_LEAF_USE_STD_STRING 0
#define BOOST_LEAF_DIAGNOSTICS 0
#define BOOST_LEAF_TLS_ARRAY
#define BOOST_LEAF_TLS_ARRAY_SIZE 64
#define BOOST_LEAF_TLS_ARRAY_START_INDEX 10
#ifdef BOOST_LEAF_TEST_SINGLE_HEADER
# include "leaf.hpp"
#else
# include <boost/leaf/handle_errors.hpp>
# include <boost/leaf/result.hpp>
#endif
#include <limits>
#include <vector>
#include <algorithm>
#include "lightweight_test.hpp"
namespace leaf = boost::leaf;
static void * tls_storage[BOOST_LEAF_TLS_ARRAY_SIZE];
static int min_tls_index = std::numeric_limits<int>::max();
static int max_tls_index = std::numeric_limits<int>::min();
namespace boost { namespace leaf {
namespace tls
{
void * read_void_ptr( int tls_index ) noexcept
{
BOOST_TEST(tls_index>=BOOST_LEAF_TLS_ARRAY_START_INDEX);
BOOST_TEST(tls_index<BOOST_LEAF_TLS_ARRAY_SIZE);
min_tls_index = std::min(min_tls_index, tls_index);
max_tls_index = std::max(max_tls_index, tls_index);
return tls_storage[tls_index];
}
void write_void_ptr( int tls_index, void * p ) noexcept
{
BOOST_TEST(tls_index>=BOOST_LEAF_TLS_ARRAY_START_INDEX);
BOOST_TEST(tls_index<BOOST_LEAF_TLS_ARRAY_SIZE);
min_tls_index = std::min(min_tls_index, tls_index);
max_tls_index = std::max(max_tls_index, tls_index);
tls_storage[tls_index] = p;
}
}
} }
template <int>
struct my_error_info
{
};
// Mirroring boost::leaf::leaf_detail::optional<T>, to verify correctness of TLS pointers
template <class T>
struct optional
{
int key_;
union { T value_; };
};
int const offset = offsetof(optional<my_error_info<1>>, value_);
int main()
{
std::vector<void const *> used_ptrs;
int r = leaf::try_handle_all(
[&]() -> leaf::result<int>
{
BOOST_TEST(min_tls_index>=BOOST_LEAF_TLS_ARRAY_START_INDEX);
BOOST_TEST(max_tls_index>min_tls_index);
BOOST_TEST(max_tls_index<BOOST_LEAF_TLS_ARRAY_SIZE);
for( int i=min_tls_index; i<=max_tls_index; ++i )
used_ptrs.push_back((char const *)tls_storage[i] + offset);
return leaf::new_error( my_error_info<1>{}, my_error_info<2>{} );
},
[&]( my_error_info<1> const & a, my_error_info<2> const & b )
{
BOOST_TEST(std::find(used_ptrs.begin(), used_ptrs.end(), &a) != used_ptrs.end());
BOOST_TEST(std::find(used_ptrs.begin(), used_ptrs.end(), &b) != used_ptrs.end());
return 1;
},
[]
{
return 2;
} );
BOOST_TEST(r==1);
return boost::report_errors();
}

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -3,8 +3,9 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || defined(BOOST_LEAF_DISABLE_STD_SYSTEM_ERROR)
#include <boost/leaf/config.hpp>
#if defined(BOOST_LEAF_NO_EXCEPTIONS) || !BOOST_LEAF_USE_STD_SYSTEM_ERROR
#include <iostream>

View File

@@ -3,7 +3,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/leaf/detail/config.hpp>
#include <boost/leaf/config.hpp>
#ifdef BOOST_LEAF_NO_EXCEPTIONS
#include <iostream>

View File

@@ -19,92 +19,91 @@ namespace leaf = boost::leaf;
leaf::result<void> hidden_result();
void hidden_throw();
int
main()
int main()
{
{
{
int r = leaf::try_handle_all(
[]() -> leaf::result<int>
int r = leaf::try_handle_all(
[]() -> leaf::result<int>
{
BOOST_LEAF_CHECK(hidden_result());
return 0;
},
[]( my_info<1> x1, my_info<2> x2, leaf::diagnostic_info const & info, leaf::verbose_diagnostic_info const & vinfo )
{
BOOST_TEST_EQ(x1.value, 1);
BOOST_TEST_EQ(x2.value, 2);
if( BOOST_LEAF_DIAGNOSTICS )
{
BOOST_LEAF_CHECK(hidden_result());
return 0;
},
[]( my_info<1> x1, my_info<2> x2, leaf::diagnostic_info const & info, leaf::verbose_diagnostic_info const & vinfo )
{
BOOST_TEST_EQ(x1.value, 1);
BOOST_TEST_EQ(x2.value, 2);
if( BOOST_LEAF_DIAGNOSTICS )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
std::stringstream ss; ss << info;
BOOST_TEST_NE(ss.str().find("1 attempt to communicate an unexpected error object"), std::string::npos);
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << info;
BOOST_TEST_NE(ss.str().find("1 attempt to communicate an unexpected error object"), std::string::npos);
#endif
}
if( BOOST_LEAF_DIAGNOSTICS )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
std::stringstream ss; ss << vinfo;
BOOST_TEST_NE(ss.str().find("Test my_info<3>::value = 3"), std::string::npos);
#endif
}
return 1;
},
[]
}
if( BOOST_LEAF_DIAGNOSTICS )
{
return 2;
} );
BOOST_TEST_EQ(r, 1);
}
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << vinfo;
BOOST_TEST_NE(ss.str().find("Test my_info<3>::value = 3"), std::string::npos);
#endif
}
return 1;
},
[]
{
return 2;
} );
BOOST_TEST_EQ(r, 1);
}
#ifndef BOOST_LEAF_NO_EXCEPTIONS
{
int r = leaf::try_catch(
[]
{
hidden_throw();
return 0;
},
[]( my_info<1> x1, my_info<2> x2, leaf::diagnostic_info const & info, leaf::verbose_diagnostic_info const & vinfo )
{
BOOST_TEST_EQ(x1.value, 1);
BOOST_TEST_EQ(x2.value, 2);
if( BOOST_LEAF_DIAGNOSTICS )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
std::stringstream ss; ss << info;
BOOST_TEST_NE(ss.str().find("1 attempt to communicate an unexpected error object"), std::string::npos);
#endif
}
if( BOOST_LEAF_DIAGNOSTICS )
{
#ifndef BOOST_LEAF_DISABLE_STD_STRING
std::stringstream ss; ss << vinfo;
BOOST_TEST_NE(ss.str().find("Test my_info<3>::value = 3"), std::string::npos);
#endif
}
return 1;
},
[]
{
return 2;
} );
BOOST_TEST_EQ(r, 1);
}
{
try
{
int r = leaf::try_catch(
[]
{
hidden_throw();
BOOST_ERROR("hidden_throw() failed to throw");
}
catch( leaf::error_id const & )
return 0;
},
[]( my_info<1> x1, my_info<2> x2, leaf::diagnostic_info const & info, leaf::verbose_diagnostic_info const & vinfo )
{
}
catch(...)
BOOST_TEST_EQ(x1.value, 1);
BOOST_TEST_EQ(x2.value, 2);
if( BOOST_LEAF_DIAGNOSTICS )
{
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << info;
BOOST_TEST_NE(ss.str().find("1 attempt to communicate an unexpected error object"), std::string::npos);
#endif
}
if( BOOST_LEAF_DIAGNOSTICS )
{
#if BOOST_LEAF_USE_STD_STRING
std::stringstream ss; ss << vinfo;
BOOST_TEST_NE(ss.str().find("Test my_info<3>::value = 3"), std::string::npos);
#endif
}
return 1;
},
[]
{
BOOST_ERROR("Failed to catch leaf::error_id");
}
return 2;
} );
BOOST_TEST_EQ(r, 1);
}
{
try
{
hidden_throw();
BOOST_ERROR("hidden_throw() failed to throw");
}
catch( leaf::error_id const & )
{
}
catch(...)
{
BOOST_ERROR("Failed to catch leaf::error_id");
}
}
#endif
return boost::report_errors();
}
return boost::report_errors();
}