From bda9a21f40a368df0a3e219e645bd38d4f6d586f Mon Sep 17 00:00:00 2001 From: n0lavar Date: Tue, 1 Aug 2023 21:23:20 +0300 Subject: [PATCH] async prototype --- public/client/TracyAsyncEvents.hpp | 127 +++++++++++++++++++++++++++++ public/client/TracyAwaitable.hpp | 108 ++++++++++++++++++++++++ public/client/TracyProfiler.hpp | 5 ++ public/client/TracyResult.hpp | 61 ++++++++++++++ public/tracy/TracyAsync.hpp | 13 +++ 5 files changed, 314 insertions(+) create mode 100644 public/client/TracyAsyncEvents.hpp create mode 100644 public/client/TracyAwaitable.hpp create mode 100644 public/client/TracyResult.hpp create mode 100644 public/tracy/TracyAsync.hpp diff --git a/public/client/TracyAsyncEvents.hpp b/public/client/TracyAsyncEvents.hpp new file mode 100644 index 00000000..93d2ab73 --- /dev/null +++ b/public/client/TracyAsyncEvents.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include "TracyProfiler.hpp" + +#define DEBUG_TEMP 1 +#if DEBUG_TEMP +#include +#include +#include +#endif + +namespace tracy +{ + class AsyncScopedZone; + struct SourceLocationData; + inline thread_local tracy::AsyncScopedZone* g_pCurrentZone = nullptr; + + void StartAsyncEvent(const AsyncScopedZone* pAsyncScopedZone +#if DEBUG_TEMP + , size_t nFiber +#endif + ); + void StopAsyncEvent(); + + class AsyncScopedZone + { + public: + AsyncScopedZone(const SourceLocationData* pSourceLocation +#if DEBUG_TEMP + , size_t nFiber +#endif + ); + ~AsyncScopedZone(); + + // private: + const SourceLocationData* const m_pSourceLocation = nullptr; +#if DEBUG_TEMP + const size_t m_nFiber = -1; +#endif + AsyncScopedZone* m_pParent = nullptr; + }; +} + + +tracy_force_inline void tracy::StartAsyncEvent(const AsyncScopedZone* pAsyncScopedZone +#if DEBUG_TEMP + , size_t nFiber +#endif +) +{ + TracyQueuePrepare( QueueType::ZoneBegin ); + MemWrite( &item->zoneBegin.time, Profiler::GetTime() ); + MemWrite( &item->zoneBegin.srcloc, (uint64_t)pAsyncScopedZone->m_pSourceLocation ); + TracyQueueCommit( zoneBeginThread ); + +#if DEBUG_TEMP + if (nFiber == 0) + { + const std::string sMessage = "fiber: " + std::to_string(nFiber); + tracy::Profiler::Message(sMessage.c_str(), sMessage.size(), 0); + } +#endif +} + +tracy_force_inline void tracy::StopAsyncEvent() +{ + TracyQueuePrepare(QueueType::ZoneEnd); + MemWrite(&item->zoneEnd.time, Profiler::GetTime()); + TracyQueueCommit(zoneEndThread); +} + +tracy_force_inline tracy::AsyncScopedZone::AsyncScopedZone(const SourceLocationData* pSourceLocation +#if DEBUG_TEMP + , size_t nFiber +#endif +) + : m_pSourceLocation(pSourceLocation) +#if DEBUG_TEMP + , m_nFiber(nFiber) +#endif +{ + if (g_pCurrentZone) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "AsyncScopedZone: constructor, StopAsyncEvent" + << ", location: " << g_pCurrentZone->m_pSourceLocation->function + << ", fiber: " << nFiber + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + m_pParent = g_pCurrentZone; + StopAsyncEvent(); + } + +#if DEBUG_TEMP + std::osyncstream(std::cout) << "AsyncScopedZone: constructor, StartAsyncEvent" + << ", location: " << pSourceLocation->function + << ", fiber: " << nFiber + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + g_pCurrentZone = this; + StartAsyncEvent(this +#if DEBUG_TEMP + , nFiber +#endif + ); +} + +tracy_force_inline tracy::AsyncScopedZone::~AsyncScopedZone() +{ + if (g_pCurrentZone) + { + StopAsyncEvent(); + g_pCurrentZone = g_pCurrentZone->m_pParent; + if (g_pCurrentZone) + StartAsyncEvent(g_pCurrentZone +#if DEBUG_TEMP + , g_pCurrentZone->m_nFiber +#endif + ); + } +} diff --git a/public/client/TracyAwaitable.hpp b/public/client/TracyAwaitable.hpp new file mode 100644 index 00000000..266d2a8c --- /dev/null +++ b/public/client/TracyAwaitable.hpp @@ -0,0 +1,108 @@ +#pragma once + +#include "TracyAsyncEvents.hpp" + +#include + +namespace tracy +{ + template + class Awaitable : public BaseAwaitableType + { + public: + Awaitable(BaseAwaitableType baseAwaitable); +#if DEBUG_TEMP + ~Awaitable(); +#endif + auto await_suspend(auto handle); + auto await_resume(); + + private: + AsyncScopedZone* m_pCurrentZone = nullptr; + }; + + template + Awaitable::Awaitable(BaseAwaitableType baseAwaitable) + : BaseAwaitableType(std::move(baseAwaitable)) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Awaitable: constructor" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + } + +#if DEBUG_TEMP + template + Awaitable::~Awaitable() + { + std::osyncstream(std::cout) << "Awaitable: destructor" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; + } +#endif + + template + auto Awaitable::await_suspend(auto handle) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Awaitable: await_suspend" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + if (g_pCurrentZone) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Awaitable: await_suspend, StopAsyncEvent" + << ", location: " << g_pCurrentZone->m_pSourceLocation->function + << ", fiber: " << g_pCurrentZone->m_nFiber + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + m_pCurrentZone = g_pCurrentZone; + g_pCurrentZone = nullptr; + StopAsyncEvent(); + } + + return BaseAwaitableType::await_suspend(handle); + } + + template + auto Awaitable::await_resume() + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Awaitable: await_resume" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + if (m_pCurrentZone) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Awaitable: await_resume, StartAsyncEvent" + << ", location: " << m_pCurrentZone->m_pSourceLocation->function + << ", fiber: " << m_pCurrentZone->m_nFiber + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + StartAsyncEvent(m_pCurrentZone +#if DEBUG_TEMP + , m_pCurrentZone->m_nFiber +#endif + ); + g_pCurrentZone = m_pCurrentZone; + m_pCurrentZone = nullptr; + } + + return BaseAwaitableType::await_resume(); + } +} diff --git a/public/client/TracyProfiler.hpp b/public/client/TracyProfiler.hpp index 9b8f8433..326cdb34 100644 --- a/public/client/TracyProfiler.hpp +++ b/public/client/TracyProfiler.hpp @@ -237,6 +237,11 @@ public: return m_zoneId.fetch_add( 1, std::memory_order_relaxed ); } + tracy_force_inline uint64_t GetFrame() const + { + return m_frameCount.load( std::memory_order_relaxed ); + } + static tracy_force_inline QueueItem* QueueSerial() { auto& p = GetProfiler(); diff --git a/public/client/TracyResult.hpp b/public/client/TracyResult.hpp new file mode 100644 index 00000000..d6b11325 --- /dev/null +++ b/public/client/TracyResult.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include "TracyAwaitable.hpp" + +#include + +namespace tracy +{ + template + class Result : public BaseResultType + { + public: + Result(BaseResultType&& result); +#if DEBUG_TEMP + ~Result(); +#endif + auto operator co_await(); + }; + + template + Result::Result(BaseResultType&& result) + : BaseResultType(std::forward(result)) + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Result: constructor" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + } + +#if DEBUG_TEMP + template + Result::~Result() + { + std::osyncstream(std::cout) << "Result: destructor" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; + } +#endif + + template + auto Result::operator co_await() + { +#if DEBUG_TEMP + std::osyncstream(std::cout) << "Result: operator co_await" + << ", thread id: " << std::this_thread::get_id() + << ", frame: " << GetProfiler().GetFrame() + << std::endl; +#endif + + return Awaitable(BaseResultType::operator co_await()); + } +} + +template class original_result, class type, class... arguments> +struct std::coroutine_traits>, arguments...> +{ + using promise_type = typename coroutine_traits, arguments...>::promise_type; +}; diff --git a/public/tracy/TracyAsync.hpp b/public/tracy/TracyAsync.hpp new file mode 100644 index 00000000..79fdce45 --- /dev/null +++ b/public/tracy/TracyAsync.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "../client/TracyResult.hpp" + +#if DEBUG_TEMP +#define ZoneAsyncC(color, fiber) \ + static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; \ + tracy::AsyncScopedZone ___tracy_async_scoped_zone( &TracyConcat(__tracy_source_location, TracyLine), fiber ); +#else +#define ZoneAsyncC(color, fiber) \ + static constexpr tracy::SourceLocationData TracyConcat(__tracy_source_location,TracyLine) { nullptr, TracyFunction, TracyFile, (uint32_t)TracyLine, color }; \ + tracy::AsyncScopedZone ___tracy_async_scoped_zone( &TracyConcat(__tracy_source_location, TracyLine) ); +#endif