Index: src/libchcore/TBufferList.h =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TBufferList.h (.../TBufferList.h) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TBufferList.h (.../TBufferList.h) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -42,20 +42,18 @@ if(!pBuffer) throw TCoreException(eErr_InvalidArgument, L"pBuffer", LOCATION); - { - boost::unique_lock lock(m_mutex); + boost::unique_lock lock(m_mutex); - m_queueBuffers.push_front(pBuffer); - m_spCount->Increase(); - } + m_queueBuffers.push_front(pBuffer); + m_spCount->Increase(); } TOverlappedDataBuffer* Pop() { TOverlappedDataBuffer* pBuffer = nullptr; { - boost::unique_lock lock(m_mutex); + boost::unique_lock lock(m_mutex); if(m_queueBuffers.empty()) return nullptr; @@ -70,35 +68,33 @@ void Clear() { - bool bRemoved = false; - { - boost::unique_lock lock(m_mutex); + boost::unique_lock lock(m_mutex); - bRemoved = !m_queueBuffers.empty(); - m_queueBuffers.clear(); - m_spCount->SetValue(0); - } + m_queueBuffers.clear(); + m_spCount->SetValue(0); } size_t GetCount() const { + boost::unique_lock lock(m_mutex); return m_spCount->GetValue(); } bool IsEmpty() const { + boost::unique_lock lock(m_mutex); return m_spCount->GetValue() == 0; } void SetExpectedBuffersCount(size_t stExpectedBuffers) // thread-unsafe by design { - boost::unique_lock lock(m_mutex); + boost::unique_lock lock(m_mutex); m_stExpectedBuffers = stExpectedBuffers; } bool AreAllBuffersAccountedFor() const { - boost::shared_lock lock(m_mutex); + boost::unique_lock lock(m_mutex); return m_stExpectedBuffers == m_spCount->GetValue(); } @@ -108,7 +104,7 @@ } private: - mutable boost::shared_mutex m_mutex; + mutable boost::mutex m_mutex; TSharedCountMTPtr m_spCount; size_t m_stExpectedBuffers = 0; // count of buffers there should be in m_queueBuffers when no buffer is in use Index: src/libchcore/TOrderedBufferQueue.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TOrderedBufferQueue.cpp (.../TOrderedBufferQueue.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TOrderedBufferQueue.cpp (.../TOrderedBufferQueue.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -55,8 +55,6 @@ if (!pairInsert.second) throw TCoreException(eErr_InvalidArgument, L"Tried to insert duplicate buffer into the collection", LOCATION); - m_spBuffersCount->Increase(); - if(pBuffer->IsLastPart()) m_bDataSourceFinished = true; @@ -71,6 +69,7 @@ UpdateHasErrors(); } + m_spBuffersCount->Increase(); UpdateHasBuffers(); } Index: src/libchcore/TOverlappedReaderFB.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TOverlappedReaderFB.cpp (.../TOverlappedReaderFB.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TOverlappedReaderFB.cpp (.../TOverlappedReaderFB.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -247,14 +247,17 @@ { TOverlappedDataBuffer* pBuffer = m_spReader->GetEmptyBuffer(); if(!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Read was possible, but no buffer is available", LOCATION); + return TSubTaskBase::eSubResult_Continue; m_counterOnTheFly.Increase(); pBuffer->SetParam(this); TSubTaskBase::ESubOperationResult eResult = m_spSrcFile->ReadFileFB(*pBuffer); if(eResult != TSubTaskBase::eSubResult_Continue) + { m_spReader->AddEmptyBuffer(pBuffer); + m_counterOnTheFly.Decrease(); + } return eResult; } Index: src/libchcore/TOverlappedWriterFB.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TOverlappedWriterFB.cpp (.../TOverlappedWriterFB.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -85,14 +85,17 @@ { TOverlappedDataBuffer* pBuffer = m_spWriter->GetWriteBuffer(); if(!pBuffer) - throw TCoreException(eErr_InternalProblem, L"Write was possible, but no buffer is available", LOCATION); + return TSubTaskBase::eSubResult_Continue; m_counterOnTheFly.Increase(); pBuffer->SetParam(this); TSubTaskBase::ESubOperationResult eResult = m_spDstFile->WriteFileFB(*pBuffer); if(eResult != TSubTaskBase::eSubResult_Continue) + { m_spWriter->AddEmptyBuffer(pBuffer); + m_counterOnTheFly.Decrease(); + } return eResult; } @@ -310,19 +313,17 @@ { m_eventProcessingFinished.ResetEvent(); TEventGuard guardProcessingFinished(m_eventProcessingFinished, true); - TEvent eventNonSignaled(true, false); m_eThreadResult = TSubTaskBase::eSubResult_Continue; - enum { eKillThread, eLocalKill, eWriteFinished, eWriteFailed, eWritePossible, eNoBuffersOnTheFly }; + enum { eKillThread, eLocalKill, eWriteFinished, eWriteFailed, eWritePossible }; std::vector vHandles = { m_rThreadController.GetKillThreadHandle(), m_eventLocalKill.Handle(), m_spWriter->GetEventWriteFinishedHandle(), m_spWriter->GetEventWriteFailedHandle(), - m_spWriter->GetEventWritePossibleHandle(), - eventNonSignaled.Handle() + m_spWriter->GetEventWritePossibleHandle() }; bool bWrittenLastBuffer = false; Index: src/libchcore/TReadBufferQueueWrapper.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TReadBufferQueueWrapper.cpp (.../TReadBufferQueueWrapper.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TReadBufferQueueWrapper.cpp (.../TReadBufferQueueWrapper.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -34,7 +34,7 @@ m_stMaxReadAheadBuffers(stMaxReadAheadBuffers), m_spOtfBuffersCount(spOtfBuffersCount), m_spCurrentReadAheadBuffers(spCurrentReadAheadBuffers), - m_eventHasBuffers(true, false) + m_eventHasBuffers(false, true) { if(!spEmptyBuffers) throw TCoreException(eErr_InvalidArgument, L"spEmptyBuffers is NULL", LOCATION); @@ -53,8 +53,6 @@ m_currentReadAheadConnector = m_spCurrentReadAheadBuffers->GetNotifier().connect(boost::bind(&TReadBufferQueueWrapper::UpdateHasBuffers, this)); m_retryBuffersConnector = m_tRetryBuffers.GetSharedCount()->GetNotifier().connect(boost::bind(&TReadBufferQueueWrapper::UpdateHasBuffers, this)); m_otfBuffersConnector = m_spOtfBuffersCount->GetNotifier().connect(boost::bind(&TReadBufferQueueWrapper::UpdateHasBuffers, this)); - - UpdateHasBuffers(); } TReadBufferQueueWrapper::~TReadBufferQueueWrapper() @@ -96,12 +94,14 @@ TOverlappedDataBuffer* TReadBufferQueueWrapper::Pop() { - if(!IsBufferReady()) + if(m_spOtfBuffersCount->GetValue() >= m_stMaxOtfBuffers) return nullptr; - // always return retry buffers first + if(m_spCurrentReadAheadBuffers->GetValue() >= m_stMaxReadAheadBuffers) + return nullptr; + TOverlappedDataBuffer* pBuffer = m_tRetryBuffers.Pop(); - if(!pBuffer) + if(!pBuffer && !IsDataSourceFinished()) { pBuffer = m_spEmptyBuffers->Pop(); if(pBuffer) @@ -111,23 +111,12 @@ } } + if(pBuffer) + m_eventHasBuffers.SetEvent(); + return pBuffer; } - bool TReadBufferQueueWrapper::IsBufferReady() const - { - if(m_spOtfBuffersCount->GetValue() >= m_stMaxOtfBuffers) - return false; - - if(m_spCurrentReadAheadBuffers->GetValue() >= m_stMaxReadAheadBuffers) - return false; - - if(!m_tRetryBuffers.IsEmpty()) - return true; - - return !IsDataSourceFinished() && !m_spEmptyBuffers->IsEmpty(); - } - void TReadBufferQueueWrapper::SetDataSourceFinished(TOverlappedDataBuffer* pBuffer) { if(!pBuffer) @@ -154,7 +143,7 @@ void TReadBufferQueueWrapper::UpdateHasBuffers() { - m_eventHasBuffers.SetEvent(IsBufferReady()); + m_eventHasBuffers.SetEvent(); } void TReadBufferQueueWrapper::ClearBuffers() Index: src/libchcore/TReadBufferQueueWrapper.h =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TReadBufferQueueWrapper.h (.../TReadBufferQueueWrapper.h) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TReadBufferQueueWrapper.h (.../TReadBufferQueueWrapper.h) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -53,7 +53,6 @@ void UpdateProcessingRange(unsigned long long ullNewPosition); private: - bool IsBufferReady() const; void UpdateHasBuffers(); private: Index: src/libchcore/TWriteBufferQueueWrapper.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TWriteBufferQueueWrapper.cpp (.../TWriteBufferQueueWrapper.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TWriteBufferQueueWrapper.cpp (.../TWriteBufferQueueWrapper.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -27,7 +27,7 @@ m_spDataQueue(spQueue), m_stMaxOtfBuffers(stMaxOtfBuffers), m_spOtfBuffersCount(spOtfBuffersCount), - m_eventHasBuffers(true, false) + m_eventHasBuffers(false, true) { if (!spQueue) throw TCoreException(eErr_InvalidArgument, L"spQueue is NULL", LOCATION); @@ -36,16 +36,16 @@ if (stMaxOtfBuffers == 0) throw TCoreException(eErr_InvalidArgument, L"stMaxOtfBuffers cannot be 0", LOCATION); - UpdateHasBuffers(); - m_dataQueueConnector = m_spDataQueue->GetSharedCount()->GetNotifier().connect(boost::bind(&TWriteBufferQueueWrapper::UpdateHasBuffers, this)); m_retryBuffersConnector = m_tRetryBuffers.GetSharedCount()->GetNotifier().connect(boost::bind(&TWriteBufferQueueWrapper::UpdateHasBuffers, this)); + m_otfBuffersConnector = m_spOtfBuffersCount->GetNotifier().connect(boost::bind(&TWriteBufferQueueWrapper::UpdateHasBuffers, this)); } TWriteBufferQueueWrapper::~TWriteBufferQueueWrapper() { m_dataQueueConnector.disconnect(); m_retryBuffersConnector.disconnect(); + m_otfBuffersConnector.disconnect(); } void TWriteBufferQueueWrapper::Push(TOverlappedDataBuffer* pBuffer) @@ -54,30 +54,27 @@ throw TCoreException(eErr_InvalidPointer, L"pBuffer", LOCATION); m_tRetryBuffers.Push(pBuffer); - UpdateHasBuffers(); } TOverlappedDataBuffer* TWriteBufferQueueWrapper::Pop() { - TOverlappedDataBuffer* pBuffer = InternalPop(); + if(m_spOtfBuffersCount->GetValue() >= m_stMaxOtfBuffers) + return nullptr; + + TOverlappedDataBuffer* pBuffer = m_tRetryBuffers.Pop(); + if(!pBuffer) + pBuffer = m_spDataQueue->Pop(); + if(pBuffer) { pBuffer->InitForWrite(); - UpdateHasBuffers(); + + m_eventHasBuffers.SetEvent(); } return pBuffer; } - TOverlappedDataBuffer* TWriteBufferQueueWrapper::InternalPop() - { - TOverlappedDataBuffer* pBuffer = m_tRetryBuffers.Pop(); - if(!pBuffer) - pBuffer = m_spDataQueue->Pop(); - - return pBuffer; - } - size_t TWriteBufferQueueWrapper::GetCount() const { return m_spDataQueue->GetCount(); @@ -94,19 +91,8 @@ m_tRetryBuffers.ClearBuffers(spEmptyBuffers); } - bool TWriteBufferQueueWrapper::HasBuffersToProcess() const - { - if(m_spOtfBuffersCount->GetValue() >= m_stMaxOtfBuffers) - return false; - - if(!m_tRetryBuffers.IsEmpty()) - return true; - - return m_spDataQueue->HasPoppableBuffer(); - } - void TWriteBufferQueueWrapper::UpdateHasBuffers() { - m_eventHasBuffers.SetEvent(HasBuffersToProcess()); + m_eventHasBuffers.SetEvent(); } } Index: src/libchcore/TWriteBufferQueueWrapper.h =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/TWriteBufferQueueWrapper.h (.../TWriteBufferQueueWrapper.h) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/TWriteBufferQueueWrapper.h (.../TWriteBufferQueueWrapper.h) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -43,11 +43,8 @@ void ClearBuffers(const TBufferListPtr& spEmptyBuffers); private: - bool HasBuffersToProcess() const; void UpdateHasBuffers(); - TOverlappedDataBuffer* InternalPop(); - private: // input buffers TOrderedBufferQueuePtr m_spDataQueue; // external queue of buffers to use @@ -62,6 +59,7 @@ // external state TSharedCountPtr m_spOtfBuffersCount; + boost::signals2::connection m_otfBuffersConnector; // event TEvent m_eventHasBuffers; Index: src/libchcore/Tests/TOverlappedReaderTests.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/Tests/TOverlappedReaderTests.cpp (.../TOverlappedReaderTests.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/Tests/TOverlappedReaderTests.cpp (.../TOverlappedReaderTests.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -25,7 +25,7 @@ EXPECT_NE(nullptr, tReader.GetEventReadPossibleHandle()); EXPECT_NE(nullptr, tReader.GetEventReadFailedHandle()); - EXPECT_TIMEOUT(tReader.GetEventReadPossibleHandle()); + EXPECT_SIGNALED(tReader.GetEventReadPossibleHandle()); EXPECT_TIMEOUT(tReader.GetEventReadFailedHandle()); EXPECT_FALSE(tReader.IsDataSourceFinished()); @@ -71,9 +71,10 @@ EXPECT_SIGNALED(tReader.GetEventReadPossibleHandle()); EXPECT_NE(nullptr, tReader.GetEmptyBuffer()); - EXPECT_TIMEOUT(tReader.GetEventReadPossibleHandle()); + EXPECT_SIGNALED(tReader.GetEventReadPossibleHandle()); EXPECT_EQ(nullptr, tReader.GetEmptyBuffer()); + EXPECT_TIMEOUT(tReader.GetEventReadPossibleHandle()); } TEST(TOverlappedReaderTests, AddEmptyBuffer) @@ -87,7 +88,7 @@ TOverlappedDataBuffer* pBuffers[ 3 ] = { tReader.GetEmptyBuffer(), tReader.GetEmptyBuffer(), tReader.GetEmptyBuffer() }; - EXPECT_TIMEOUT(tReader.GetEventReadPossibleHandle()); + EXPECT_SIGNALED(tReader.GetEventReadPossibleHandle()); tReader.AddEmptyBuffer(pBuffers[ 0 ]); EXPECT_SIGNALED(tReader.GetEventReadPossibleHandle()); Index: src/libchcore/Tests/TOverlappedWriterTests.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/Tests/TOverlappedWriterTests.cpp (.../TOverlappedWriterTests.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/Tests/TOverlappedWriterTests.cpp (.../TOverlappedWriterTests.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -24,7 +24,9 @@ EXPECT_NE(nullptr, tWriter.GetEventWriteFailedHandle()); EXPECT_NE(nullptr, tWriter.GetEventWriteFinishedHandle()); + EXPECT_SIGNALED(tWriter.GetEventWritePossibleHandle()); EXPECT_TIMEOUT(tWriter.GetEventWritePossibleHandle()); + EXPECT_TIMEOUT(tWriter.GetEventWriteFailedHandle()); EXPECT_TIMEOUT(tWriter.GetEventWriteFinishedHandle()); } @@ -39,7 +41,7 @@ TSharedCountPtr spOtfBufferCount(std::make_shared>()); TOverlappedWriter tWriter(spLogData, spQueue, spRange, spEmptyBuffers, 1, spOtfBufferCount); - EXPECT_TIMEOUT(tWriter.GetEventWritePossibleHandle()); + EXPECT_SIGNALED(tWriter.GetEventWritePossibleHandle()); EXPECT_TIMEOUT(tWriter.GetEventWriteFailedHandle()); EXPECT_TIMEOUT(tWriter.GetEventWriteFinishedHandle()); } Index: src/libchcore/Tests/TReadBufferQueueWrapperTests.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/Tests/TReadBufferQueueWrapperTests.cpp (.../TReadBufferQueueWrapperTests.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/Tests/TReadBufferQueueWrapperTests.cpp (.../TReadBufferQueueWrapperTests.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -23,7 +23,7 @@ TSharedCountMTPtr spReadAheadBufferCount(std::make_shared>()); TReadBufferQueueWrapper queue(spList, 0, 1024, 1, 1, spOtfBufferCount, spReadAheadBufferCount); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); EXPECT_EQ(false, queue.IsDataSourceFinished()); } @@ -112,8 +112,9 @@ EXPECT_EQ(3072, buffer1.GetFilePosition()); EXPECT_EQ(1024, buffer1.GetRequestedDataSize()); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); EXPECT_EQ(nullptr, queue.Pop()); + EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); } TEST(TReadBufferQueueWrapperTests, PushPop_MixedBuffers) @@ -154,8 +155,9 @@ EXPECT_EQ(3072, buffer1.GetFilePosition()); EXPECT_EQ(1024, buffer1.GetRequestedDataSize()); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); EXPECT_EQ(nullptr, queue.Pop()); + EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); } ///////////////////////////////////////////////////////////////////////////////// Index: src/libchcore/Tests/TWriteBufferQueueWrapperTests.cpp =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/Tests/TWriteBufferQueueWrapperTests.cpp (.../TWriteBufferQueueWrapperTests.cpp) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/Tests/TWriteBufferQueueWrapperTests.cpp (.../TWriteBufferQueueWrapperTests.cpp) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -21,7 +21,7 @@ TSharedCountPtr spOtfBufferCount(std::make_shared>()); TWriteBufferQueueWrapper queue(spQueue, 1, spOtfBufferCount); EXPECT_EQ(0, queue.GetCount()); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); } TEST(TWriteBufferQueueWrapperTests, Pop_EmptyQueue) @@ -126,8 +126,9 @@ EXPECT_EQ(3000, buffer4.GetFilePosition()); EXPECT_EQ(1000, buffer4.GetRequestedDataSize()); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); EXPECT_EQ(nullptr, queue.Pop()); + EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); } TEST(TWriteBufferQueueWrapperTests, PushPop_MixedBuffers) @@ -177,6 +178,7 @@ EXPECT_EQ(1000, buffer2.GetFilePosition()); EXPECT_EQ(1000, buffer2.GetRequestedDataSize()); - EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); + EXPECT_SIGNALED(queue.GetHasBuffersEvent()); EXPECT_EQ(nullptr, queue.Pop()); + EXPECT_TIMEOUT(queue.GetHasBuffersEvent()); } Index: src/libchcore/libchcore.vc140.vcxproj =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/libchcore.vc140.vcxproj (.../libchcore.vc140.vcxproj) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -523,7 +523,6 @@ - Index: src/libchcore/libchcore.vc140.vcxproj.filters =================================================================== diff -u -rd99302fce795dbb5139659016a5da7948f141fb4 -rcb1a7688ad1ac1081a219c170754776e986ccc8c --- src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision d99302fce795dbb5139659016a5da7948f141fb4) +++ src/libchcore/libchcore.vc140.vcxproj.filters (.../libchcore.vc140.vcxproj.filters) (revision cb1a7688ad1ac1081a219c170754776e986ccc8c) @@ -567,9 +567,6 @@ Source Files\Tools\Threading - - Source Files\Tools\Threading - Source Files\Tools\Threading