Files
UnrealEngineUWP/Engine/Source/Developer/ProfilerService/Private/ProfilerServiceManager.h
Andriy Tylychko 327a94d1a4 StatsThread replaced by a Pipe:
* the thread was removed and its surrounding was cleaned up a bit
* ENamedThreads::StatsThread (and relatives) deprecated
* support for single-threaded execution looks a bit messy because it still have to be based on the old TaskGraph API until we convert the game thread to the new API (which will be one of the very last things)
* despite the direct usage of ENamedThreads::StatsThread from an external code is highly unlikely, to preserve backward compatiblity internally TaskGraph redirects all remaining stats tasks to StatsPipe

#rb martin.ridgers

[CL 15794122 by Andriy Tylychko in ue5-main branch]
2021-03-24 04:47:07 -04:00

247 lines
7.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "HAL/ThreadSafeCounter.h"
#include "Misc/Guid.h"
#include "IMessageContext.h"
#include "IProfilerServiceManager.h"
#include "HAL/Runnable.h"
#include "Containers/Queue.h"
#include "Containers/Ticker.h"
#include "MessageEndpoint.h"
struct FProfilerServiceCapture;
struct FProfilerServiceData2;
struct FProfilerServiceFileChunk;
struct FProfilerServicePong;
struct FProfilerServicePreview;
struct FProfilerServiceRequest;
struct FProfilerServiceSubscribe;
struct FProfilerServiceUnsubscribe;
DECLARE_LOG_CATEGORY_EXTERN(LogProfilerService, Log, All);
/**
* Thread used to read, prepare and send files through the message bus.
* Supports resending bad file chunks and basic synchronization between service and client.
*/
class FFileTransferRunnable
: public FRunnable
{
typedef TKeyValuePair<FArchive*, FMessageAddress> FReaderAndAddress;
public:
/** Default constructor. */
FFileTransferRunnable(TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe>& InMessageEndpoint);
/** Destructor. */
~FFileTransferRunnable();
// Begin FRunnable interface.
virtual bool Init();
virtual uint32 Run();
virtual void Stop()
{
StopTaskCounter.Increment();
}
virtual void Exit();
// End FRunnable interface
void EnqueueFileToSend(const FString& StatFilename, const FMessageAddress& RecipientAddress, const FGuid& ServiceInstanceId);
/** Enqueues a file chunk. */
void EnqueueFileChunkToSend(FProfilerServiceFileChunk* FileChunk, bool bTriggerWorkEvent = false);
/** Prepare the chunks to be sent through the message bus. */
void PrepareFileForSending(FProfilerServiceFileChunk*& FileChunk);
/** Removes file from the list of the active transfers, must be confirmed by the profiler client. */
void FinalizeFileSending(const FString& Filename);
/** Aborts file sending to the specified client, probably client disconnected or exited. */
void AbortFileSending(const FMessageAddress& Recipient);
/** Checks if there has been any stop requests. */
FORCEINLINE bool ShouldStop() const
{
return StopTaskCounter.GetValue() > 0;
}
protected:
/** Deletes the file reader. */
void DeleteFileReader(FReaderAndAddress& ReaderAndAddress);
/** Reads the data from the archive and generates hash. */
void ReadAndSetHash(FProfilerServiceFileChunk* FileChunk, const FProfilerFileChunkHeader& FileChunkHeader, FArchive* Reader);
/** Thread that is running this task. */
FRunnableThread* Runnable;
/** Event used to signaling that work is available. */
FEvent* WorkEvent;
/** Holds the messaging endpoint. */
TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> MessageEndpoint;
/** > 0 if we have been asked to abort work in progress at the next opportunity. */
FThreadSafeCounter StopTaskCounter;
/** Added on the main thread, processed on the async thread. */
TQueue<FProfilerServiceFileChunk*, EQueueMode::Mpsc> SendQueue;
/** Critical section used to synchronize. */
FCriticalSection SyncActiveTransfers;
/** Active transfers, stored as a filename -> reader and destination address. Assumes that filename is unique and never will be the same. */
TMap<FString, FReaderAndAddress> ActiveTransfers;
};
#if STATS
/**
* struct that holds the client information
*/
struct FClientData
{
/** Connection is active. */
bool Active;
/** Connection is previewing. */
bool Preview;
/** Default constructor. */
FClientData()
: Active(false)
, Preview(false)
{ }
};
#endif //STATS
/**
* Implements the Profile Service Manager
*/
class FProfilerServiceManager
: public TSharedFromThis<FProfilerServiceManager>
, public IProfilerServiceManager
{
public:
/** Default constructor. */
FProfilerServiceManager();
public:
//~ IProfilerServiceManager interface
virtual void StartCapture() override;
virtual void StopCapture() override;
public:
/**
* Creates a profiler service manager for shared use
*/
static TSharedPtr<IProfilerServiceManager> CreateSharedServiceManager();
/** Initializes the manager. */
void Init();
/** Shuts down the manager. */
void Shutdown();
private:
/**
* Changes the data preview state for the given client to the specified value.
*/
void SetPreviewState(const FMessageAddress& ClientAddress, const bool bRequestedPreviewState);
/** Callback for a tick, used to ping the clients */
bool HandlePing(float DeltaTime);
/** Handles FProfilerServiceCapture messages. */
void HandleServiceCaptureMessage(const FProfilerServiceCapture& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServicePong messages. */
void HandleServicePongMessage(const FProfilerServicePong& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServicePreview messages. */
void HandleServicePreviewMessage(const FProfilerServicePreview& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServiceRequest messages. */
void HandleServiceRequestMessage(const FProfilerServiceRequest& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServiceFileChunk messages. */
void HandleServiceFileChunkMessage(const FProfilerServiceFileChunk& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServiceSubscribe messages. */
void HandleServiceSubscribeMessage(const FProfilerServiceSubscribe& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles FProfilerServiceUnsubscribe messages. */
void HandleServiceUnsubscribeMessage(const FProfilerServiceUnsubscribe& Message, const TSharedRef<IMessageContext, ESPMode::ThreadSafe>& Context);
/** Handles a new frame from the stats system. Called from the stats thread. */
void HandleNewFrame(int64 Frame);
#if STATS
/** Compresses all stats data and send to the game thread. */
void CompressDataAndSendToGame(TArray<uint8>* DataToTask, int64 Frame);
/** Handles a new frame from the stats system. Called from the game thread. */
void HandleNewFrameGT(FProfilerServiceData2* ToGameThread);
#endif //STATS
void AddNewFrameHandleStatsPipe();
void RemoveNewFrameHandleStatsPipe();
/** Holds the messaging endpoint. */
TSharedPtr<FMessageEndpoint, ESPMode::ThreadSafe> MessageEndpoint;
/** Holds the session and instance identifier. */
FGuid SessionId;
FGuid InstanceId;
/** Holds the message addresses for registered clients */
TArray<FMessageAddress> PreviewClients;
#if STATS
/** Holds the client data for registered clients */
TMap<FMessageAddress, FClientData> ClientData;
#endif //STATS
/** Thread used to read, prepare and send file chunks through the message bus. */
FFileTransferRunnable* FileTransferRunnable;
/** Filename of last capture file. */
FString LastStatsFilename;
/** Size of the stats metadata. */
int32 MetadataSize;
/** Holds a delegate to be invoked for client pings */
FTickerDelegate PingDelegate;
/** Handle to the registered PingDelegate */
FDelegateHandle PingDelegateHandle;
/** Handle to the registered HandleNewFrame delegate */
FDelegateHandle NewFrameDelegateHandle;
};