OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #if ( defined( __linux__ ) && !defined( __ANDROID__ ) ) 00026 #include <sys/prctl.h> 00027 #endif 00028 00029 #include <iostream> 00030 #include <string> 00031 00032 #include "exceptions/WSignalSubscriptionFailed.h" 00033 #include "WCondition.h" 00034 #include "WConditionOneShot.h" 00035 #include "WException.h" 00036 #include "WLogger.h" 00037 #include "WThreadedRunner.h" 00038 00039 WThreadedRunner::WThreadedRunner(): 00040 m_shutdownFlag( new WConditionOneShot(), false ), 00041 m_isCrashed( new WConditionOneShot(), false ), 00042 m_crashMessage( "" ), 00043 m_threadName( "" ) 00044 { 00045 // initialize members 00046 } 00047 00048 WThreadedRunner::~WThreadedRunner() 00049 { 00050 // cleanup 00051 } 00052 00053 const WBoolFlag& WThreadedRunner::isCrashed() const 00054 { 00055 return m_isCrashed; 00056 } 00057 00058 void WThreadedRunner::onThreadException( const WException& e ) 00059 { 00060 handleDeadlyException( e ); 00061 } 00062 00063 void WThreadedRunner::handleDeadlyException( const WException& e, std::string sender ) 00064 { 00065 wlog::error( sender ) << "WException. Notifying. Message: " << e.what(); 00066 00067 // ensure proper exception propagation 00068 signal_thread_error( e ); 00069 00070 // notify waiting threads 00071 m_isCrashed( true ); 00072 m_crashMessage = e.what(); 00073 } 00074 00075 void WThreadedRunner::run() 00076 { 00077 run( boost::bind( &WThreadedRunner::threadMainSave, this ) ); 00078 } 00079 00080 void WThreadedRunner::run( THREADFUNCTION f ) 00081 { 00082 m_thread = boost::thread( f ); 00083 } 00084 00085 void WThreadedRunner::wait( bool requestFinish ) 00086 { 00087 if( requestFinish ) 00088 { 00089 requestStop(); 00090 } 00091 m_thread.join(); 00092 } 00093 00094 void WThreadedRunner::requestStop() 00095 { 00096 // first notify 00097 notifyStop(); 00098 00099 // then signal it 00100 m_shutdownFlag( true ); 00101 } 00102 00103 void WThreadedRunner::waitForStop() 00104 { 00105 m_shutdownFlag.wait(); 00106 } 00107 00108 void WThreadedRunner::threadMainSave() 00109 { 00110 WThreadedRunner::setThisThreadName( getThreadName() ); 00111 00112 try 00113 { 00114 threadMain(); 00115 } 00116 catch( const WException& e ) 00117 { 00118 onThreadException( e ); 00119 } 00120 catch( const std::exception& e ) 00121 { 00122 onThreadException( WException( e ) ); 00123 } 00124 } 00125 00126 void WThreadedRunner::threadMain() 00127 { 00128 WLogger::getLogger()->addLogMessage( "This should never be called. Implement a thread function here.", "WThreadedRunner", LL_WARNING ); 00129 } 00130 00131 void WThreadedRunner::notifyStop() 00132 { 00133 } 00134 00135 void WThreadedRunner::yield() const 00136 { 00137 m_thread.yield(); 00138 } 00139 00140 void WThreadedRunner::sleep( const int32_t t ) const 00141 { 00142 boost::this_thread::sleep( boost::posix_time::seconds( t ) ); 00143 } 00144 00145 void WThreadedRunner::msleep( const int32_t t ) const 00146 { 00147 boost::this_thread::sleep( boost::posix_time::microseconds( t ) ); 00148 } 00149 00150 boost::signals2::connection WThreadedRunner::subscribeSignal( THREAD_SIGNAL signal, t_ThreadErrorSignalHandlerType notifier ) 00151 { 00152 switch( signal) 00153 { 00154 case WTHREAD_ERROR: 00155 return signal_thread_error.connect( notifier ); 00156 default: 00157 throw WSignalSubscriptionFailed( "Could not subscribe to unknown signal." ); 00158 break; 00159 } 00160 } 00161 00162 void WThreadedRunner::setThreadName( std::string name ) 00163 { 00164 m_threadName = name; 00165 } 00166 00167 std::string WThreadedRunner::getThreadName() const 00168 { 00169 return m_threadName; 00170 } 00171 00172 const std::string& WThreadedRunner::getCrashMessage() const 00173 { 00174 return m_crashMessage; 00175 } 00176 00177 void WThreadedRunner::setThisThreadName( std::string name ) 00178 { 00179 #if ( defined( __linux__ ) && !defined( __ANDROID__ ) ) 00180 // set the name of the thread. This name is shown by the "top", for example. 00181 prctl( PR_SET_NAME, ( "openwalnut (" + name + ")" ).c_str() ); 00182 #endif 00183 }