poke_exception.html 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  3. <title>Custom exception ptr - Boost.Outcome documentation</title>
  4. <link rel="stylesheet" href="../../../css/boost.css" type="text/css">
  5. <meta name="generator" content="Hugo 0.52 with Boostdoc theme">
  6. <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
  7. <link rel="icon" href="../../../images/favicon.ico" type="image/ico"/>
  8. <body><div class="spirit-nav">
  9. <a accesskey="p" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/prev.png" alt="Prev"></a>
  10. <a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
  11. <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">
  12. <div class="titlepage"><div><div><h1 style="clear: both">Custom exception ptr</h1></div></div></div>
  13. <p>If you merely want <code>result</code> to capture stack backtraces without calling a memory allocator
  14. and retaining any triviality of copy which is important for optimisation,
  15. you already have everything you need.</p>
  16. <p>But let&rsquo;s keep going by intercepting any
  17. construction of our localised <code>outcome</code> from our localised <code>result</code>, retrieving any
  18. stored backtrace and using it to synthesise an exception ptr with a message text
  19. including the backtrace. Firstly let us look at the function which synthesises
  20. the exception ptr:</p>
  21. <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>
  22. <span class="p">{</span>
  23. <span class="c1">// Synthesise a custom exception_ptr from the TLS slot and write it into the outcome
  24. </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>
  25. <span class="p">{</span>
  26. <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>
  27. <span class="p">{</span>
  28. <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>
  29. <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>
  30. <span class="p">{</span>
  31. <span class="c1">// Make a custom string for the exception
  32. </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>
  33. <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>
  34. <span class="k">struct</span> <span class="n">unsymbols</span> <span class="c1">// RAII cleaner for symbols
  35. </span><span class="c1"></span> <span class="p">{</span>
  36. <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>
  37. <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>
  38. <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>
  39. <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>
  40. <span class="p">{</span>
  41. <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>
  42. <span class="p">{</span>
  43. <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>
  44. <span class="p">{</span>
  45. <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>
  46. <span class="p">}</span>
  47. <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>
  48. <span class="p">}</span>
  49. <span class="p">}</span>
  50. <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>
  51. <span class="c1">// Override the payload/exception member in the outcome with our synthesised exception ptr
  52. </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>
  53. <span class="p">}</span>
  54. <span class="p">}</span>
  55. <span class="p">}</span>
  56. <span class="p">}</span>
  57. </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>
  58. <p>If the localised <code>outcome</code> being constructed is errored, try fetching the TLS slot
  59. for the unique 16-bit value in its spare storage. If that is valid, symbolise the
  60. stack backtrace into a string and make an exception ptr with a runtime error with
  61. that string. Finally, override the payload/exception member in our just-copy-constructed
  62. localised <code>outcome</code> with the new exception ptr.</p>
  63. <hr>
  64. <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>
  65. points out, you <em>almost certainly</em> never want to use this function if there is any
  66. other alternative. It is worth explaining what is meant by this.</p>
  67. <p>In this section, we <em>always</em> synthesise an exception ptr from the stored state and
  68. error code at the exact point of transition from <code>result</code> based APIs to <code>outcome</code>
  69. based APIs. This is acceptable only because we know that our code enforces that
  70. discipline.</p>
  71. <p>If one were designing a library facility, one could not assume such discipline in the
  72. library user. One would probably be better off making the exception ptr synthesis
  73. <em>lazy</em> via a custom no-value policy which generates the stacktrace-containing error
  74. message only on demand e.g. <code>.exception()</code> observation, or a <code>.value()</code> observation
  75. where no value is available.</p>
  76. <p>Such a design is however more indeterminate than the design presented in this section,
  77. because the indeterminacy is less predictable than in this design. Ultimately which
  78. strategy you adopt depends on how important absolute determinism is to your Outcome-based
  79. application.</p>
  80. </div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
  81. <hr>
  82. <div class="spirit-nav">
  83. <a accesskey="p" href="../../../tutorial/advanced/hooks/hook_result.html"><img src="../../../images/prev.png" alt="Prev"></a>
  84. <a accesskey="u" href="../../../tutorial/advanced/hooks.html"><img src="../../../images/up.png" alt="Up"></a>
  85. <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>
  86. </html>