1 //Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc. 2 3 //Distributed under the Boost Software License, Version 1.0. (See accompanying 4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef UUID_274DA366004E11DCB1DDFE2E56D89593 7 #define UUID_274DA366004E11DCB1DDFE2E56D89593 8 #if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 9 #pragma GCC system_header 10 #endif 11 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 12 #pragma warning(push,1) 13 #endif 14 15 namespace 16 boost 17 { 18 namespace 19 exception_detail 20 { 21 template <class T> 22 class 23 refcount_ptr 24 { 25 public: 26 refcount_ptr()27 refcount_ptr(): 28 px_(0) 29 { 30 } 31 ~refcount_ptr()32 ~refcount_ptr() 33 { 34 release(); 35 } 36 refcount_ptr(refcount_ptr const & x)37 refcount_ptr( refcount_ptr const & x ): 38 px_(x.px_) 39 { 40 add_ref(); 41 } 42 43 refcount_ptr & operator =(refcount_ptr const & x)44 operator=( refcount_ptr const & x ) 45 { 46 adopt(x.px_); 47 return *this; 48 } 49 50 void adopt(T * px)51 adopt( T * px ) 52 { 53 release(); 54 px_=px; 55 add_ref(); 56 } 57 58 T * get() const59 get() const 60 { 61 return px_; 62 } 63 64 private: 65 66 T * px_; 67 68 void add_ref()69 add_ref() 70 { 71 if( px_ ) 72 px_->add_ref(); 73 } 74 75 void release()76 release() 77 { 78 if( px_ && px_->release() ) 79 px_=0; 80 } 81 }; 82 } 83 84 //////////////////////////////////////////////////////////////////////// 85 86 template <class Tag,class T> 87 class error_info; 88 89 typedef error_info<struct throw_function_,char const *> throw_function; 90 typedef error_info<struct throw_file_,char const *> throw_file; 91 typedef error_info<struct throw_line_,int> throw_line; 92 93 template <> 94 class 95 error_info<throw_function_,char const *> 96 { 97 public: 98 typedef char const * value_type; 99 value_type v_; 100 explicit error_info(value_type v)101 error_info( value_type v ): 102 v_(v) 103 { 104 } 105 }; 106 107 template <> 108 class 109 error_info<throw_file_,char const *> 110 { 111 public: 112 typedef char const * value_type; 113 value_type v_; 114 explicit error_info(value_type v)115 error_info( value_type v ): 116 v_(v) 117 { 118 } 119 }; 120 121 template <> 122 class 123 error_info<throw_line_,int> 124 { 125 public: 126 typedef int value_type; 127 value_type v_; 128 explicit error_info(value_type v)129 error_info( value_type v ): 130 v_(v) 131 { 132 } 133 }; 134 135 #if defined(__GNUC__) 136 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 137 # pragma GCC visibility push (default) 138 # endif 139 #endif 140 class exception; 141 #if defined(__GNUC__) 142 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 143 # pragma GCC visibility pop 144 # endif 145 #endif 146 147 template <class T> 148 class shared_ptr; 149 150 namespace 151 exception_detail 152 { 153 class error_info_base; 154 struct type_info_; 155 156 struct 157 error_info_container 158 { 159 virtual char const * diagnostic_information( char const * ) const = 0; 160 virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0; 161 virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0; 162 virtual void add_ref() const = 0; 163 virtual bool release() const = 0; 164 virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0; 165 166 protected: 167 ~error_info_containerboost::exception_detail::error_info_container168 ~error_info_container() throw() 169 { 170 } 171 }; 172 173 template <class> 174 struct get_info; 175 176 template <> 177 struct get_info<throw_function>; 178 179 template <> 180 struct get_info<throw_file>; 181 182 template <> 183 struct get_info<throw_line>; 184 185 char const * get_diagnostic_information( exception const &, char const * ); 186 187 void copy_boost_exception( exception *, exception const * ); 188 189 template <class E,class Tag,class T> 190 E const & set_info( E const &, error_info<Tag,T> const & ); 191 192 template <class E> 193 E const & set_info( E const &, throw_function const & ); 194 195 template <class E> 196 E const & set_info( E const &, throw_file const & ); 197 198 template <class E> 199 E const & set_info( E const &, throw_line const & ); 200 } 201 202 #if defined(__GNUC__) 203 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 204 # pragma GCC visibility push (default) 205 # endif 206 #endif 207 class 208 exception 209 { 210 //<N3757> 211 public: 212 template <class Tag> void set( typename Tag::type const & ); 213 template <class Tag> typename Tag::type const * get() const; 214 //</N3757> 215 216 protected: 217 exception()218 exception(): 219 throw_function_(0), 220 throw_file_(0), 221 throw_line_(-1) 222 { 223 } 224 225 #ifdef __HP_aCC 226 //On HP aCC, this protected copy constructor prevents throwing boost::exception. 227 //On all other platforms, the same effect is achieved by the pure virtual destructor. exception(exception const & x)228 exception( exception const & x ) throw(): 229 data_(x.data_), 230 throw_function_(x.throw_function_), 231 throw_file_(x.throw_file_), 232 throw_line_(x.throw_line_) 233 { 234 } 235 #endif 236 237 virtual ~exception() throw() 238 #ifndef __HP_aCC 239 = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors. 240 #endif 241 ; 242 243 #if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310) 244 public: 245 #else 246 private: 247 248 template <class E> 249 friend E const & exception_detail::set_info( E const &, throw_function const & ); 250 251 template <class E> 252 friend E const & exception_detail::set_info( E const &, throw_file const & ); 253 254 template <class E> 255 friend E const & exception_detail::set_info( E const &, throw_line const & ); 256 257 template <class E,class Tag,class T> 258 friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & ); 259 260 friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); 261 262 template <class> 263 friend struct exception_detail::get_info; 264 friend struct exception_detail::get_info<throw_function>; 265 friend struct exception_detail::get_info<throw_file>; 266 friend struct exception_detail::get_info<throw_line>; 267 friend void exception_detail::copy_boost_exception( exception *, exception const * ); 268 #endif 269 mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_; 270 mutable char const * throw_function_; 271 mutable char const * throw_file_; 272 mutable int throw_line_; 273 }; 274 #if defined(__GNUC__) 275 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 276 # pragma GCC visibility pop 277 # endif 278 #endif 279 280 inline 281 exception:: ~exception()282 ~exception() throw() 283 { 284 } 285 286 namespace 287 exception_detail 288 { 289 template <class E> 290 E const & set_info(E const & x,throw_function const & y)291 set_info( E const & x, throw_function const & y ) 292 { 293 x.throw_function_=y.v_; 294 return x; 295 } 296 297 template <class E> 298 E const & set_info(E const & x,throw_file const & y)299 set_info( E const & x, throw_file const & y ) 300 { 301 x.throw_file_=y.v_; 302 return x; 303 } 304 305 template <class E> 306 E const & set_info(E const & x,throw_line const & y)307 set_info( E const & x, throw_line const & y ) 308 { 309 x.throw_line_=y.v_; 310 return x; 311 } 312 } 313 314 //////////////////////////////////////////////////////////////////////// 315 316 namespace 317 exception_detail 318 { 319 #if defined(__GNUC__) 320 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 321 # pragma GCC visibility push (default) 322 # endif 323 #endif 324 template <class T> 325 struct 326 error_info_injector: 327 public T, 328 public exception 329 { 330 explicit error_info_injectorboost::exception_detail::error_info_injector331 error_info_injector( T const & x ): 332 T(x) 333 { 334 } 335 ~error_info_injectorboost::exception_detail::error_info_injector336 ~error_info_injector() throw() 337 { 338 } 339 }; 340 #if defined(__GNUC__) 341 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 342 # pragma GCC visibility pop 343 # endif 344 #endif 345 346 struct large_size { char c[256]; }; 347 large_size dispatch_boost_exception( exception const * ); 348 349 struct small_size { }; 350 small_size dispatch_boost_exception( void const * ); 351 352 template <class,int> 353 struct enable_error_info_helper; 354 355 template <class T> 356 struct 357 enable_error_info_helper<T,sizeof(large_size)> 358 { 359 typedef T type; 360 }; 361 362 template <class T> 363 struct 364 enable_error_info_helper<T,sizeof(small_size)> 365 { 366 typedef error_info_injector<T> type; 367 }; 368 369 template <class T> 370 struct 371 enable_error_info_return_type 372 { 373 typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type; 374 }; 375 } 376 377 template <class T> 378 inline 379 typename 380 exception_detail::enable_error_info_return_type<T>::type enable_error_info(T const & x)381 enable_error_info( T const & x ) 382 { 383 typedef typename exception_detail::enable_error_info_return_type<T>::type rt; 384 return rt(x); 385 } 386 387 //////////////////////////////////////////////////////////////////////// 388 389 namespace 390 exception_detail 391 { 392 #if defined(__GNUC__) 393 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 394 # pragma GCC visibility push (default) 395 # endif 396 #endif 397 class 398 clone_base 399 { 400 public: 401 402 virtual clone_base const * clone() const = 0; 403 virtual void rethrow() const = 0; 404 405 virtual ~clone_base()406 ~clone_base() throw() 407 { 408 } 409 }; 410 #if defined(__GNUC__) 411 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 412 # pragma GCC visibility pop 413 # endif 414 #endif 415 416 inline 417 void copy_boost_exception(exception * a,exception const * b)418 copy_boost_exception( exception * a, exception const * b ) 419 { 420 refcount_ptr<error_info_container> data; 421 if( error_info_container * d=b->data_.get() ) 422 data = d->clone(); 423 a->throw_file_ = b->throw_file_; 424 a->throw_line_ = b->throw_line_; 425 a->throw_function_ = b->throw_function_; 426 a->data_ = data; 427 } 428 429 inline 430 void copy_boost_exception(void *,void const *)431 copy_boost_exception( void *, void const * ) 432 { 433 } 434 435 template <class T> 436 class 437 clone_impl: 438 public T, 439 public virtual clone_base 440 { 441 struct clone_tag { }; clone_impl(clone_impl const & x,clone_tag)442 clone_impl( clone_impl const & x, clone_tag ): 443 T(x) 444 { 445 copy_boost_exception(this,&x); 446 } 447 448 public: 449 450 explicit clone_impl(T const & x)451 clone_impl( T const & x ): 452 T(x) 453 { 454 copy_boost_exception(this,&x); 455 } 456 ~clone_impl()457 ~clone_impl() throw() 458 { 459 } 460 461 private: 462 463 clone_base const * clone() const464 clone() const 465 { 466 return new clone_impl(*this,clone_tag()); 467 } 468 469 void rethrow() const470 rethrow() const 471 { 472 throw*this; 473 } 474 }; 475 } 476 477 template <class T> 478 inline 479 exception_detail::clone_impl<T> enable_current_exception(T const & x)480 enable_current_exception( T const & x ) 481 { 482 return exception_detail::clone_impl<T>(x); 483 } 484 } 485 486 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 487 #pragma warning(pop) 488 #endif 489 #endif 490