1 #ifndef BOOST_LEAF_ERROR_HPP_INCLUDED 2 #define BOOST_LEAF_ERROR_HPP_INCLUDED 3 4 // Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc. 5 6 // Distributed under the Boost Software License, Version 1.0. (See accompanying 7 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_LEAF_ENABLE_WARNINGS 10 # if defined(__clang__) 11 # pragma clang system_header 12 # elif (__GNUC__*100+__GNUC_MINOR__>301) 13 # pragma GCC system_header 14 # elif defined(_MSC_VER) 15 # pragma warning(push,1) 16 # endif 17 #endif 18 19 #include <boost/leaf/detail/function_traits.hpp> 20 #include <boost/leaf/detail/print.hpp> 21 #include <system_error> 22 #include <type_traits> 23 #include <memory> 24 #include <string> 25 26 #if BOOST_LEAF_DIAGNOSTICS 27 # include <sstream> 28 # include <set> 29 #endif 30 31 #define BOOST_LEAF_TOKEN_PASTE(x, y) x ## y 32 #define BOOST_LEAF_TOKEN_PASTE2(x, y) BOOST_LEAF_TOKEN_PASTE(x, y) 33 #define BOOST_LEAF_TMP BOOST_LEAF_TOKEN_PASTE2(boost_leaf_tmp_, __LINE__) 34 35 #define BOOST_LEAF_ASSIGN(v,r)\ 36 static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(r)>::type>::value, "The BOOST_LEAF_ASSIGN macro requires a result type as the second argument");\ 37 auto && BOOST_LEAF_TMP = r;\ 38 if( !BOOST_LEAF_TMP )\ 39 return BOOST_LEAF_TMP.error();\ 40 v = std::forward<decltype(BOOST_LEAF_TMP)>(BOOST_LEAF_TMP).value() 41 42 #define BOOST_LEAF_AUTO(v, r)\ 43 BOOST_LEAF_ASSIGN(auto v, r) 44 45 #define BOOST_LEAF_CHECK(r)\ 46 {\ 47 static_assert(::boost::leaf::is_result_type<typename std::decay<decltype(r)>::type>::value, "BOOST_LEAF_CHECK requires a result type");\ 48 auto && BOOST_LEAF_TMP = r;\ 49 if( !BOOST_LEAF_TMP )\ 50 return BOOST_LEAF_TMP.error();\ 51 } 52 53 #define BOOST_LEAF_NEW_ERROR ::leaf::leaf_detail::inject_loc{__FILE__,__LINE__,__FUNCTION__}+::boost::leaf::new_error 54 55 namespace boost { namespace leaf { 56 57 namespace leaf_detail 58 { 59 struct inject_loc 60 { 61 char const * const file; 62 int const line; 63 char const * const fn; 64 65 template <class T> operator +(inject_loc loc,T && x)66 friend T operator+( inject_loc loc, T && x ) noexcept 67 { 68 x.load_source_location_(loc.file, loc.line, loc.fn); 69 return std::move(x); 70 } 71 }; 72 } 73 74 } } 75 76 //////////////////////////////////////// 77 78 #ifdef BOOST_LEAF_NO_EXCEPTIONS 79 80 namespace boost 81 { 82 BOOST_LEAF_NORETURN void throw_exception( std::exception const & ); // user defined 83 } 84 85 namespace boost { namespace leaf { 86 87 template <class T> throw_exception(T const & e)88 BOOST_LEAF_NORETURN void throw_exception( T const & e ) 89 { 90 ::boost::throw_exception(e); 91 } 92 93 } } 94 95 #else 96 97 namespace boost { namespace leaf { 98 99 template <class T> throw_exception(T const & e)100 BOOST_LEAF_NORETURN void throw_exception( T const & e ) 101 { 102 throw e; 103 } 104 105 } } 106 107 #endif 108 109 //////////////////////////////////////// 110 111 #ifdef BOOST_LEAF_NO_THREADS 112 113 # define BOOST_LEAF_THREAD_LOCAL 114 namespace boost { namespace leaf { 115 namespace leaf_detail 116 { 117 using atomic_unsigned_int = unsigned int; 118 } 119 } } 120 121 #else 122 123 # include <atomic> 124 # include <thread> 125 # define BOOST_LEAF_THREAD_LOCAL thread_local 126 namespace boost { namespace leaf { 127 namespace leaf_detail 128 { 129 using atomic_unsigned_int = std::atomic<unsigned int>; 130 } 131 } } 132 133 #endif 134 135 //////////////////////////////////////// 136 137 namespace boost { namespace leaf { 138 139 #if BOOST_LEAF_DIAGNOSTICS 140 141 namespace leaf_detail 142 { 143 class e_unexpected_count 144 { 145 public: 146 147 char const * (*first_type)(); 148 int count; 149 e_unexpected_count(char const * (* first_type)())150 BOOST_LEAF_CONSTEXPR explicit e_unexpected_count(char const * (*first_type)()) noexcept: 151 first_type(first_type), 152 count(1) 153 { 154 } 155 156 template <class CharT, class Traits> print(std::basic_ostream<CharT,Traits> & os) const157 void print( std::basic_ostream<CharT, Traits> & os ) const 158 { 159 BOOST_LEAF_ASSERT(first_type != 0); 160 BOOST_LEAF_ASSERT(count>0); 161 os << "Detected "; 162 if( count==1 ) 163 os << "1 attempt to communicate an unexpected error object"; 164 else 165 os << count << " attempts to communicate unexpected error objects, the first one"; 166 (os << " of type " << first_type() << '\n').flush(); 167 } 168 }; 169 170 template <> 171 struct diagnostic<e_unexpected_count, false, false> 172 { 173 static constexpr bool is_invisible = true; printboost::leaf::leaf_detail::diagnostic174 BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_count const &) noexcept { } 175 }; 176 177 class e_unexpected_info 178 { 179 std::string s_; 180 std::set<char const *(*)()> already_; 181 182 public: 183 e_unexpected_info()184 e_unexpected_info() noexcept 185 { 186 } 187 188 template <class E> add(E && e)189 void add(E && e) 190 { 191 if( !diagnostic<E>::is_invisible && already_.insert(&type<E>).second ) 192 { 193 std::stringstream s; 194 diagnostic<E>::print(s,e); 195 (s << '\n').flush(); 196 s_ += s.str(); 197 } 198 } 199 200 template <class CharT, class Traits> print(std::basic_ostream<CharT,Traits> & os) const201 void print( std::basic_ostream<CharT, Traits> & os ) const 202 { 203 os << "Unhandled error objects:\n" << s_; 204 } 205 }; 206 207 template <> 208 struct diagnostic<e_unexpected_info, false, false> 209 { 210 static constexpr bool is_invisible = true; printboost::leaf::leaf_detail::diagnostic211 BOOST_LEAF_CONSTEXPR static void print(std::ostream &, e_unexpected_info const &) noexcept { } 212 }; 213 214 template <class=void> 215 struct tl_unexpected_enabled 216 { 217 static BOOST_LEAF_THREAD_LOCAL int counter; 218 }; 219 220 template <class T> 221 BOOST_LEAF_THREAD_LOCAL int tl_unexpected_enabled<T>::counter; 222 } 223 224 #endif 225 226 } } 227 228 //////////////////////////////////////// 229 230 namespace boost { namespace leaf { 231 232 struct e_source_location 233 { 234 char const * const file; 235 int const line; 236 char const * const function; 237 238 template <class CharT, class Traits> operator <<(std::basic_ostream<CharT,Traits> & os,e_source_location const & x)239 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, e_source_location const & x ) 240 { 241 return os << leaf::type<e_source_location>() << ": " << x.file << '(' << x.line << ") in function " << x.function; 242 } 243 }; 244 245 //////////////////////////////////////// 246 247 namespace leaf_detail 248 { 249 template <class E> 250 class slot; 251 252 template <class E> 253 struct tl_slot_ptr 254 { 255 static BOOST_LEAF_THREAD_LOCAL slot<E> * p; 256 }; 257 258 template <class E> 259 BOOST_LEAF_THREAD_LOCAL slot<E> * tl_slot_ptr<E>::p; 260 261 template <class E> 262 class slot: 263 optional<E> 264 { 265 slot( slot const & ) = delete; 266 slot & operator=( slot const & ) = delete; 267 268 using impl = optional<E>; 269 slot<E> * * top_; 270 slot<E> * prev_; 271 272 public: 273 slot()274 BOOST_LEAF_CONSTEXPR slot() noexcept: 275 top_(0) 276 { 277 } 278 slot(slot && x)279 BOOST_LEAF_CONSTEXPR slot( slot && x ) noexcept: 280 optional<E>(std::move(x)), 281 top_(0) 282 { 283 BOOST_LEAF_ASSERT(x.top_==0); 284 } 285 activate()286 BOOST_LEAF_CONSTEXPR void activate() noexcept 287 { 288 BOOST_LEAF_ASSERT(top_==0 || *top_!=this); 289 top_ = &tl_slot_ptr<E>::p; 290 prev_ = *top_; 291 *top_ = this; 292 } 293 deactivate()294 BOOST_LEAF_CONSTEXPR void deactivate() noexcept 295 { 296 BOOST_LEAF_ASSERT(top_!=0 && *top_==this); 297 *top_ = prev_; 298 } 299 300 BOOST_LEAF_CONSTEXPR void propagate() noexcept; 301 302 template <class CharT, class Traits> print(std::basic_ostream<CharT,Traits> & os,int key_to_print) const303 void print( std::basic_ostream<CharT, Traits> & os, int key_to_print ) const 304 { 305 if( !diagnostic<E>::is_invisible ) 306 if( int k = this->key() ) 307 { 308 if( key_to_print ) 309 { 310 if( key_to_print!=k ) 311 return; 312 } 313 else 314 os << '[' << k << ']'; 315 diagnostic<E>::print(os, value(k)); 316 (os << '\n').flush(); 317 } 318 } 319 320 using impl::put; 321 using impl::has_value; 322 using impl::value; 323 }; 324 325 #if BOOST_LEAF_DIAGNOSTICS 326 327 template <class E> load_unexpected_count(int err_id)328 BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept 329 { 330 if( slot<e_unexpected_count> * sl = tl_slot_ptr<e_unexpected_count>::p ) 331 if( e_unexpected_count * unx = sl->has_value(err_id) ) 332 ++unx->count; 333 else 334 sl->put(err_id, e_unexpected_count(&type<E>)); 335 } 336 337 template <class E> load_unexpected_info(int err_id,E && e)338 BOOST_LEAF_CONSTEXPR inline void load_unexpected_info( int err_id, E && e ) noexcept 339 { 340 if( slot<e_unexpected_info> * sl = tl_slot_ptr<e_unexpected_info>::p ) 341 if( e_unexpected_info * unx = sl->has_value(err_id) ) 342 unx->add(std::forward<E>(e)); 343 else 344 sl->put(err_id, e_unexpected_info()).add(std::forward<E>(e)); 345 } 346 347 template <class E> load_unexpected(int err_id,E && e)348 BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept 349 { 350 load_unexpected_count<E>(err_id); 351 load_unexpected_info(err_id, std::forward<E>(e)); 352 } 353 354 #endif 355 356 template <class E> propagate()357 BOOST_LEAF_CONSTEXPR inline void slot<E>::propagate() noexcept 358 { 359 BOOST_LEAF_ASSERT(top_!=0 && (*top_==prev_ || *top_==this)); 360 if( prev_ ) 361 { 362 impl & that_ = *prev_; 363 if( that_.empty() ) 364 { 365 impl & this_ = *this; 366 that_ = std::move(this_); 367 } 368 } 369 #if BOOST_LEAF_DIAGNOSTICS 370 else 371 { 372 int c = tl_unexpected_enabled<>::counter; 373 BOOST_LEAF_ASSERT(c>=0); 374 if( c ) 375 if( int err_id = impl::key() ) 376 load_unexpected(err_id, std::move(*this).value(err_id)); 377 } 378 #endif 379 } 380 381 template <class E> load_slot(int err_id,E && e)382 BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept 383 { 384 static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed"); 385 using T = typename std::decay<E>::type; 386 BOOST_LEAF_ASSERT((err_id&3)==1); 387 if( slot<T> * p = tl_slot_ptr<T>::p ) 388 (void) p->put(err_id, std::forward<E>(e)); 389 #if BOOST_LEAF_DIAGNOSTICS 390 else 391 { 392 int c = tl_unexpected_enabled<>::counter; 393 BOOST_LEAF_ASSERT(c>=0); 394 if( c ) 395 load_unexpected(err_id, std::forward<E>(e)); 396 } 397 #endif 398 return 0; 399 } 400 401 template <class F> accumulate_slot(int err_id,F && f)402 BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept 403 { 404 static_assert(function_traits<F>::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference"); 405 using E = typename std::decay<fn_arg_type<F,0>>::type; 406 static_assert(!std::is_pointer<E>::value, "Error objects of pointer types are not allowed"); 407 BOOST_LEAF_ASSERT((err_id&3)==1); 408 if( auto sl = tl_slot_ptr<E>::p ) 409 if( auto v = sl->has_value(err_id) ) 410 (void) std::forward<F>(f)(*v); 411 else 412 (void) std::forward<F>(f)(sl->put(err_id,E())); 413 return 0; 414 } 415 } 416 417 //////////////////////////////////////// 418 419 namespace leaf_detail 420 { 421 template <class=void> 422 struct id_factory 423 { 424 static atomic_unsigned_int counter; 425 static BOOST_LEAF_THREAD_LOCAL unsigned current_id; 426 generate_next_idboost::leaf::leaf_detail::id_factory427 BOOST_LEAF_CONSTEXPR static unsigned generate_next_id() noexcept 428 { 429 auto id = (counter+=4); 430 BOOST_LEAF_ASSERT((id&3)==1); 431 return id; 432 } 433 }; 434 435 template <class T> 436 atomic_unsigned_int id_factory<T>::counter(-3); 437 438 template <class T> 439 BOOST_LEAF_THREAD_LOCAL unsigned id_factory<T>::current_id(0); 440 current_id()441 inline int current_id() noexcept 442 { 443 auto id = id_factory<>::current_id; 444 BOOST_LEAF_ASSERT(id==0 || (id&3)==1); 445 return id; 446 } 447 new_id()448 inline int new_id() noexcept 449 { 450 auto id = id_factory<>::generate_next_id(); 451 return id_factory<>::current_id = id; 452 } 453 } 454 455 //////////////////////////////////////// 456 457 namespace leaf_detail 458 { 459 template <class T, int Arity = function_traits<T>::arity> 460 struct load_item 461 { 462 static_assert(Arity==0 || Arity==1, "If a functions is passed to new_error or load, it must take zero or one argument"); 463 }; 464 465 template <class E> 466 struct load_item<E, -1> 467 { loadboost::leaf::leaf_detail::load_item468 BOOST_LEAF_CONSTEXPR static int load( int err_id, E && e ) noexcept 469 { 470 return load_slot(err_id, std::forward<E>(e)); 471 } 472 }; 473 474 template <class F> 475 struct load_item<F, 0> 476 { loadboost::leaf::leaf_detail::load_item477 BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept 478 { 479 return load_slot(err_id, std::forward<F>(f)()); 480 } 481 }; 482 483 template <class F> 484 struct load_item<F, 1> 485 { loadboost::leaf::leaf_detail::load_item486 BOOST_LEAF_CONSTEXPR static int load( int err_id, F && f ) noexcept 487 { 488 return accumulate_slot(err_id, std::forward<F>(f)); 489 } 490 }; 491 } 492 493 //////////////////////////////////////// 494 495 namespace leaf_detail 496 { 497 class leaf_category final: public std::error_category 498 { equivalent(int,std::error_condition const &) const499 bool equivalent( int, std::error_condition const & ) const noexcept final override { return false; } equivalent(std::error_code const &,int) const500 bool equivalent( std::error_code const &, int ) const noexcept final override { return false; } name() const501 char const * name() const noexcept final override { return "LEAF error"; } message(int condition) const502 std::string message( int condition ) const final override { return name(); } 503 public: ~leaf_category()504 ~leaf_category() noexcept final override { } 505 }; 506 507 template <class=void> 508 struct get_error_category 509 { 510 static leaf_category cat; 511 }; 512 513 template <class T> 514 leaf_category get_error_category<T>::cat; 515 import_error_code(std::error_code const & ec)516 inline int import_error_code( std::error_code const & ec ) noexcept 517 { 518 if( int err_id = ec.value() ) 519 { 520 std::error_category const & cat = get_error_category<>::cat; 521 if( &ec.category()==&cat ) 522 { 523 BOOST_LEAF_ASSERT((err_id&3)==1); 524 return (err_id&~3)|1; 525 } 526 else 527 { 528 err_id = new_id(); 529 (void) load_slot(err_id, ec); 530 return (err_id&~3)|1; 531 } 532 } 533 else 534 return 0; 535 } 536 } 537 is_error_id(std::error_code const & ec)538 inline bool is_error_id( std::error_code const & ec ) noexcept 539 { 540 bool res = (&ec.category() == &leaf_detail::get_error_category<>::cat); 541 BOOST_LEAF_ASSERT(!res || !ec.value() || ((ec.value()&3)==1)); 542 return res; 543 } 544 545 //////////////////////////////////////// 546 547 class error_id; 548 549 namespace leaf_detail 550 { 551 BOOST_LEAF_CONSTEXPR error_id make_error_id(int) noexcept; 552 } 553 554 class error_id 555 { 556 friend error_id BOOST_LEAF_CONSTEXPR leaf_detail::make_error_id(int) noexcept; 557 558 int value_; 559 error_id(int value)560 BOOST_LEAF_CONSTEXPR explicit error_id( int value ) noexcept: 561 value_(value) 562 { 563 BOOST_LEAF_ASSERT(value_==0 || ((value_&3)==1)); 564 } 565 566 public: 567 error_id()568 BOOST_LEAF_CONSTEXPR error_id() noexcept: 569 value_(0) 570 { 571 } 572 error_id(std::error_code const & ec)573 error_id( std::error_code const & ec ) noexcept: 574 value_(leaf_detail::import_error_code(ec)) 575 { 576 BOOST_LEAF_ASSERT(!value_ || ((value_&3)==1)); 577 } 578 579 template <class Enum> error_id(Enum e,typename std::enable_if<std::is_error_code_enum<Enum>::value,Enum>::type * =0)580 error_id( Enum e, typename std::enable_if<std::is_error_code_enum<Enum>::value, Enum>::type * = 0 ) noexcept: 581 value_(leaf_detail::import_error_code(e)) 582 { 583 } 584 load() const585 BOOST_LEAF_CONSTEXPR error_id load() const noexcept 586 { 587 return *this; 588 } 589 590 template <class... Item> load(Item &&...item) const591 BOOST_LEAF_CONSTEXPR error_id load( Item && ... item ) const noexcept 592 { 593 if( int err_id = value() ) 594 { 595 int const unused[ ] = { 42, leaf_detail::load_item<Item>::load(err_id, std::forward<Item>(item))... }; 596 (void) unused; 597 } 598 return *this; 599 } 600 to_error_code() const601 std::error_code to_error_code() const noexcept 602 { 603 return std::error_code(value_, leaf_detail::get_error_category<>::cat); 604 } 605 value() const606 BOOST_LEAF_CONSTEXPR int value() const noexcept 607 { 608 if( int v = value_ ) 609 { 610 BOOST_LEAF_ASSERT((v&3)==1); 611 return (v&~3)|1; 612 } 613 else 614 return 0; 615 } 616 operator bool() const617 BOOST_LEAF_CONSTEXPR explicit operator bool() const noexcept 618 { 619 return value_ != 0; 620 } 621 operator ==(error_id a,error_id b)622 BOOST_LEAF_CONSTEXPR friend bool operator==( error_id a, error_id b ) noexcept 623 { 624 return a.value_ == b.value_; 625 } 626 operator !=(error_id a,error_id b)627 BOOST_LEAF_CONSTEXPR friend bool operator!=( error_id a, error_id b ) noexcept 628 { 629 return !(a == b); 630 } 631 operator <(error_id a,error_id b)632 BOOST_LEAF_CONSTEXPR friend bool operator<( error_id a, error_id b ) noexcept 633 { 634 return a.value_ < b.value_; 635 } 636 637 template <class CharT, class Traits> operator <<(std::basic_ostream<CharT,Traits> & os,error_id x)638 friend std::basic_ostream<CharT, Traits> & operator<<( std::basic_ostream<CharT, Traits> & os, error_id x ) 639 { 640 return os << x.value_; 641 } 642 load_source_location_(char const * file,int line,char const * function) const643 BOOST_LEAF_CONSTEXPR void load_source_location_( char const * file, int line, char const * function ) const noexcept 644 { 645 BOOST_LEAF_ASSERT(file&&*file); 646 BOOST_LEAF_ASSERT(line>0); 647 BOOST_LEAF_ASSERT(function&&*function); 648 BOOST_LEAF_ASSERT(value_); 649 (void) load(e_source_location {file,line,function}); 650 } 651 }; 652 653 namespace leaf_detail 654 { make_error_id(int err_id)655 BOOST_LEAF_CONSTEXPR inline error_id make_error_id( int err_id ) noexcept 656 { 657 BOOST_LEAF_ASSERT(err_id==0 || (err_id&3)==1); 658 return error_id((err_id&~3)|1); 659 } 660 } 661 new_error()662 inline error_id new_error() noexcept 663 { 664 return leaf_detail::make_error_id(leaf_detail::new_id()); 665 } 666 667 template <class... Item> new_error(Item &&...item)668 inline error_id new_error( Item && ... item ) noexcept 669 { 670 return leaf_detail::make_error_id(leaf_detail::new_id()).load(std::forward<Item>(item)...); 671 } 672 current_error()673 inline error_id current_error() noexcept 674 { 675 return leaf_detail::make_error_id(leaf_detail::current_id()); 676 } 677 678 //////////////////////////////////////////// 679 680 class polymorphic_context 681 { 682 protected: 683 684 polymorphic_context() noexcept = default; 685 ~polymorphic_context() noexcept = default; 686 687 public: 688 689 virtual error_id propagate_captured_errors() noexcept = 0; 690 virtual void activate() noexcept = 0; 691 virtual void deactivate() noexcept = 0; 692 virtual void propagate() noexcept = 0; 693 virtual bool is_active() const noexcept = 0; 694 virtual void print( std::ostream & ) const = 0; 695 error_id captured_id_; 696 }; 697 698 using context_ptr = std::shared_ptr<polymorphic_context>; 699 700 //////////////////////////////////////////// 701 702 template <class Ctx> 703 class context_activator 704 { 705 context_activator( context_activator const & ) = delete; 706 context_activator & operator=( context_activator const & ) = delete; 707 708 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 709 int const uncaught_exceptions_; 710 #endif 711 Ctx * ctx_; 712 713 public: 714 context_activator(Ctx & ctx)715 explicit BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept: 716 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 717 uncaught_exceptions_(std::uncaught_exceptions()), 718 #endif 719 ctx_(ctx.is_active() ? 0 : &ctx) 720 { 721 if( ctx_ ) 722 ctx_->activate(); 723 } 724 context_activator(context_activator && x)725 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept: 726 #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 727 uncaught_exceptions_(x.uncaught_exceptions_), 728 #endif 729 ctx_(x.ctx_) 730 { 731 x.ctx_ = 0; 732 } 733 ~context_activator()734 BOOST_LEAF_ALWAYS_INLINE ~context_activator() noexcept 735 { 736 if( !ctx_ ) 737 return; 738 if( ctx_->is_active() ) 739 ctx_->deactivate(); 740 #ifndef BOOST_LEAF_NO_EXCEPTIONS 741 # if BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS 742 if( std::uncaught_exceptions() > uncaught_exceptions_ ) 743 # else 744 if( std::uncaught_exception() ) 745 # endif 746 ctx_->propagate(); 747 #endif 748 } 749 }; 750 751 template <class Ctx> activate_context(Ctx & ctx)752 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context(Ctx & ctx) noexcept 753 { 754 return context_activator<Ctx>(ctx); 755 } 756 757 //////////////////////////////////////////// 758 759 template <class R> 760 struct is_result_type: std::false_type 761 { 762 }; 763 764 template <class R> 765 struct is_result_type<R const>: is_result_type<R> 766 { 767 }; 768 769 } } 770 771 #undef BOOST_LEAF_THREAD_LOCAL 772 773 #endif 774