Files
UnrealEngineUWP/Engine/Source/Developer/TraceAnalysis/Private/Analysis/Processor.cpp
martin ridgers 27c78d0d4b Over time the framework behind the analysis of traces has grown reactively and organically without little thought to structure. The monolithic class has been refactored to derive some structure that will ease future maintenance (and protocol changes in particular).
#rb johan.berg
#jira ue-114532
#rnx

#ROBOMERGE-SOURCE: CL 16979281 in //UE5/Main/...
#ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v838-16927207)

[CL 16979283 by martin ridgers in ue5-release-engine-test branch]
2021-07-28 02:24:48 -04:00

129 lines
3.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Processor.h"
#include "HAL/Event.h"
#include "HAL/PlatformProcess.h"
#include "HAL/RunnableThread.h"
#include "StreamReader.h"
#include "Templates/UnrealTemplate.h"
#include "Trace/DataStream.h"
namespace UE {
namespace Trace {
////////////////////////////////////////////////////////////////////////////////
FAnalysisProcessor::FImpl::FImpl(IInDataStream& InDataStream, TArray<IAnalyzer*>&& InAnalyzers)
: AnalysisEngine(Forward<TArray<IAnalyzer*>>(InAnalyzers))
, DataStream(InDataStream)
, StopEvent(FPlatformProcess::GetSynchEventFromPool(true))
, UnpausedEvent(FPlatformProcess::GetSynchEventFromPool(true))
{
Thread = FRunnableThread::Create(this, TEXT("TraceAnalysis"));
PauseAnalysis(false);
}
////////////////////////////////////////////////////////////////////////////////
FAnalysisProcessor::FImpl::~FImpl()
{
StopAnalysis();
FPlatformProcess::ReturnSynchEventToPool(UnpausedEvent);
FPlatformProcess::ReturnSynchEventToPool(StopEvent);
}
////////////////////////////////////////////////////////////////////////////////
uint32 FAnalysisProcessor::FImpl::Run()
{
AnalysisEngine.Begin();
FStreamBuffer Buffer;
while (!StopEvent->Wait(0, true))
{
UnpausedEvent->Wait();
int32 BytesRead = Buffer.Fill([&] (uint8* Out, uint32 Size)
{
return DataStream.Read(Out, Size);
});
if (BytesRead <= 0)
{
break;
}
if (!AnalysisEngine.OnData(Buffer))
{
break;
}
}
AnalysisEngine.End();
bComplete = true;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
bool FAnalysisProcessor::FImpl::IsActive() const
{
return !bComplete;
}
////////////////////////////////////////////////////////////////////////////////
void FAnalysisProcessor::FImpl::StopAnalysis()
{
if (IsActive())
{
StopEvent->Trigger();
WaitOnAnalysis();
}
}
////////////////////////////////////////////////////////////////////////////////
void FAnalysisProcessor::FImpl::WaitOnAnalysis()
{
if (IsActive())
{
Thread->Kill(true);
delete Thread;
Thread = nullptr;
}
}
////////////////////////////////////////////////////////////////////////////////
void FAnalysisProcessor::FImpl::PauseAnalysis(bool bState)
{
if (IsActive())
{
bState ? UnpausedEvent->Reset() : UnpausedEvent->Trigger();
}
}
////////////////////////////////////////////////////////////////////////////////
bool FAnalysisProcessor::IsActive() const { return (Impl != nullptr) ? Impl->IsActive() : false; }
void FAnalysisProcessor::Stop() { if (Impl != nullptr) { Impl->StopAnalysis(); } }
void FAnalysisProcessor::Wait() { if (Impl != nullptr) { Impl->WaitOnAnalysis(); } }
void FAnalysisProcessor::Pause(bool bState) { if (Impl != nullptr) { Impl->PauseAnalysis(bState); } }
////////////////////////////////////////////////////////////////////////////////
FAnalysisProcessor::FAnalysisProcessor(FAnalysisProcessor&& Rhs)
{
this->operator = (MoveTemp(Rhs));
}
////////////////////////////////////////////////////////////////////////////////
FAnalysisProcessor& FAnalysisProcessor::operator = (FAnalysisProcessor&& Rhs)
{
Swap(Impl, Rhs.Impl);
return *this;
}
////////////////////////////////////////////////////////////////////////////////
FAnalysisProcessor::~FAnalysisProcessor()
{
delete Impl;
}
} // namespace Trace
} // namespace UE