// Copyright (C) 2002 Eric Woodruff (eric.woodruff@falsetto.com) // // Permission to copy, use, sell and distribute this software is granted // provided this copyright notice appears in all copies. // Permission to modify the code and to distribute modified code is granted // provided this copyright notice appears in all copies, and a notice // that the code was modified is included with the copyright notice. // // This software is provided "as is" without express or implied warranty, // and with no claim as to its suitability for any purpose. #ifndef ADVANCED_THREAD_HPP__ #define ADVANCED_THREAD_HPP__ #include #include #include #include #include #include namespace boost { namespace threads { struct IThreadException { virtual void doThrow () = 0; virtual ~IThreadException () {} }; template class thread_exception : public IThreadException { public: thread_exception (Exception exception) : exception (exception) {} thread_exception () {} void doThrow () { throw exception; } private: Exception exception; }; typedef shared_ptr HThreadException; template void thread_throw (Exception exception) { throw HThreadException (boost::New, IThreadException> (exception)); // ideally throw boost::New > (exception); // off topic note to self: boost::New is preferred as a class so it can easily be made a friend // to force the shared_ptr paradigm by making the constructor private } template class ExceptionAdapter { public: static ReturnType convertExceptions (boost::function0 const& f) { return Catcher::value>::callFunctor (f); } private: template struct Catcher { static ReturnType callFunctor (boost::function0 const& f) { try { return Catcher::callFunctor (f); } catch (tuples::element::type exception) { thread_throw (exception); } } }; template struct Catcher<0, HACK> { static ReturnType callFunctor (boost::function0 const& f) { return f (); } }; }; // only needed on void return problems template class ExceptionAdapter { public: static void convertExceptions (boost::function0 const& f) { Catcher::value>::callFunctor (f); } private: template struct Catcher { static void callFunctor (boost::function0 const& f) { try { Catcher::callFunctor (f); } catch (tuples::element::type exception) { thread_throw (exception); } } }; template struct Catcher<0, HACK> { static void callFunctor (boost::function0 const& f) { f (); } }; }; // whenever there is an exception, it can be received on multiple joins from different threads template class throws_exceptions { typedef boost::tuple Exceptions; public: // make a flag to terminate instead of bad_exception? // currently an empty exception list will throw bad_exception instead of terminating // i guess that follows the "throws_exceptions" mantra void assert_no_exception () { if (HThreadException () != exception) { exception->doThrow (); } } protected: template ReturnType runThread (boost::function0 const& f) { try { return ExceptionAdapter::convertExceptions (f); } catch (HThreadException const& exception) { setException (exception); } catch (...) { setException (boost::New, IThreadException> ()); } } // really only needed on void return problems void runThread (boost::function0 const& f) { try { ExceptionAdapter::convertExceptions (f); } catch (HThreadException const& exception) { setException (exception); } catch (...) { setException (boost::New, IThreadException> ()); } } private: void setException (HThreadException const& exception) { this->exception = exception; } HThreadException exception; }; class terminates_on_exception { public: void assert_no_exception () { } protected: template ReturnType runThread (boost::function0 const& f) { try { return f (); } catch (...) { std::terminate (); } } // again, for void return problems void runThread (boost::function0 const& f) { try { f (); } catch (...) { std::terminate (); } } }; } // the "int HACK" is to appease CodeWarrior template class advanced_thread : public ExceptionPolicy { public: typedef boost::function0 Functor; advanced_thread (Functor const& f) : /*thread (bind (&advanced_thread::threadProcess, this)),*/ functor (f) { runThread (); // for simple testing only ExceptionPolicy::assert_no_exception (); } ReturnType join () { //thread.join (); ExceptionPolicy::assert_no_exception (); return returnValue; } private: void runThread () { returnValue = ExceptionPolicy::runThread (functor); } Functor functor; ReturnType returnValue; // thread }; template class advanced_thread : public ExceptionPolicy { public: typedef boost::function0 Functor; advanced_thread (Functor const& f) : functor (f) { runThread (); // for simple testing only ExceptionPolicy::assert_no_exception (); } void join () { //thread.join (); ExceptionPolicy::assert_no_exception (); } private: void runThread () { ExceptionPolicy::runThread (functor); } Functor functor; // thread }; } #endif