Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*- Implement the members of exception_ptr.
  2. // Copyright (C) 2008-2015 Free Software Foundation, Inc.
  3. //
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10. //
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <bits/c++config.h>
  26. #include <bits/atomic_lockfree_defines.h>
  27.  
  28. #if ATOMIC_INT_LOCK_FREE > 1
  29.  
  30. #define _GLIBCXX_EH_PTR_COMPAT
  31.  
  32. #include <exception>
  33. #include <bits/exception_ptr.h>
  34. #include "unwind-cxx.h"
  35.  
  36. using namespace __cxxabiv1;
  37.  
  38. // Verify assumptions about member layout in exception types
  39. namespace
  40. {
  41. template<typename Ex>
  42.   constexpr std::size_t unwindhdr()
  43.   { return offsetof(Ex, unwindHeader); }
  44.  
  45. template<typename Ex>
  46.   constexpr std::size_t termHandler()
  47.   { return unwindhdr<Ex>() - offsetof(Ex, terminateHandler); }
  48.  
  49. static_assert( termHandler<__cxa_exception>()
  50.                == termHandler<__cxa_dependent_exception>(),
  51.                "__cxa_dependent_exception::termHandler layout must be"
  52.                " consistent with __cxa_exception::termHandler" );
  53.  
  54. #ifndef __ARM_EABI_UNWINDER__
  55. template<typename Ex>
  56.   constexpr std::ptrdiff_t adjptr()
  57.   { return unwindhdr<Ex>() - offsetof(Ex, adjustedPtr); }
  58.  
  59. static_assert( adjptr<__cxa_exception>()
  60.                == adjptr<__cxa_dependent_exception>(),
  61.                "__cxa_dependent_exception::adjustedPtr layout must be"
  62.                " consistent with __cxa_exception::adjustedPtr" );
  63. #endif
  64. }
  65.  
  66. std::__exception_ptr::exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
  67. : _M_exception_object(0) { }
  68.  
  69.  
  70. std::__exception_ptr::exception_ptr::exception_ptr(void* obj)
  71. _GLIBCXX_USE_NOEXCEPT
  72. : _M_exception_object(obj)  { _M_addref(); }
  73.  
  74.  
  75. std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool)
  76. _GLIBCXX_USE_NOEXCEPT
  77. : _M_exception_object(0) { }
  78.  
  79.  
  80. std::__exception_ptr::
  81. exception_ptr::exception_ptr(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
  82. : _M_exception_object(other._M_exception_object)
  83. { _M_addref(); }
  84.  
  85.  
  86. std::__exception_ptr::exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
  87. { _M_release(); }
  88.  
  89.  
  90. std::__exception_ptr::exception_ptr&
  91. std::__exception_ptr::
  92. exception_ptr::operator=(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
  93. {
  94.   exception_ptr(other).swap(*this);
  95.   return *this;
  96. }
  97.  
  98.  
  99. void
  100. std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT
  101. {
  102.   if (_M_exception_object)
  103.     {
  104.       __cxa_refcounted_exception *eh =
  105.         __get_refcounted_exception_header_from_obj (_M_exception_object);
  106.       __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
  107.     }
  108. }
  109.  
  110.  
  111. void
  112. std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT
  113. {
  114.   if (_M_exception_object)
  115.     {
  116.       __cxa_refcounted_exception *eh =
  117.         __get_refcounted_exception_header_from_obj (_M_exception_object);
  118.       if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
  119.         {
  120.           if (eh->exc.exceptionDestructor)
  121.             eh->exc.exceptionDestructor (_M_exception_object);
  122.  
  123.           __cxa_free_exception (_M_exception_object);
  124.           _M_exception_object = 0;
  125.         }
  126.     }
  127. }
  128.  
  129.  
  130. void*
  131. std::__exception_ptr::exception_ptr::_M_get() const _GLIBCXX_USE_NOEXCEPT
  132. { return _M_exception_object; }
  133.  
  134.  
  135. void
  136. std::__exception_ptr::exception_ptr::swap(exception_ptr &other)
  137.   _GLIBCXX_USE_NOEXCEPT
  138. {
  139.   void *tmp = _M_exception_object;
  140.   _M_exception_object = other._M_exception_object;
  141.   other._M_exception_object = tmp;
  142. }
  143.  
  144.  
  145. // Retained for compatibility with CXXABI_1.3.
  146. void
  147. std::__exception_ptr::exception_ptr::_M_safe_bool_dummy()
  148.   _GLIBCXX_USE_NOEXCEPT { }
  149.  
  150.  
  151. // Retained for compatibility with CXXABI_1.3.
  152. bool
  153. std::__exception_ptr::exception_ptr::operator!() const _GLIBCXX_USE_NOEXCEPT
  154. { return _M_exception_object == 0; }
  155.  
  156.  
  157. // Retained for compatibility with CXXABI_1.3.
  158. std::__exception_ptr::exception_ptr::operator __safe_bool() const
  159. _GLIBCXX_USE_NOEXCEPT
  160. {
  161.   return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
  162. }
  163.  
  164.  
  165. const std::type_info*
  166. std::__exception_ptr::exception_ptr::__cxa_exception_type() const
  167.   _GLIBCXX_USE_NOEXCEPT
  168. {
  169.   __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
  170.   return eh->exceptionType;
  171. }
  172.  
  173.  
  174. bool std::__exception_ptr::operator==(const exception_ptr& lhs,
  175.                                       const exception_ptr& rhs)
  176.   _GLIBCXX_USE_NOEXCEPT
  177. { return lhs._M_exception_object == rhs._M_exception_object; }
  178.  
  179.  
  180. bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
  181.                                       const exception_ptr& rhs)
  182.   _GLIBCXX_USE_NOEXCEPT
  183. { return !(lhs == rhs);}
  184.  
  185.  
  186. std::exception_ptr
  187. std::current_exception() _GLIBCXX_USE_NOEXCEPT
  188. {
  189.   __cxa_eh_globals *globals = __cxa_get_globals ();
  190.   __cxa_exception *header = globals->caughtExceptions;
  191.  
  192.   if (!header)
  193.     return std::exception_ptr();
  194.  
  195.   // Since foreign exceptions can't be counted, we can't return them.
  196.   if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
  197.     return std::exception_ptr();
  198.  
  199.   return std::exception_ptr(
  200.     __get_object_from_ambiguous_exception (header));
  201. }
  202.  
  203.  
  204. static void
  205. __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code,
  206.                                   _Unwind_Exception *exc)
  207. {
  208.   // This cleanup is set only for dependents.
  209.   __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
  210.   __cxa_refcounted_exception *header =
  211.     __get_refcounted_exception_header_from_obj (dep->primaryException);
  212.  
  213.   // We only want to be called through _Unwind_DeleteException.
  214.   // _Unwind_DeleteException in the HP-UX IA64 libunwind library
  215.   // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
  216.   // like the GCC _Unwind_DeleteException function does.
  217.   if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
  218.     __terminate (header->exc.terminateHandler);
  219.  
  220.   __cxa_free_dependent_exception (dep);
  221.  
  222.   if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
  223.     {
  224.       if (header->exc.exceptionDestructor)
  225.         header->exc.exceptionDestructor (header + 1);
  226.  
  227.       __cxa_free_exception (header + 1);
  228.     }
  229. }
  230.  
  231.  
  232. void
  233. std::rethrow_exception(std::exception_ptr ep)
  234. {
  235.   void *obj = ep._M_get();
  236.   __cxa_refcounted_exception *eh
  237.     = __get_refcounted_exception_header_from_obj (obj);
  238.  
  239.   __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
  240.   dep->primaryException = obj;
  241.   __atomic_add_fetch (&eh->referenceCount, 1,  __ATOMIC_ACQ_REL);
  242.  
  243.   dep->unexpectedHandler = get_unexpected ();
  244.   dep->terminateHandler = get_terminate ();
  245.   __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
  246.   dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
  247.  
  248.   __cxa_eh_globals *globals = __cxa_get_globals ();
  249.   globals->uncaughtExceptions += 1;
  250.  
  251. #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
  252.   _Unwind_SjLj_RaiseException (&dep->unwindHeader);
  253. #else
  254.   _Unwind_RaiseException (&dep->unwindHeader);
  255. #endif
  256.  
  257.   // Some sort of unwinding error.  Note that terminate is a handler.
  258.   __cxa_begin_catch (&dep->unwindHeader);
  259.   std::terminate();
  260. }
  261.  
  262. #undef _GLIBCXX_EH_PTR_COMPAT
  263.  
  264. #endif
  265.