// 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 #include namespace boost { namespace threads { struct IThreadException { virtual void doThrow () = 0; virtual ~IThreadException () {} }; template struct thread_exception : public IThreadException { 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) { // again because of lack of boost::New support in shared_ptr throw HThreadException (boost::New, IThreadException> (exception)); // ideally throw boost::New > (exception); } #define thread_exceptions boost::tuple // obviously not namespaced, used for sanity, i suppose // this could be done the right way typedef thread_exceptions<> no_exceptions; } template class advanced_thread_base { public: typedef Exceptions Exceptions; void join () { assertNoException (); //thread.join (); } void assertNoException () { if (threads::HThreadException () != exception) { exception->doThrow (); } } protected: advanced_thread_base (boost::function const& threadFunctor) {//: thread (threadFunctor) { assertNoException (); } void setException (threads::HThreadException const& exception) { this->exception = exception; } private: //boost::thread thread; threads::HThreadException exception; }; // in codewarrior i can only do any specialization if a simple type is also involved, such as int template class advanced_thread : public advanced_thread_base { typedef advanced_thread_base Super; public: typedef boost::function Functor; advanced_thread (Functor const& f) : Super (bind (&advanced_thread::doThread, this)), functor (f) { doThread (); // for testing only assertNoException (); // for testing only } ReturnType getReturnValue () { assertNoException (); return returnValue; } private: void doThread () { try { returnValue = ExceptionAdapter::value>::callFunctor (functor); } catch (threads::HThreadException& exception) { setException (exception); } catch (...) { // get support for boost::New in shrared_ptr setException (boost::New, threads::IThreadException> ()); // ideally setException (boost::New > ()); } } template struct ExceptionAdapter { static ReturnType callFunctor (Functor const& f) { try { return ExceptionAdapter::callFunctor (f); } catch (tuples::element::type exception) { threads::thread_throw (exception); } } }; template struct ExceptionAdapter<0, HACK> { static ReturnType callFunctor (Functor const& f) { return f (); } }; Functor functor; ReturnType returnValue; }; template class advanced_thread : public advanced_thread_base { typedef advanced_thread_base Super; public: typedef boost::function Functor; advanced_thread (Functor const& f) : Super (bind (&advanced_thread::doThread, this)), functor (f) { doThread (); // for testing only assertNoException (); // for testing only } private: void doThread () { try { ExceptionAdapter::value>::callFunctor (functor); } catch (threads::HThreadException& exception) { setException (exception); } catch (...) { setException (boost::New, threads::IThreadException> ()); // ideally setException (boost::New > ()); } } template struct ExceptionAdapter { static void callFunctor (Functor const& f) { try { ExceptionAdapter::callFunctor (f); } catch (tuples::element::type exception) { threads::thread_throw (exception); } } }; template struct ExceptionAdapter<0, HACK> { static void callFunctor (Functor const& f) { f (); } }; Functor functor; }; } #endif