[DEV] add v1.76.0

This commit is contained in:
2021-10-05 21:37:46 +02:00
parent a97e9ae7d4
commit d0115b733d
45133 changed files with 4744437 additions and 1026325 deletions

View File

@@ -0,0 +1,64 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ADL bridging - Boost.Outcome documentation</title>
<link rel="stylesheet" href="../../../css/boost.css" type="text/css">
<meta name="generator" content="Hugo 0.52 with Boostdoc theme">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
<body><div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/keeping_state.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">ADL bridging</h1></div></div></div>
<div class="notices note" style="background: url('../../../images/note.png') top left no-repeat padding-box padding-box;">
<div class="notices heading">note</div>
<div class="notices message"><p>In Outcome v2.2 the ADL-based event hooks were replaced with policy-based event hooks (next page).
The code in this section is still valid in v2.2 onwards, it&rsquo;s just that ADL is no longer used
to find the hooks.</p>
</div>
</div>
<p>In a previous section, we used the <code>failure_info</code> type to create
the ADL bridge into the namespace where the ADL discovered <a href="../../../reference/functions/policy.html"><code>outcome_throw_as_system_error_with_payload()</code></a> function was to be found.</p>
<p>Here we do the same, but more directly by creating a thin clone of <code>std::error_code</code>
into the local namespace. This ensures that this namespace will be searched by the
compiler when discovering the event hooks (Outcome v2.1 and earlier only).</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">error_code_extended</span>
<span class="p">{</span>
<span class="c1">// Use the error_code type as the ADL bridge for the hooks by creating a type here
</span><span class="c1"></span> <span class="c1">// It can be any type that your localised result uses, including the value type but
</span><span class="c1"></span> <span class="c1">// by localising the error code type here you prevent nasty surprises later when the
</span><span class="c1"></span> <span class="c1">// value type you use doesn&#39;t trigger the ADL bridge.
</span><span class="c1"></span> <span class="k">struct</span> <span class="nl">error_code</span> <span class="p">:</span> <span class="k">public</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span>
<span class="p">{</span>
<span class="c1">// literally passthrough
</span><span class="c1"></span> <span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span><span class="o">::</span><span class="n">error_code</span><span class="p">;</span>
<span class="n">error_code</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="n">error_code</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="n">ec</span><span class="p">)</span>
<span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="c1">// Localise result and outcome to using the local error_code so this namespace gets looked up for the hooks
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">R</span><span class="o">&gt;</span> <span class="k">using</span> <span class="n">result</span> <span class="o">=</span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">R</span><span class="p">,</span> <span class="n">error_code</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">R</span><span class="o">&gt;</span> <span class="k">using</span> <span class="n">outcome</span> <span class="o">=</span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">R</span><span class="p">,</span> <span class="n">error_code</span> <span class="cm">/*, std::exception_ptr */</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/error_code_extended.cpp#L95" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>For convenience, we template alias local copies of <code>result</code> and <code>outcome</code> in this
namespace bound to the ADL bridging <code>error_code</code>.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/keeping_state.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,72 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hook outcome - Boost.Outcome documentation</title>
<link rel="stylesheet" href="../../../css/boost.css" type="text/css">
<meta name="generator" content="Hugo 0.52 with Boostdoc theme">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
<body><div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/poke_exception.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/interop.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Hook outcome</h1></div></div></div>
<p>The final step is to add event hooks for the very specific case of
when our localised <code>outcome</code> is copy or move constructed from our localised <code>result</code>.</p>
<p>You ought to be very careful that the <code>noexcept</code>-ness of these matches the <code>noexcept</code>-ness
of the types in the <code>outcome</code>. You may have noticed that <code>poke_exception()</code> creates
a <code>std::string</code> and appends to it. This can throw an exception. If the copy and/or
move constructors of <code>T</code>, <code>EC</code> and <code>EP</code> are <code>noexcept</code>, then so will be <code>outcome</code>&rsquo;s
copy and/or move constructor. Thus if <code>poke_exception()</code> throws, instant program
termination would occur, which is bad.</p>
<p>We avoid that problem in this case by wrapping <code>poke_exception()</code> in a <code>try...catch</code>
which throws away any exceptions thrown. For Outcome before v2.2, these specially
named free functions must be placed into a namespace which is ADL searched:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">error_code_extended</span>
<span class="p">{</span>
<span class="c1">// Specialise the outcome copy and move conversion hook for when our localised result
</span><span class="c1"></span> <span class="c1">// is used as the source for copy construction our localised outcome
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="n">hook_outcome_copy_construction</span><span class="p">(</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">*</span><span class="n">res</span><span class="p">,</span> <span class="k">const</span> <span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span> <span class="o">&amp;</span> <span class="cm">/*unused*/</span><span class="p">)</span> <span class="k">noexcept</span>
<span class="p">{</span>
<span class="k">try</span>
<span class="p">{</span>
<span class="c1">// when copy constructing from a result&lt;T&gt;, poke in an exception
</span><span class="c1"></span> <span class="n">poke_exception</span><span class="p">(</span><span class="n">res</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span><span class="p">(...)</span>
<span class="p">{</span>
<span class="c1">// Do nothing
</span><span class="c1"></span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="n">hook_outcome_move_construction</span><span class="p">(</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">*</span><span class="n">res</span><span class="p">,</span> <span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span> <span class="o">&amp;&amp;</span> <span class="cm">/*unused*/</span><span class="p">)</span> <span class="k">noexcept</span>
<span class="p">{</span>
<span class="k">try</span>
<span class="p">{</span>
<span class="c1">// when move constructing from a result&lt;T&gt;, poke in an exception
</span><span class="c1"></span> <span class="n">poke_exception</span><span class="p">(</span><span class="n">res</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">catch</span><span class="p">(...)</span>
<span class="p">{</span>
<span class="c1">// Do nothing
</span><span class="c1"></span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/error_code_extended.cpp#L182" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>For Outcome v2.2 and later, these functions must be placed into a custom no value
policy with the names <code>on_outcome_copy_construction()</code> and <code>on_outcome_move_construction()</code>
respectively. As with before, the implementation of the functions is identical, just
the name and location has changed.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/poke_exception.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/interop.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,86 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hook result - Boost.Outcome documentation</title>
<link rel="stylesheet" href="../../../css/boost.css" type="text/css">
<meta name="generator" content="Hugo 0.52 with Boostdoc theme">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
<body><div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/adl_bridging.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/poke_exception.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Hook result</h1></div></div></div>
<p>We now tell Outcome that for every instance of our localised <code>result&lt;T&gt;</code>, that
on failure construction only, we want custom code to be run which increments the current
slot in TLS storage and writes the current stack backtrace into it.</p>
<p>For Outcome before v2.2, we must do this by inserting a specially named free function into
a namespace searched by ADL:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">error_code_extended</span>
<span class="p">{</span>
<span class="c1">// Specialise the result construction hook for our localised result
</span><span class="c1"></span> <span class="c1">// We hook any non-copy, non-move, non-inplace construction, capturing a stack backtrace
</span><span class="c1"></span> <span class="c1">// if the result is errored.
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="n">hook_result_construction</span><span class="p">(</span><span class="n">result</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="o">*</span><span class="n">res</span><span class="p">,</span> <span class="n">U</span> <span class="o">&amp;&amp;</span> <span class="cm">/*unused*/</span><span class="p">)</span> <span class="k">noexcept</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">res</span><span class="o">-&gt;</span><span class="n">has_error</span><span class="p">())</span>
<span class="p">{</span>
<span class="c1">// Grab the next extended info slot in the TLS
</span><span class="c1"></span> <span class="n">extended_error_info</span> <span class="o">&amp;</span><span class="n">eei</span> <span class="o">=</span> <span class="n">mythreadlocaldata</span><span class="p">().</span><span class="n">next</span><span class="p">();</span>
<span class="c1">// Write the index just grabbed into the spare uint16_t
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">hooks</span><span class="o">::</span><span class="n">set_spare_storage</span><span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="n">mythreadlocaldata</span><span class="p">().</span><span class="n">current</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="c1">// Capture a backtrace into my claimed extended info slot in the TLS
</span><span class="c1"></span> <span class="n">eei</span><span class="p">.</span><span class="n">items</span> <span class="o">=</span> <span class="o">::</span><span class="n">backtrace</span><span class="p">(</span><span class="n">eei</span><span class="p">.</span><span class="n">backtrace</span><span class="p">.</span><span class="n">data</span><span class="p">(),</span> <span class="n">eei</span><span class="p">.</span><span class="n">backtrace</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/error_code_extended.cpp#L119" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>For Outcome v2.2 and later, we must do this by using a custom no value policy which contains
a function named <code>on_result_construction()</code>. The function implementation is identical between
both mechanisms, just the name and placement of the function declaration differs.</p>
<p>The only non-obvious part above is the call to <a href="../../../reference/functions/hooks/set_spare_storage.html" class="api-reference"><code>void set_spare_storage(basic_result|basic_outcome *, uint16_t) noexcept</code></a>
.</p>
<p>Both <code>result</code> and <code>outcome</code> keep their internal state metadata in a <code>uint32_t</code>,
half of which is not used by Outcome. As it can be very useful to keep a small
unique number attached to any particular <code>result</code> or <code>outcome</code> instance, we
permit user code to set those sixteen bits to anything they feel like.
The corresponding function to retrieve those sixteen bits is <a href="../../../reference/functions/hooks/spare_storage.html" class="api-reference"><code>uint16_t spare_storage(const basic_result|basic_outcome *) noexcept</code></a>
.</p>
<p>The state of the sixteen bits of spare storage are ignored during comparison operations.</p>
<p>The sixteen bits of spare storage propagate during the following operations:</p>
<ol>
<li>Copy and move construction between <code>result</code>&rsquo;s.</li>
<li>Copy and move construction between <code>outcome</code>&rsquo;s.</li>
<li>Copy and move construction from a <code>result</code> to an <code>outcome</code>.</li>
<li>Converting copy and move constructions for all the above.</li>
<li>Assignment for all of the above.</li>
</ol>
<p>They are NOT propagated in these operations:</p>
<ol>
<li>Any conversion or translation which goes through a <code>failure_type</code> or <code>success_type</code>.</li>
<li>Any conversion or translation which goes through a <code>ValueOrError</code> concept match.</li>
<li>Any unpacking or repacking of value/error/exception e.g. a manual repack of an
<code>outcome</code> into a <code>result</code>.</li>
</ol>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/adl_bridging.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/poke_exception.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,78 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Keeping state - Boost.Outcome documentation</title>
<link rel="stylesheet" href="../../../css/boost.css" type="text/css">
<meta name="generator" content="Hugo 0.52 with Boostdoc theme">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
<body><div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/adl_bridging.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Keeping state</h1></div></div></div>
<p>The first thing we are going to need is somewhere to store the stack backtrace.
We could take the easier route and simply store it into an allocated block and
keep the pointer as a custom payload in a <code>result&lt;T, std::pair&lt;error_code, std::unique_ptr&lt;stack_backtrace&gt;&gt;&gt;</code>
(see previous section on <a href="../../payload">Custom payloads</a>). But let us assume that we care so deeply about bounded execution times
that ever calling <code>malloc</code> is unacceptable.</p>
<p>We therefore are going to need some completely static and trivially typed storage
perhaps kept per-thread to avoid the need to keep mutexes.</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="cm">/* Outcome&#39;s hook mechanism works vis ADL, so we will need a custom namespace
</span><span class="cm">to ensure the hooks apply only to the types declared in this namespace only
</span><span class="cm">*/</span>
<span class="k">namespace</span> <span class="n">error_code_extended</span>
<span class="p">{</span>
<span class="c1">// The extra error information we will keep
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">extended_error_info</span>
<span class="p">{</span>
<span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o">&lt;</span><span class="kt">void</span> <span class="o">*</span><span class="p">,</span> <span class="mi">16</span><span class="o">&gt;</span> <span class="n">backtrace</span><span class="p">;</span> <span class="c1">// The backtrace
</span><span class="c1"></span> <span class="n">size_t</span> <span class="n">items</span><span class="p">;</span> <span class="c1">// Items in backtrace array which are valid
</span><span class="c1"></span> <span class="p">};</span>
<span class="k">struct</span> <span class="n">mythreadlocaldata_t</span>
<span class="p">{</span>
<span class="c1">// Keep 16 slots of extended error info as a ringbuffer
</span><span class="c1"></span> <span class="n">extended_error_info</span> <span class="n">slots</span><span class="p">[</span><span class="mi">16</span><span class="p">];</span>
<span class="c1">// The current oldest slot
</span><span class="c1"></span> <span class="n">uint16_t</span> <span class="n">current</span><span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="c1">// Return the oldest slot
</span><span class="c1"></span> <span class="n">extended_error_info</span> <span class="o">&amp;</span><span class="n">next</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">slots</span><span class="p">[(</span><span class="n">current</span><span class="o">++</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16</span><span class="p">];</span> <span class="p">}</span>
<span class="c1">// Retrieve a previously stored slot, detecting if it is stale
</span><span class="c1"></span> <span class="n">extended_error_info</span> <span class="o">*</span><span class="n">get</span><span class="p">(</span><span class="n">uint16_t</span> <span class="n">idx</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// If the idx is stale, return not found
</span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">idx</span> <span class="o">-</span> <span class="n">current</span> <span class="o">&gt;=</span> <span class="mi">16</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">nullptr</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">slots</span> <span class="o">+</span> <span class="p">(</span><span class="n">idx</span> <span class="o">%</span> <span class="mi">16</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="c1">// Meyers&#39; singleton returning a thread local data structure for this thread
</span><span class="c1"></span> <span class="kr">inline</span> <span class="n">mythreadlocaldata_t</span> <span class="o">&amp;</span><span class="n">mythreadlocaldata</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">static</span> <span class="k">thread_local</span> <span class="n">mythreadlocaldata_t</span> <span class="n">v</span><span class="p">;</span>
<span class="k">return</span> <span class="n">v</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/error_code_extended.cpp#L52" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>The extended error info is kept in a sixteen item long, thread local, ring buffer. We continuously
increment the current index pointer which is a 16 bit value which will wrap after
65,535. This lets us detect an attempt to access recycled storage, and thus return
item-not-found instead of the wrong extended error info.</p>
</div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/adl_bridging.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,100 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Custom exception ptr - Boost.Outcome documentation</title>
<link rel="stylesheet" href="../../../css/boost.css" type="text/css">
<meta name="generator" content="Hugo 0.52 with Boostdoc theme">
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
<body><div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/hook_outcome.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Custom exception ptr</h1></div></div></div>
<p>If you merely want <code>result</code> to capture stack backtraces without calling a memory allocator
and retaining any triviality of copy which is important for optimisation,
you already have everything you need.</p>
<p>But let&rsquo;s keep going by intercepting any
construction of our localised <code>outcome</code> from our localised <code>result</code>, retrieving any
stored backtrace and using it to synthesise an exception ptr with a message text
including the backtrace. Firstly let us look at the function which synthesises
the exception ptr:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">error_code_extended</span>
<span class="p">{</span>
<span class="c1">// Synthesise a custom exception_ptr from the TLS slot and write it into the outcome
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">R</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="n">poke_exception</span><span class="p">(</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">R</span><span class="o">&gt;</span> <span class="o">*</span><span class="n">o</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">o</span><span class="o">-&gt;</span><span class="n">has_error</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">extended_error_info</span> <span class="o">*</span><span class="n">eei</span> <span class="o">=</span> <span class="n">mythreadlocaldata</span><span class="p">().</span><span class="n">get</span><span class="p">(</span><span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">hooks</span><span class="o">::</span><span class="n">spare_storage</span><span class="p">(</span><span class="n">o</span><span class="p">));</span>
<span class="k">if</span><span class="p">(</span><span class="n">eei</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Make a custom string for the exception
</span><span class="c1"></span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str</span><span class="p">(</span><span class="n">o</span><span class="o">-&gt;</span><span class="n">error</span><span class="p">().</span><span class="n">message</span><span class="p">());</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34; [&#34;</span><span class="p">);</span>
<span class="k">struct</span> <span class="n">unsymbols</span> <span class="c1">// RAII cleaner for symbols
</span><span class="c1"></span> <span class="p">{</span>
<span class="kt">char</span> <span class="o">**</span><span class="n">_</span><span class="p">{</span><span class="k">nullptr</span><span class="p">};</span>
<span class="o">~</span><span class="n">unsymbols</span><span class="p">()</span> <span class="p">{</span> <span class="o">::</span><span class="n">free</span><span class="p">(</span><span class="n">_</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span> <span class="n">symbols</span><span class="p">{</span><span class="o">::</span><span class="n">backtrace_symbols</span><span class="p">(</span><span class="n">eei</span><span class="o">-&gt;</span><span class="n">backtrace</span><span class="p">.</span><span class="n">data</span><span class="p">(),</span> <span class="n">eei</span><span class="o">-&gt;</span><span class="n">items</span><span class="p">)};</span>
<span class="k">if</span><span class="p">(</span><span class="n">symbols</span><span class="p">.</span><span class="n">_</span> <span class="o">!=</span> <span class="k">nullptr</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="n">size_t</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="n">eei</span><span class="o">-&gt;</span><span class="n">items</span><span class="p">;</span> <span class="n">n</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;; &#34;</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">symbols</span><span class="p">.</span><span class="n">_</span><span class="p">[</span><span class="n">n</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;]&#34;</span><span class="p">);</span>
<span class="c1">// Override the payload/exception member in the outcome with our synthesised exception ptr
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">hooks</span><span class="o">::</span><span class="n">override_outcome_exception</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">make_exception_ptr</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="n">str</span><span class="p">)));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/error_code_extended.cpp#L142" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>If the localised <code>outcome</code> being constructed is errored, try fetching the TLS slot
for the unique 16-bit value in its spare storage. If that is valid, symbolise the
stack backtrace into a string and make an exception ptr with a runtime error with
that string. Finally, override the payload/exception member in our just-copy-constructed
localised <code>outcome</code> with the new exception ptr.</p>
<hr>
<p>As the reference documentation for <a href="../../../reference/functions/hooks/override_outcome_exception.html" class="api-reference"><code>void override_outcome_exception(basic_outcome&lt;T, EC, EP, NoValuePolicy&gt; *, U &amp;&amp;) noexcept</code></a>
points out, you <em>almost certainly</em> never want to use this function if there is any
other alternative. It is worth explaining what is meant by this.</p>
<p>In this section, we <em>always</em> synthesise an exception ptr from the stored state and
error code at the exact point of transition from <code>result</code> based APIs to <code>outcome</code>
based APIs. This is acceptable only because we know that our code enforces that
discipline.</p>
<p>If one were designing a library facility, one could not assume such discipline in the
library user. One would probably be better off making the exception ptr synthesis
<em>lazy</em> via a custom no-value policy which generates the stacktrace-containing error
message only on demand e.g. <code>.exception()</code> observation, or a <code>.value()</code> observation
where no value is available.</p>
<p>Such a design is however more indeterminate than the design presented in this section,
because the indeterminacy is less predictable than in this design. Ultimately which
strategy you adopt depends on how important absolute determinism is to your Outcome-based
application.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
<a accesskey="h" href="../../../index.html"><img src="../../../images/home.png" alt="Home"></a><a accesskey="n" href="../../../tutorial/advanced/hooks/hook_outcome.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>