Index: src/libchcore/TOverlappedWriterFB.cpp =================================================================== diff -u -N -rf1d25f23712f5de7459f690ab51b2640d0f81b91 -r7892d3d5ca43da7dca4d9e8e0c321c21c3e13ea0 --- src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision f1d25f23712f5de7459f690ab51b2640d0f81b91) +++ src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision 7892d3d5ca43da7dca4d9e8e0c321c21c3e13ea0) @@ -21,6 +21,9 @@ #include "TSubTaskStatsInfo.h" #include "TFilesystemFileFeedbackWrapper.h" #include "TFileInfo.h" +#include "TCoreWin32Exception.h" +#include "TWorkerThreadController.h" +#include "TEventGuard.h" namespace chcore { @@ -41,7 +44,10 @@ m_spStats(spStats), m_spSrcFileInfo(spSrcFileInfo), m_spDataRange(spRange), - m_bOnlyCreate(bOnlyCreate) + m_bOnlyCreate(bOnlyCreate), + m_eventProcessingFinished(true, false), + m_eventWritingFinished(true, false), + m_rThreadController(rThreadController) { if(!spFilesystem) throw TCoreException(eErr_InvalidArgument, L"spFilesystem is NULL", LOCATION); @@ -157,9 +163,20 @@ } m_spWriter->AddEmptyBuffer(pBuffer); + return eResult; } + HANDLE TOverlappedWriterFB::GetEventWritingFinishedHandle() const + { + return m_eventWritingFinished.Handle(); + } + + HANDLE TOverlappedWriterFB::GetEventProcessingFinishedHandle() const + { + return m_eventProcessingFinished.Handle(); + } + void TOverlappedWriterFB::AdjustProcessedSize(file_size_t fsWritten) { // in case we read past the original eof, try to get new file size from filesystem @@ -271,6 +288,63 @@ return eResult; } + void TOverlappedWriterFB::StartThreaded() + { + TEventGuard guardProcessingFinished(m_eventProcessingFinished, true); + + m_eThreadResult = TSubTaskBase::eSubResult_Continue; + + enum { eKillThread, eWriteFinished, eWriteFailed, eWritePossible }; + + std::vector vHandles = { + m_rThreadController.GetKillThreadHandle(), + m_spWriter->GetEventWriteFinishedHandle(), + m_spWriter->GetEventWriteFailedHandle(), + m_spWriter->GetEventWritePossibleHandle() + }; + + bool bStopProcessing = false; + while(!bStopProcessing && m_eThreadResult == TSubTaskBase::eSubResult_Continue) + { + DWORD dwResult = WaitForMultipleObjectsEx(boost::numeric_cast(vHandles.size()), vHandles.data(), false, INFINITE, true); + switch(dwResult) + { + case STATUS_USER_APC: + break; + + case WAIT_OBJECT_0 + eKillThread: + m_eThreadResult = TSubTaskBase::eSubResult_KillRequest; + bStopProcessing = true; + break; + + case WAIT_OBJECT_0 + eWritePossible: + m_eThreadResult = OnWritePossible(); + break; + + case WAIT_OBJECT_0 + eWriteFailed: + m_eThreadResult = OnWriteFailed(); + break; + + case WAIT_OBJECT_0 + eWriteFinished: + { + m_eThreadResult = OnWriteFinished(bStopProcessing); + if(m_eThreadResult == TSubTaskBase::eSubResult_Continue && bStopProcessing) + m_eventWritingFinished.SetEvent(); + break; + } + + default: + DWORD dwLastError = GetLastError(); + throw TCoreWin32Exception(eErr_UnhandledCase, dwLastError, L"Unknown result from async waiting function", LOCATION); + } + } + } + + TSubTaskBase::ESubOperationResult TOverlappedWriterFB::StopThreaded() + { + return m_eThreadResult; + } + TOverlappedWriterPtr TOverlappedWriterFB::GetWriter() const { return m_spWriter;