EventSubscribers.h#

Fully qualified name: omni/kit/EventSubscribers.h

File members: omni/kit/EventSubscribers.h

// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: LicenseRef-NvidiaProprietary
//
// NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
// property and proprietary rights in and to this material, related
// documentation and any modifications thereto. Any use, reproduction,
// disclosure or distribution of this material and related documentation
// without an express license agreement from NVIDIA CORPORATION or
// its affiliates is strictly prohibited.

#pragma once

#include "../../carb/Defines.h"

#include <vector>

namespace carb
{

template <class FuncT, typename SubIdT>
class EventSubscribers
{
public:
    SubIdT subscribe(FuncT fn, void* userData)
    {
        // Search for free slot
        size_t index;
        bool found = false;
        for (size_t i = 0; i < m_subscribers.size(); i++)
        {
            if (!m_subscribers[i].fn)
            {
                index = i;
                found = true;
                break;
            }
        }

        // Add new slot if haven't found a free one
        if (!found)
        {
            m_subscribers.push_back({});
            index = m_subscribers.size() - 1;
        }

        m_subscribers[index] = { fn, userData };
        return (SubIdT)index;
    }

    void unsubscribe(SubIdT id)
    {
        CARB_ASSERT(id < m_subscribers.size());
        m_subscribers[id] = {};
    }

    template <typename... Ts>
    void send(Ts... args)
    {
        // Iterate by index because subscribers can actually change during iteration (vector can grow)
        const size_t kCount = m_subscribers.size();
        for (size_t i = 0; i < kCount; i++)
        {
            auto& subsribers = m_subscribers[i];
            if (subsribers.fn)
                subsribers.fn(args..., subsribers.userData);
        }
    }

    template <typename... Ts>
    void sendForId(uint64_t id, Ts... args)
    {
        CARB_ASSERT(id < m_subscribers.size());
        if (m_subscribers[id].fn)
            m_subscribers[id].fn(args..., m_subscribers[id].userData);
    }

private:
    struct EventData
    {
        FuncT fn;
        void* userData;
    };
    std::vector<EventData> m_subscribers;
};

} // namespace carb