carb/PluginInitializers.h

File members: carb/PluginInitializers.h

// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

#pragma once

#include "Defines.h"

#include <atomic>

namespace carb
{
#ifndef DOXYGEN_BUILD
void pluginDeinitialize();

namespace detail
{

inline bool& initialized() noexcept
{
    static bool init = false;
    return init;
}

class Deinit
{
private:
    friend void ::carb::pluginDeinitialize();

    static std::atomic<Deinit*>& chain() noexcept
    {
        static std::atomic<Deinit*> s_chain{ nullptr };
        return s_chain;
    }
    static void call() noexcept
    {
        auto p = chain().load(std::memory_order_relaxed);
        for (decltype(p) next; p; p = next)
        {
            next = p->m_next;
#    if CARB_EXCEPTIONS_ENABLED
            try
            {
                p->deinit();
            }
            catch (...)
            {
            }
#    else
            p->deinit();
#    endif
        }
    }

    Deinit* m_next{ nullptr };

protected:
    virtual void deinit() = 0;

    Deinit() : m_next(chain().load(std::memory_order_relaxed))
    {
        while (!chain().compare_exchange_strong(m_next, this))
        {
        }
    }
};

} // namespace detail
#endif
struct Framework;
namespace logging
{
void registerLoggingForClient() noexcept;
void deregisterLoggingForClient() noexcept;
} // namespace logging
namespace profiler
{
void registerProfilerForClient() noexcept;
void deregisterProfilerForClient() noexcept;
} // namespace profiler
namespace assert
{
void registerAssertForClient() noexcept;
void deregisterAssertForClient() noexcept;
} // namespace assert
namespace l10n
{
void registerLocalizationForClient() noexcept;
void deregisterLocalizationForClient() noexcept;
} // namespace l10n

inline void pluginInitialize()
{
    if (detail::initialized())
        return;
    carb::detail::initialized() = true;

    logging::registerLoggingForClient();
    profiler::registerProfilerForClient();
    assert::registerAssertForClient();
    l10n::registerLocalizationForClient();
}

inline void pluginDeinitialize()
{
    if (!detail::initialized())
        return;
    carb::detail::initialized() = false;

    // Execute the deinit chain
    detail::Deinit::call();

    assert::deregisterAssertForClient();
    profiler::deregisterProfilerForClient();
    logging::deregisterLoggingForClient();
    l10n::deregisterLocalizationForClient();
}

} // namespace carb