Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // -*- C++ -*- Implement the members of exception_ptr.
  2. // Copyright (C) 2008-2013 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. std::__exception_ptr::exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
  39. : _M_exception_object(0) { }
  40.  
  41.  
  42. std::__exception_ptr::exception_ptr::exception_ptr(void* obj)
  43. _GLIBCXX_USE_NOEXCEPT
  44. : _M_exception_object(obj)  { _M_addref(); }
  45.  
  46.  
  47. std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool)
  48. _GLIBCXX_USE_NOEXCEPT
  49. : _M_exception_object(0) { }
  50.  
  51.  
  52. std::__exception_ptr::
  53. exception_ptr::exception_ptr(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
  54. : _M_exception_object(other._M_exception_object)
  55. { _M_addref(); }
  56.  
  57.  
  58. std::__exception_ptr::exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
  59. { _M_release(); }
  60.  
  61.  
  62. std::__exception_ptr::exception_ptr&
  63. std::__exception_ptr::
  64. exception_ptr::operator=(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT
  65. {
  66.   exception_ptr(other).swap(*this);
  67.   return *this;
  68. }
  69.  
  70.  
  71. void
  72. std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT
  73. {
  74.   if (_M_exception_object)
  75.     {
  76.       __cxa_refcounted_exception *eh =
  77.         __get_refcounted_exception_header_from_obj (_M_exception_object);
  78.       __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
  79.     }
  80. }
  81.  
  82.  
  83. void
  84. std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT
  85. {
  86.   if (_M_exception_object)
  87.     {
  88.       __cxa_refcounted_exception *eh =
  89.         __get_refcounted_exception_header_from_obj (_M_exception_object);
  90.       if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
  91.         {
  92.           if (eh->exc.exceptionDestructor)
  93.             eh->exc.exceptionDestructor (_M_exception_object);
  94.  
  95.           __cxa_free_exception (_M_exception_object);
  96.           _M_exception_object = 0;
  97.         }
  98.     }
  99. }
  100.  
  101.  
  102. void*
  103. std::__exception_ptr::exception_ptr::_M_get() const _GLIBCXX_USE_NOEXCEPT
  104. { return _M_exception_object; }
  105.  
  106.  
  107. void
  108. std::__exception_ptr::exception_ptr::swap(exception_ptr &other)
  109.   _GLIBCXX_USE_NOEXCEPT
  110. {
  111.   void *tmp = _M_exception_object;
  112.   _M_exception_object = other._M_exception_object;
  113.   other._M_exception_object = tmp;
  114. }
  115.  
  116.  
  117. // Retained for compatibility with CXXABI_1.3.
  118. void
  119. std::__exception_ptr::exception_ptr::_M_safe_bool_dummy()
  120.   _GLIBCXX_USE_NOEXCEPT { }
  121.  
  122.  
  123. // Retained for compatibility with CXXABI_1.3.
  124. bool
  125. std::__exception_ptr::exception_ptr::operator!() const _GLIBCXX_USE_NOEXCEPT
  126. { return _M_exception_object == 0; }
  127.  
  128.  
  129. // Retained for compatibility with CXXABI_1.3.
  130. std::__exception_ptr::exception_ptr::operator __safe_bool() const
  131. _GLIBCXX_USE_NOEXCEPT
  132. {
  133.   return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
  134. }
  135.  
  136.  
  137. const std::type_info*
  138. std::__exception_ptr::exception_ptr::__cxa_exception_type() const
  139.   _GLIBCXX_USE_NOEXCEPT
  140. {
  141.   __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
  142.   return eh->exceptionType;
  143. }
  144.  
  145.  
  146. bool std::__exception_ptr::operator==(const exception_ptr& lhs,
  147.                                       const exception_ptr& rhs)
  148.   _GLIBCXX_USE_NOEXCEPT
  149. { return lhs._M_exception_object == rhs._M_exception_object; }
  150.  
  151.  
  152. bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
  153.                                       const exception_ptr& rhs)
  154.   _GLIBCXX_USE_NOEXCEPT
  155. { return !(lhs == rhs);}
  156.  
  157.  
  158. std::exception_ptr
  159. std::current_exception() _GLIBCXX_USE_NOEXCEPT
  160. {
  161.   __cxa_eh_globals *globals = __cxa_get_globals ();
  162.   __cxa_exception *header = globals->caughtExceptions;
  163.  
  164.   if (!header)
  165.     return std::exception_ptr();
  166.  
  167.   // Since foreign exceptions can't be counted, we can't return them.
  168.   if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
  169.     return std::exception_ptr();
  170.  
  171.   return std::exception_ptr(
  172.     __get_object_from_ambiguous_exception (header));
  173. }
  174.  
  175.  
  176. static void
  177. __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code,
  178.                                   _Unwind_Exception *exc)
  179. {
  180.   // This cleanup is set only for dependents.
  181.   __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
  182.   __cxa_refcounted_exception *header =
  183.     __get_refcounted_exception_header_from_obj (dep->primaryException);
  184.  
  185.   // We only want to be called through _Unwind_DeleteException.
  186.   // _Unwind_DeleteException in the HP-UX IA64 libunwind library
  187.   // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
  188.   // like the GCC _Unwind_DeleteException function does.
  189.   if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
  190.     __terminate (header->exc.terminateHandler);
  191.  
  192.   __cxa_free_dependent_exception (dep);
  193.  
  194.   if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
  195.     {
  196.       if (header->exc.exceptionDestructor)
  197.         header->exc.exceptionDestructor (header + 1);
  198.  
  199.       __cxa_free_exception (header + 1);
  200.     }
  201. }
  202.  
  203.  
  204. void
  205. std::rethrow_exception(std::exception_ptr ep)
  206. {
  207.   void *obj = ep._M_get();
  208.   __cxa_refcounted_exception *eh
  209.     = __get_refcounted_exception_header_from_obj (obj);
  210.  
  211.   __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
  212.   dep->primaryException = obj;
  213.   __atomic_add_fetch (&eh->referenceCount, 1,  __ATOMIC_ACQ_REL);
  214.  
  215.   dep->unexpectedHandler = __unexpected_handler;
  216.   dep->terminateHandler = __terminate_handler;
  217.   __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
  218.   dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
  219.  
  220. #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
  221.   _Unwind_SjLj_RaiseException (&dep->unwindHeader);
  222. #else
  223.   _Unwind_RaiseException (&dep->unwindHeader);
  224. #endif
  225.  
  226.   // Some sort of unwinding error.  Note that terminate is a handler.
  227.   __cxa_begin_catch (&dep->unwindHeader);
  228.   std::terminate();
  229. }
  230.  
  231. #undef _GLIBCXX_EH_PTR_COMPAT
  232.  
  233. #endif
  234.