Repository: microsoft/terminal
File: src/renderer/base/renderer.cpp (C++)

Code before:
// - pEngine - The output engine for targeting each rendering frame
// Return Value:
// - An instance of a Renderer.
Renderer::Renderer(IRenderData* pData,
                   _In_reads_(cEngines) IRenderEngine** const rgpEngines,
                   const size_t cEngines,
                   std::unique_ptr<IRenderThread> thread) :
    _pData(THROW_HR_IF_NULL(E_INVALIDARG, pData)),
    _pThread{ std::move(thread) },
    _viewport{ pData->GetViewport() }
{
    for (size_t i = 0; i < cEngines; i++)
    {
        AddRenderEngine(rgpEngines[i]);
    }
}

// Routine Description:
// - Destroys an instance of a renderer
// Arguments:
// - <none>
// Return Value:
// - <none>
Renderer::~Renderer()
{
    // IRenderThread blocks until it has shut down.
    _pThread.reset();
}

// Routine Description:
// - Walks through the console data structures to compose a new frame based on the data that has changed since last call and outputs it to the connected rendering engine.
// Arguments:
// - <none>
// Return Value:
// - HRESULT S_OK, GDI error, Safe Math error, or state/argument errors.
[[nodiscard]] HRESULT Renderer::PaintFrame()
{
    FOREACH_ENGINE(pEngine)
    {
        auto tries = maxRetriesForRenderEngine;
        while (tries > 0)
        {
            const auto hr = _PaintFrameForEngine(pEngine);
            if (E_PENDING == hr)
            {
                if (--tries == 0)
                {
                    // Stop trying.
                    _pThread->DisablePainting();
                    if (_pfnRendererEnteredErrorState)
                    {

Review comment (suggestion):
Worried about removing the `_destructing` member. Those things are usually workarounds for poor threading, and need to stay around until the threading is fixed :/

Code after:
// - pEngine - The output engine for targeting each rendering frame
// Return Value:
// - An instance of a Renderer.
Renderer::Renderer(IRenderData* pData,
                   _In_reads_(cEngines) IRenderEngine** const rgpEngines,
                   const size_t cEngines,
                   std::unique_ptr<IRenderThread> thread) :
    _pData(THROW_HR_IF_NULL(E_INVALIDARG, pData)),
    _pThread{ std::move(thread) },
    _viewport{ pData->GetViewport() }
{
    for (size_t i = 0; i < cEngines; i++)
    {
        AddRenderEngine(rgpEngines[i]);
    }
}

// Routine Description:
// - Destroys an instance of a renderer
// Arguments:
// - <none>
// Return Value:
// - <none>
Renderer::~Renderer()
{
    // IRenderThread blocks until it has shut down.
    _destructing = true;
    _pThread.reset();
}

// Routine Description:
// - Walks through the console data structures to compose a new frame based on the data that has changed since last call and outputs it to the connected rendering engine.
// Arguments:
// - <none>
// Return Value:
// - HRESULT S_OK, GDI error, Safe Math error, or state/argument errors.
[[nodiscard]] HRESULT Renderer::PaintFrame()
{
    FOREACH_ENGINE(pEngine)
    {
        auto tries = maxRetriesForRenderEngine;
        while (tries > 0)
        {
            if (_destructing)
            {
                return S_FALSE;
            }

            const auto hr = _PaintFrameForEngine(pEngine);
            if (E_PENDING == hr)
            {