/* $Revision: 19 $ $Date: 9/10/03 15:44 $ Copyright © 1997-2003, FSL Technologies Limited. Contact "http://fost3.fsltech.com". */ #include "stdafx.h" #define VC_EXTRALEAN #include #include #include #include #include #include using namespace std; using namespace FSLib; namespace { Revision c_revision( L"$Archive: /FOST.3/F3Util/thread.cpp $", __DATE__, L"$Revision: 19 $", L"$Date: 9/10/03 15:44 $" ); } namespace FSLib { class Thread { public: Thread( CWinThread *t ) : m_thread( t ) { } ~Thread() { try { while ( !completed() ) { Sleep( 100 ); } delete m_thread; } catch ( exception & ) { absorbException(); } } bool completed(); CWinThread *m_thread; }; } /* Thread */ bool Thread::completed() { DWORD retval; GetExitCodeThread( m_thread->m_hThread, &retval ); return retval != STILL_ACTIVE; } /* Task */ inline Task::Task() : m_stop( false ) { } inline Task::~Task() { if ( m_thread.get() ) { wait(); } } void Task::start() { if ( m_thread.get() ) { wait(); } m_stop = false; { ExclusiveWrite::WriteLock lock( m_attributes ); m_timing = Period< void >(); m_fault = Null; m_kernel = Null; m_user = Null; m_thread = boost::shared_ptr< Thread >( new Thread( AfxBeginThread( &Task::loader, reinterpret_cast< void * >( this ), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED ) ) ); } m_thread->m_thread->m_bAutoDelete = false; m_thread->m_thread->ResumeThread(); } inline void Task::stop() { m_stop = true; } inline bool Task::completed() { if ( m_thread.get() ) { return m_thread->completed(); } else { return true; } } inline void Task::wait() { while ( !completed() ) { Sleep( 100 ); } } inline bool Task::wait( const TimePeriod &howLong ) { for ( unsigned __int64 ms( howLong.milliseconds() ); !completed() && ms >= 0; ms -= 100 ) { Sleep( 100 ); } return completed(); } inline Period< void > Task::timing() const { ExclusiveWrite::ReadLock lock( m_attributes ); return m_timing; } inline Nullable< FSLib::wstring > Task::fault() const { ExclusiveWrite::ReadLock lock( m_attributes ); return m_fault; } unsigned int Task::loader( void *s ) { FSLib::Exceptions::StructuredHandler handler; ::CoInitialize( NULL ); Task *self = reinterpret_cast< Task * >( s ); { ExclusiveWrite::WriteLock lock( self->m_attributes ); self->m_timing.start( TimeStamp::now() ); } try { self->process(); } catch ( FSLib::Exceptions::Exception &e ) { wstringstream ws; ws << e; ExclusiveWrite::WriteLock lock( self->m_attributes ); self->m_fault = FSLib::wstring( ws.str() ); } catch ( std::exception &e ) { ExclusiveWrite::WriteLock lock( self->m_attributes ); self->m_fault = widen( e.what() ); } catch ( ... ) { ExclusiveWrite::WriteLock lock( self->m_attributes ); self->m_fault = L"Unknown exception"; } { ExclusiveWrite::WriteLock lock( self->m_attributes ); self->m_timing.end( FSLib::TimeStamp::now() ); FILETIME created, exited, kernel, user; if ( GetProcessTimes( self->m_thread->m_thread->m_hThread, &created, &exited, &kernel, &user ) ) { // Can record accurate timings // Must devide results from GetProcessTimes by 10,000 as it reports times in // 100ns blocks and TimePeriod expects a time in ms. self->m_kernel = TimePeriod( ( ( static_cast< unsigned __int64 >( kernel.dwHighDateTime ) << 16 ) + kernel.dwLowDateTime ) / 10000 ); self->m_user = TimePeriod( ( ( static_cast< unsigned __int64 >( user.dwHighDateTime ) << 16 ) + user.dwLowDateTime ) / 10000 ); } } return 0; } /* $History: thread.cpp $ * * ***************** Version 19 ***************** * User: Kirit Date: 9/10/03 Time: 15:44 * Updated in $/FOST.3/F3Util * Headers re-arranged to give a proper SDK feel and to make determination * of required headers simpler. * * ***************** Version 17 ***************** * User: Kirit Date: 8/10/03 Time: 12:48 * Updated in $/FOST/Cpp/FSCppUtil * Removed WINVER settings. * * ***************** Version 16 ***************** * User: Kirit Date: 3/10/03 Time: 18:44 * Updated in $/FOST.3/F3Util * * ***************** Version 15 ***************** * User: Kirit Date: 3/10/03 Time: 16:09 * Updated in $/FOST/Cpp/FSCppUtil * Added stdafx.h and stdafx.cpp pre-compiled header support. * * ***************** Version 14 ***************** * User: Kirit Date: 20/06/02 Time: 15:02 * Updated in $/FOST/Cpp/FSCppUtil * Added structured exception handling to sub-threads. * * ***************** Version 13 ***************** * User: Kirit Date: 7/05/02 Time: 12:01 * Updated in $/FOST/Cpp/FSCppUtil * Wrapped std::basic_string<> in order to change the copy semantics to * stop the problems with using C++ in the COM layer for IIS. * * ***************** Version 12 ***************** * User: Kirit Date: 28/04/02 Time: 21:18 * Updated in $/FOST/Cpp/FSCppUtil * Added support for converting Windows Structured Exceptions to the * std::exception hierarchy. * Updated exceptions so that catch (...) is only done where necessary and * correct. * * ***************** Version 11 ***************** * User: Kirit Date: 19/03/02 Time: 20:54 * Updated in $/FOST/Cpp/FSCppUtil * Corrected history from last check-in. * Updated TestAX.IDL to remove registry entries from removed classes. * * ***************** Version 10 ***************** * User: Kirit Date: 19/03/02 Time: 19:48 * Updated in $/FOST/Cpp/FSCppUtil * Debug compiles now all end in '_d'. * The C++ implementation names (Type.cppName) have been changed to also * include the DLL that the implementation is in as per the documentation. * In all source files the following have been done: * * Ensured that every header file has a revision object. * * Ensured that every translation unit has a revision object. * * Ensured that every source file (which understands comments) * has a history section. * * Changed all copyright notices to be for Obsideon Ltd. * * Changed copyright notices to use the longest possible timeframe. * * ***************** Version 9 ***************** * User: Kirit Date: 20/02/02 Time: 0:51 * Updated in $/FOST/Cpp/FSCppUtil * Destructor behavour under exceptions should now be sorted. * * ***************** Version 8 ***************** * User: Kirit Date: 26/12/01 Time: 18:47 * Updated in $/FOST/Cpp/FSCppUtil * Sorted out task kernel and user timing results so that they are not off * by a factor of 10,000. * * ***************** Version 7 ***************** * User: Kirit Date: 25/12/01 Time: 19:11 * Updated in $/FOST/Cpp/FSCppUtil * Some debugging of and extension of TimePeriod. * Added new reporting to Task and sorted out synchronised access to its * data members. * * ***************** Version 6 ***************** * User: Kirit Date: 4/11/01 Time: 3:42 * Updated in $/FOST/Cpp/FSCppUtil * Updates to support Mutex lock testing. * Header revision information now captured. * Periods<> container updated to better support error reporting and fault * finding. * * ***************** Version 5 ***************** * User: Kirit Date: 23/10/01 Time: 22:49 * Updated in $/FOST/FSCppUtil * Added new wait() member to thread so that controlling threads can * specify a timeout for waiting for a thread to complete. * * ***************** Version 4 ***************** * User: Kirit Date: 19/07/01 Time: 17:33 * Updated in $/FOST/FSCppUtil * Improved thread control. * ID pre-assignment now works correctly even under heavy load. * * ***************** Version 3 ***************** * User: Kirit Date: 19/07/01 Time: 15:08 * Updated in $/FOST/FSCppUtil * ID pre-assignment still issues the occasional ID multiple times under * heavy load. * Threading support now handles exceptions more properly. * * ***************** Version 2 ***************** * User: Kirit Date: 19/07/01 Time: 14:02 * Updated in $/FOST/FSCppUtil * First (crude) implementation of multi-threading support. * * ***************** Version 1 ***************** * User: Kirit Date: 18/07/01 Time: 17:38 * Created in $/FOST/FSCppUtil */