From 4d5caf7d011bf73c7b90ff1d8c1cfdad817fa2f5 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Fri, 27 Feb 2026 11:47:00 +0100 Subject: Ported "lane trace" feature from UE (by way of IAX) (#771) * Ported "lane trace" feature from UE (by way of IAX) --- CHANGELOG.md | 1 + src/zencore/include/zencore/trace.h | 1 + thirdparty/trace/lane_trace.h | 146 ++++++++ thirdparty/trace/lane_trace.inl | 646 ++++++++++++++++++++++++++++++++++++ thirdparty/trace/trace.h | 22 +- 5 files changed, 805 insertions(+), 11 deletions(-) create mode 100644 thirdparty/trace/lane_trace.h create mode 100644 thirdparty/trace/lane_trace.inl diff --git a/CHANGELOG.md b/CHANGELOG.md index e555dd86f..873e88761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Feature: Added 404 page to dashboard, to make it easier to find your way back to a valid URL - Improvement: `zen oplog-import` now uses partial block requests to reduce download size - Improvement: Use latency to Cloud Storage host and Zen Cache host when calculating partial block requests +- Improvement: IAX's lane tracing - Bugfix: `--plain-progress` style progress bar should now show elapsed time correctly - Bugfix: Time spent indexing local and remote state during `zen builds download` now show the correct time diff --git a/src/zencore/include/zencore/trace.h b/src/zencore/include/zencore/trace.h index 99a565151..d17e018ea 100644 --- a/src/zencore/include/zencore/trace.h +++ b/src/zencore/include/zencore/trace.h @@ -13,6 +13,7 @@ ZEN_THIRD_PARTY_INCLUDES_START # define TRACE_IMPLEMENT 0 #endif #include +#include #undef TRACE_IMPLEMENT ZEN_THIRD_PARTY_INCLUDES_END diff --git a/thirdparty/trace/lane_trace.h b/thirdparty/trace/lane_trace.h new file mode 100644 index 000000000..170526eb2 --- /dev/null +++ b/thirdparty/trace/lane_trace.h @@ -0,0 +1,146 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#if __has_include() +# include +# include +# include +# include +#else +# define UE_LANETRACE_ENABLED 2 +# define IOSTOREHTTPCLIENT_API +#endif + +//////////////////////////////////////////////////////////////////////////////// +#if !defined(UE_LANETRACE_ENABLED) +# define UE_LANETRACE_ENABLED CPUPROFILERTRACE_ENABLED && !UE_BUILD_SHIPPING +#endif + +#if UE_LANETRACE_ENABLED +# define LANETRACE_OFF_IMPL(...) +# define UE_API IOSTOREHTTPCLIENT_API +#else +# define LANETRACE_OFF_IMPL(...) { return __VA_ARGS__ ; } +# define UE_API inline +#endif + + +//////////////////////////////////////////////////////////////////////////////// +#if UE_LANETRACE_ENABLED == 2 +namespace trace { +#endif + +//////////////////////////////////////////////////////////////////////////////// +struct FLaneTraceSpec +{ + FAnsiStringView Name; + FAnsiStringView Group = "Lanes"; + const void* Channel; + int32 Weight = 100; +}; + +class FLaneTrace; +UE_API FLaneTrace* LaneTrace_New(const FLaneTraceSpec& Spec) LANETRACE_OFF_IMPL(nullptr); +UE_API void LaneTrace_Delete(FLaneTrace* Lane) LANETRACE_OFF_IMPL(); +UE_API uint32 LaneTrace_NewScope(const FAnsiStringView& Name) LANETRACE_OFF_IMPL(1); +UE_API void LaneTrace_Enter(FLaneTrace* Lane, uint32 ScopeId) LANETRACE_OFF_IMPL(); +UE_API void LaneTrace_Change(FLaneTrace* Lane, uint32 ScopeId) LANETRACE_OFF_IMPL(); +UE_API void LaneTrace_Leave(FLaneTrace* Lane) LANETRACE_OFF_IMPL(); +UE_API void LaneTrace_LeaveAll(FLaneTrace* Lane) LANETRACE_OFF_IMPL(); + + + +//////////////////////////////////////////////////////////////////////////////// +struct FLanePostcode +{ + FLanePostcode(const void* In) : Value(UPTRINT(In)) {} + FLanePostcode(UPTRINT In) : Value(In) {} + UPTRINT Value; +}; + +class FLaneEstate; +UE_API FLaneEstate* LaneEstate_New(const FLaneTraceSpec& Spec) LANETRACE_OFF_IMPL(nullptr); +UE_API void LaneEstate_Delete(FLaneEstate* Estate) LANETRACE_OFF_IMPL(); +UE_API FLaneTrace* LaneEstate_Build(FLaneEstate* Estate, FLanePostcode Postcode) LANETRACE_OFF_IMPL(nullptr); +UE_API FLaneTrace* LaneEstate_Lookup(FLaneEstate* Estate, FLanePostcode Postcode) LANETRACE_OFF_IMPL(nullptr); +UE_API void LaneEstate_Demolish(FLaneEstate* Estate, FLanePostcode Postcode)LANETRACE_OFF_IMPL(); + +#undef LANETRACE_OFF_IMPL +#undef UE_API + + + +#if UE_LANETRACE_ENABLED + +//////////////////////////////////////////////////////////////////////////////// +class FLaneTraceScope +{ +public: + FLaneTraceScope(FLaneTrace* InLane, uint32 Scope); + FLaneTraceScope() = default; + ~FLaneTraceScope(); + FLaneTraceScope(FLaneTraceScope&& Rhs); + FLaneTraceScope& operator = (FLaneTraceScope&& Rhs); + void Change(uint32 Scope) const; + +private: + FLaneTraceScope(const FLaneTraceScope&) = delete; + FLaneTraceScope& operator = (const FLaneTraceScope&) = delete; + FLaneTrace* Lane = nullptr; +}; + +//////////////////////////////////////////////////////////////////////////////// +inline FLaneTraceScope::FLaneTraceScope(FLaneTrace* InLane, uint32 Scope) +: Lane(InLane) +{ + LaneTrace_Enter(Lane, Scope); +} + +//////////////////////////////////////////////////////////////////////////////// +inline FLaneTraceScope::~FLaneTraceScope() +{ + if (Lane) + { + LaneTrace_Leave(Lane); + } +} + +//////////////////////////////////////////////////////////////////////////////// +inline FLaneTraceScope::FLaneTraceScope(FLaneTraceScope&& Rhs) +{ + Swap(Rhs.Lane, Lane); +} + +//////////////////////////////////////////////////////////////////////////////// +inline FLaneTraceScope& FLaneTraceScope::operator = (FLaneTraceScope&& Rhs) +{ + Swap(Rhs.Lane, Lane); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +inline void FLaneTraceScope::Change(uint32 Scope) const +{ + LaneTrace_Change(Lane, Scope); +} + +#else // UE_LANETRACE_ENABLED + +class FLaneTraceScope +{ +public: + FLaneTraceScope(...) {} + void Change(uint32) const {} +}; + +#endif // UE_LANETRACE_ENABLED + +//////////////////////////////////////////////////////////////////////////////// +#if UE_LANETRACE_ENABLED == 2 +} // namespace trace +#endif + +#if defined(TRACE_IMPLEMENT) && TRACE_IMPLEMENT +# include "lane_trace.inl" +#endif diff --git a/thirdparty/trace/lane_trace.inl b/thirdparty/trace/lane_trace.inl new file mode 100644 index 000000000..abfaab027 --- /dev/null +++ b/thirdparty/trace/lane_trace.inl @@ -0,0 +1,646 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#if __has_include() +# include +# if UE_LANETRACE_ENABLED +# include +# include +# include +# include +# endif +#endif + +#if UE_LANETRACE_ENABLED + +//////////////////////////////////////////////////////////////////////////////// +#if UE_LANETRACE_ENABLED == 2 + +#include + +#define check(e) do { if ((e) == false) *(int volatile*)0 = 0; } while (false) + +struct FCriticalSection +{ + void Lock() { Inner.lock(); } + void Unlock() { Inner.unlock(); } + std::mutex Inner; +}; + +struct FScopeLock +{ + FScopeLock(FCriticalSection* Lock) : Inner(Lock->Inner) {} + std::unique_lock Inner; +}; + +namespace trace { +#endif + +// For this to work Insights would need to know it there may be a ThreadId field +#define LANETRACE_USE_V2_EVENTS 0 + +namespace LaneTraceDetail +{ + +//////////////////////////////////////////////////////////////////////////////// +UE_TRACE_EVENT_BEGIN($Trace, ThreadInfo, NoSync|Important) + UE_TRACE_EVENT_FIELD(uint32, ThreadId) + UE_TRACE_EVENT_FIELD(int32, SortHint) + UE_TRACE_EVENT_FIELD(UE::Trace::AnsiString, Name) +UE_TRACE_EVENT_END() + +UE_TRACE_EVENT_BEGIN(CpuProfiler, EventBatch) + UE_TRACE_EVENT_FIELD(uint8[], Data) + UE_TRACE_EVENT_FIELD(uint16, ThreadId) +UE_TRACE_EVENT_END() + +#if LANETRACE_USE_V2_EVENTS +UE_TRACE_EVENT_BEGIN(CpuProfiler, EventBatchV2) + UE_TRACE_EVENT_FIELD(uint8[], Data) + UE_TRACE_EVENT_FIELD(uint16, ThreadId) +UE_TRACE_EVENT_END() +#endif + +//////////////////////////////////////////////////////////////////////////////// +static int32 Encode32_7bit(int32 Value, void* __restrict Out) +{ + // Calculate the number of bytes + int32 Length = 1; + + Length += (Value >= (1 << 7)); + Length += (Value >= (1 << 14)); + Length += (Value >= (1 << 21)); + + // Add a gap every eigth bit for the continuations + int32 Ret = Value; + Ret = (Ret & 0x0000'3fff) | ((Ret & 0x0fff'c000) << 2); + Ret = (Ret & 0x007f'007f) | ((Ret & 0x3f80'3f80) << 1); + + // Set the bits indicating another byte follows + int32 Continuations = 0x0080'8080; + Continuations >>= (sizeof(Value) - Length) * 8; + Ret |= Continuations; + + ::memcpy(Out, &Ret, sizeof(Value)); + + return Length; +} + +//////////////////////////////////////////////////////////////////////////////// +static int32 Encode64_7bit(int64 Value, void* __restrict Out) +{ + // Calculate the output length + uint32 Length = 1; + Length += (Value >= (1ll << 7)); + Length += (Value >= (1ll << 14)); + Length += (Value >= (1ll << 21)); + Length += (Value >= (1ll << 28)); + Length += (Value >= (1ll << 35)); + Length += (Value >= (1ll << 42)); + Length += (Value >= (1ll << 49)); + + // Add a gap every eigth bit for the continuations + int64 Ret = Value; + Ret = (Ret & 0x0000'0000'0fff'ffffull) | ((Ret & 0x00ff'ffff'f000'0000ull) << 4); + Ret = (Ret & 0x0000'3fff'0000'3fffull) | ((Ret & 0x0fff'c000'0fff'c000ull) << 2); + Ret = (Ret & 0x007f'007f'007f'007full) | ((Ret & 0x3f80'3f80'3f80'3f80ull) << 1); + + // Set the bits indicating another byte follows + int64 Continuations = 0x0080'8080'8080'8080ull; + Continuations >>= (sizeof(Value) - Length) * 8; + Ret |= Continuations; + + ::memcpy(Out, &Ret, sizeof(Value)); + + return Length; +} + +//////////////////////////////////////////////////////////////////////////////// +static uint64 TimeGetTimestamp() +{ +#if UE_LANETRACE_ENABLED != 2 + return FPlatformTime::Cycles64(); +#else + return trace::detail::TimeGetTimestamp(); +#endif +} + + + +//////////////////////////////////////////////////////////////////////////////// +class FScopeBuffer +{ +public: + FScopeBuffer(UE::Trace::FChannel& InChannel); + void SetThreadId(uint32 Value); + bool IsInScope() const; + uint32 GetDepth() const; + void Flush(bool Force=false); + void Enter(uint64 Timestamp, uint32 ScopeId); + void Leave(uint64 Timestamp); + +private: + enum + { + BufferSize = 128, + Overflow = 24, + EnterLsb = 1, + LeaveLsb = 0, + TraceEventBatchVer = 1 + LANETRACE_USE_V2_EVENTS, + }; + uint64 LastTimestamp = 0; + uint64 PrevTimestamp = 0; + uint8* Cursor = Buffer; + UE::Trace::FChannel& Channel; + uint32 ThreadIdOverride = 0; + uint16 Depth = 0; + uint8 Buffer[BufferSize]; +}; + +//////////////////////////////////////////////////////////////////////////////// +FScopeBuffer::FScopeBuffer(UE::Trace::FChannel& InChannel) +: Channel(InChannel) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBuffer::SetThreadId(uint32 Value) +{ + ThreadIdOverride = Value; +} + +//////////////////////////////////////////////////////////////////////////////// +bool FScopeBuffer::IsInScope() const +{ + return GetDepth() > 0; +} + +//////////////////////////////////////////////////////////////////////////////// +uint32 FScopeBuffer::GetDepth() const +{ + return Depth; +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBuffer::Flush(bool Force) +{ + if (Cursor == Buffer) + { + return; + } + + if (Depth > 0 && !Force && (Cursor <= (Buffer + BufferSize - Overflow))) + { + return; + } + + if (TraceEventBatchVer == 1) + { + UE_TRACE_LOG(CpuProfiler, EventBatch, Channel) + << EventBatch.ThreadId(uint16(ThreadIdOverride)) + << EventBatch.Data(Buffer, uint32(ptrdiff_t(Cursor - Buffer))); + } +#if LANETRACE_USE_V2_EVENTS + else + { + UE_TRACE_LOG(CpuProfiler, EventBatchV2, Channel) + << EventBatchV2.ThreadId(uint16(ThreadIdOverride)) + << EventBatchV2.Data(Buffer, uint32(ptrdiff_t(Cursor - Buffer))); + + // Both protocols should really do this rebase but it make analysis go + // bonkers and I'm not looking into that right now + PrevTimestamp = 0; + } +#endif + + LastTimestamp = 0; + PrevTimestamp = 0; + + Cursor = Buffer; +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBuffer::Enter(uint64 Timestamp, uint32 ScopeId) +{ + check(Timestamp >= LastTimestamp); + LastTimestamp = Timestamp; + + PrevTimestamp += (Timestamp -= PrevTimestamp); + enum { Shift = (TraceEventBatchVer == 1) ? 1 : 2 }; + Cursor += Encode64_7bit((Timestamp << Shift) | EnterLsb, Cursor); + Cursor += Encode32_7bit(ScopeId, Cursor); + Depth++; +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBuffer::Leave(uint64 Timestamp) +{ + check(Timestamp >= LastTimestamp); + LastTimestamp = Timestamp; + + if (Depth == 0) + { + return; + } + + PrevTimestamp += (Timestamp -= PrevTimestamp); + enum { Shift = (TraceEventBatchVer == 1) ? 1 : 2 }; + Cursor += Encode64_7bit((Timestamp << Shift) | LeaveLsb, Cursor); + Depth--; +} + + + +//////////////////////////////////////////////////////////////////////////////// +struct FLoctight +{ + struct FScope + { + FScope() = default; + ~FScope(); + FScope(FScope&& Rhs); + FScope(const FScope&) = delete; + FScope& operator = (const FScope&) = delete; + FScope& operator = (FScope&&) = delete; + FCriticalSection* Outer = nullptr; + }; + FScope Scope() const; + mutable FCriticalSection Loch; +}; + +//////////////////////////////////////////////////////////////////////////////// +FLoctight::FScope::~FScope() +{ + if (Outer) + { + Outer->Unlock(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +FLoctight::FScope::FScope(FScope&& Rhs) +{ + Swap(Outer, Rhs.Outer); +} + +//////////////////////////////////////////////////////////////////////////////// +FLoctight::FScope FLoctight::Scope() const +{ + Loch.Lock(); + FScope Ret; + Ret.Outer = &Loch; + return Ret; +} + + + +//////////////////////////////////////////////////////////////////////////////// +class FScopeBufferTs + : protected FLoctight + , protected FScopeBuffer +{ +public: + void SetThreadId(uint32 Value); + bool IsInScope() const; + void Flush(bool Force=false); + void Enter(uint32 ScopeId); + void Leave(); +}; + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBufferTs::SetThreadId(uint32 Value) +{ + FScope _ = Scope(); + FScopeBuffer::SetThreadId(Value); +} + +//////////////////////////////////////////////////////////////////////////////// +bool FScopeBufferTs::IsInScope() const +{ + FScope _ = Scope(); + return FScopeBuffer::IsInScope(); +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBufferTs::Flush(bool Force) +{ + FScope _ = Scope(); + FScopeBuffer::Flush(Force); +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBufferTs::Enter(uint32 ScopeId) +{ + uint64 Timestamp = TimeGetTimestamp(); + FScope _ = Scope(); + FScopeBuffer::Enter(Timestamp, ScopeId); +} + +//////////////////////////////////////////////////////////////////////////////// +void FScopeBufferTs::Leave() +{ + uint64 Timestamp = TimeGetTimestamp(); + FScope _ = Scope(); + FScopeBuffer::Leave(Timestamp); +} + + + +//////////////////////////////////////////////////////////////////////////////// +class FLane +{ +public: + FLane(const FLaneTraceSpec& Spec); + ~FLane(); + static uint32 NewScope(const FAnsiStringView& Name); + void Enter(uint32 ScopeId); + void Change(uint32 ScopeId); + void Leave(); + void LeaveAll(); + +private: + FScopeBuffer Buffer; +}; + +//////////////////////////////////////////////////////////////////////////////// +FLane::FLane(const FLaneTraceSpec& Spec) +: Buffer(*(UE::Trace::FChannel*)(Spec.Channel)) +{ + static uint32 volatile NextId = 0; + uint32 Id = UE::Trace::Private::AtomicAddRelaxed(&NextId, 1u) + 1; + Id += 2 << 10; + + uint32 NameSize = uint32(Spec.Name.Len()); + UE_TRACE_LOG($Trace, ThreadInfo, true, NameSize) + << ThreadInfo.ThreadId(Id) + << ThreadInfo.SortHint(Spec.Weight) + << ThreadInfo.Name(Spec.Name.GetData(), NameSize); + + Buffer.SetThreadId(Id); +} + +//////////////////////////////////////////////////////////////////////////////// +FLane::~FLane() +{ + Buffer.Flush(true); +} + +//////////////////////////////////////////////////////////////////////////////// +uint32 FLane::NewScope(const FAnsiStringView& Name) +{ +#if UE_LANETRACE_ENABLED != 2 + return FCpuProfilerTrace::OutputEventType(Name.GetData(), "", 0u); +#else + return uint32(ScopeNew(Name)); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +void FLane::Enter(uint32 ScopeId) +{ + uint64 Timestamp = TimeGetTimestamp(); + Buffer.Enter(Timestamp, ScopeId); + Buffer.Flush(false); +} + +//////////////////////////////////////////////////////////////////////////////// +void FLane::Change(uint32 ScopeId) +{ + uint64 Timestamp = TimeGetTimestamp(); + Buffer.Leave(Timestamp); + Buffer.Enter(Timestamp, ScopeId); + Buffer.Flush(false); +} + +//////////////////////////////////////////////////////////////////////////////// +void FLane::Leave() +{ + uint64 Timestamp = TimeGetTimestamp(); + Buffer.Leave(Timestamp); + Buffer.Flush(false); +} + +//////////////////////////////////////////////////////////////////////////////// +void FLane::LeaveAll() +{ + uint64 Timestamp = TimeGetTimestamp(); + while (Buffer.IsInScope()) + { + Buffer.Leave(Timestamp); + } + Buffer.Flush(true); +} + +} // namespace LaneTraceDetail + + + +//////////////////////////////////////////////////////////////////////////////// +class FLaneTrace + : public LaneTraceDetail::FLane +{ + using LaneTraceDetail::FLane::FLane; +}; + +//////////////////////////////////////////////////////////////////////////////// +FLaneTrace* LaneTrace_New(const FLaneTraceSpec& Spec) +{ + return new FLaneTrace(Spec); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneTrace_Delete(FLaneTrace* Lane) +{ + delete Lane; +} + +//////////////////////////////////////////////////////////////////////////////// +uint32 LaneTrace_NewScope(const FAnsiStringView& Name) +{ + return FLaneTrace::NewScope(Name); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneTrace_Enter(FLaneTrace* Lane, uint32 ScopeId) +{ + Lane->Enter(ScopeId); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneTrace_Change(FLaneTrace* Lane, uint32 ScopeId) +{ + Lane->Change(ScopeId); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneTrace_Leave(FLaneTrace* Lane) +{ + Lane->Leave(); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneTrace_LeaveAll(FLaneTrace* Lane) +{ + Lane->LeaveAll(); +} + + + +namespace LaneTraceDetail +{ + +//////////////////////////////////////////////////////////////////////////////// +class FEstate +{ +public: + FEstate(const FLaneTraceSpec& Spec); + ~FEstate(); + FLaneTrace* Build(UPTRINT Postcode); + FLaneTrace* Lookup(UPTRINT Postcode); + void Demolish(UPTRINT Postcode); + +private: + struct FEntry + { + UPTRINT Postcode = 0; + FLaneTrace* Lane = nullptr; + }; + + enum { GROWTH_SIZE = 4 }; + + FLaneTraceSpec LaneSpec; + FCriticalSection Lock; + TArray Directory; +}; + +//////////////////////////////////////////////////////////////////////////////// +FEstate::FEstate(const FLaneTraceSpec& InSpec) +: LaneSpec(InSpec) +{ + Directory.SetNum(GROWTH_SIZE); +} + +//////////////////////////////////////////////////////////////////////////////// +FEstate::~FEstate() +{ + for (FEntry& Entry : Directory) + { + if (Entry.Lane != nullptr) + { + LaneTrace_Delete(Entry.Lane); + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +FLaneTrace* FEstate::Build(UPTRINT Postcode) +{ + auto UseEstate = [this] (UPTRINT Postcode, FEntry& Entry) + { + Entry.Postcode = Postcode; + if (Entry.Lane == nullptr) + { + Entry.Lane = LaneTrace_New(LaneSpec); + } + + return Entry.Lane; + }; + + FScopeLock _(&Lock); + + for (FEntry& Entry : Directory) + { + if (Entry.Postcode == 0) + { + return UseEstate(Postcode, Entry); + } + } + + int32 NextSize = Directory.Num() + GROWTH_SIZE; + Directory.SetNum(NextSize); + return UseEstate(Postcode, Directory[NextSize - GROWTH_SIZE]); +} + +//////////////////////////////////////////////////////////////////////////////// +FLaneTrace* FEstate::Lookup(UPTRINT Postcode) +{ + FScopeLock _(&Lock); + + for (const FEntry& Entry : Directory) + { + if (Entry.Postcode == Postcode) + { + return Entry.Lane; + } + } + + checkf(false, TEXT("Invalid/unknown postcode given, unable to find estate: %llx"), Postcode); + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +void FEstate::Demolish(UPTRINT Postcode) +{ + FScopeLock _(&Lock); + + for (FEntry& Entry : Directory) + { + if (Entry.Postcode == Postcode) + { + LaneTrace_LeaveAll(Entry.Lane); + Entry.Postcode = 0; + return; + } + } + + checkf(false, TEXT("Invalid/unknown postcode given, unable to demolish estate: %llx"), Postcode); +} + +} // namespace LaneTraceDetail + + + +//////////////////////////////////////////////////////////////////////////////// +class FLaneEstate + : public LaneTraceDetail::FEstate +{ +public: + using LaneTraceDetail::FEstate::FEstate; +}; + +//////////////////////////////////////////////////////////////////////////////// +FLaneEstate*LaneEstate_New(const FLaneTraceSpec& Spec) +{ + return new FLaneEstate(Spec); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneEstate_Delete(FLaneEstate* Estate) +{ + delete Estate; +} + +//////////////////////////////////////////////////////////////////////////////// +FLaneTrace* LaneEstate_Build(FLaneEstate* Estate, FLanePostcode Postcode) +{ + return Estate->Build(Postcode.Value); +} + +//////////////////////////////////////////////////////////////////////////////// +FLaneTrace* LaneEstate_Lookup(FLaneEstate* Estate, FLanePostcode Postcode) +{ + return Estate->Lookup(Postcode.Value); +} + +//////////////////////////////////////////////////////////////////////////////// +void LaneEstate_Demolish(FLaneEstate* Estate, FLanePostcode Postcode) +{ + return Estate->Demolish(Postcode.Value); +} + +#undef LANETRACE_UNTESTED + +#if UE_LANETRACE_ENABLED == 2 +} // namespace trace +#endif + +#endif // UE_LANETRACE_ENABLED diff --git a/thirdparty/trace/trace.h b/thirdparty/trace/trace.h index a1fce80a6..0835781ba 100644 --- a/thirdparty/trace/trace.h +++ b/thirdparty/trace/trace.h @@ -190,7 +190,7 @@ struct TArray : public std::vector { using Super = std::vector; - using Super::vector; + using Super::Super; using Super::back; using Super::begin; using Super::clear; @@ -260,7 +260,7 @@ struct TStringViewAdapter : public std::basic_string_view { using Super = std::basic_string_view; - using Super::basic_string_view; + using Super::Super; using Super::size; using Super::data; size_t Len() const { return size(); } @@ -596,8 +596,8 @@ namespace UE { namespace Trace { enum AnsiString {}; enum WideString {}; -template -struct TEventRef +template +struct TEventRef { using ReferenceType = IdType; TEventRef(IdType InId, uint32 InTypeId) @@ -632,7 +632,7 @@ inline uint64 TEventRef::GetHash() const return (uint64(RefTypeId) << 32) ^ Id; } typedef TEventRef FEventRef8; -typedef TEventRef FEventRef16; +typedef TEventRef FEventRef16; typedef TEventRef FEventRef32; typedef TEventRef FEventRef64; template @@ -653,7 +653,7 @@ struct FChannelInfo; typedef void* AllocFunc(SIZE_T, uint32); typedef void FreeFunc(void*, SIZE_T); typedef void ChannelIterFunc(const ANSICHAR*, bool, void*); -/* The callback provides information about a channel and a user provided pointer. +/* The callback provides information about a channel and a user provided pointer. Returning false from the callback will stop the enumeration */ typedef bool ChannelIterCallback(const FChannelInfo& Info, void*/*User*/); struct FStatistics @@ -673,7 +673,7 @@ struct FSendFlags }; UE_TRACE_API void SetMemoryHooks(AllocFunc Alloc, FreeFunc Free) UE_TRACE_IMPL(); UE_TRACE_API void Initialize(const FInitializeDesc& Desc) UE_TRACE_IMPL(); -UE_TRACE_API void StartWorkerThread() UE_TRACE_IMPL(); +UE_TRACE_API void StartWorkerThread() UE_TRACE_IMPL(); UE_TRACE_API void Shutdown() UE_TRACE_IMPL(); UE_TRACE_API void Update() UE_TRACE_IMPL(); UE_TRACE_API void GetStatistics(FStatistics& Out) UE_TRACE_IMPL(); @@ -718,7 +718,7 @@ struct FChannelInfo bool bIsEnabled; bool bIsReadOnly; }; -typedef void ChannelIterFunc(const ANSICHAR*, bool, void*); +typedef void ChannelIterFunc(const ANSICHAR*, bool, void*); typedef bool ChannelIterCallback(const FChannelInfo& OutChannelInfo, void*); /* A named channel which can be used to filter trace events. Channels can be @@ -1277,7 +1277,7 @@ struct FNewEventEvent struct { uint16 Offset; - uint16 RefUid; + uint16 RefUid; uint8 TypeInfo; uint8 NameSize; } Reference; @@ -2519,7 +2519,7 @@ FChannel* FChannel::FindChannel(const ANSICHAR* ChannelName) } return nullptr; } -void FChannel::EnumerateChannels(ChannelIterFunc Func, void* User) +void FChannel::EnumerateChannels(ChannelIterFunc Func, void* User) { using namespace Private; FChannel* ChannelLists[] = @@ -4985,7 +4985,7 @@ UPTRINT TcpSocketConnect(const ANSICHAR* Host, uint16 Port) { struct FAddrInfoPtr { - ~FAddrInfoPtr() + ~FAddrInfoPtr() { if (Value != nullptr) { -- cgit v1.2.3