IEvents.h#
Fully qualified name: carb/events/IEvents.h
File members: carb/events/IEvents.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 "EventsTypes.h"
#include "../Interface.h"
#include "../InterfaceUtils.h"
#include "../RString.h"
#include "../dictionary/DictionaryUtils.h"
#include "../../omni/Vector.h"
#include <utility>
#include "../Defines.h"
#define carb_events_IEvents_latest CARB_HEXVERSION(1, 5)
#ifndef carb_events_IEvents
# define carb_events_IEvents CARB_HEXVERSION(1, 4)
#endif
#ifndef CARB_EVENTS_DEPRECATIONS
# define CARB_EVENTS_DEPRECATIONS 1
#endif
#if CARB_EVENTS_DEPRECATIONS && CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
# define CARB_EVENTS_DEPRECATED_1_5(msg) CARB_DEPRECATED(msg)
#else
# define CARB_EVENTS_DEPRECATED_1_5(msg)
#endif
namespace carb::events
{
class IEvent : public IObject
{
public:
EventType type;
SenderId sender;
dictionary::Item* payload;
template <typename ValueT>
CARB_EVENTS_DEPRECATED_1_5("Use setValue() with string_view instead")
void setValues(const std::pair<const char*, ValueT>& param);
template <typename ValueT, typename... ValuesT>
CARB_EVENTS_DEPRECATED_1_5("Use setValue() with string_view instead")
void setValues(const std::pair<const char*, ValueT>& param, ValuesT&&... params);
virtual void consume() = 0;
CARB_EVENTS_DEPRECATED_1_5("Use attachObject with cpp::string_view")
virtual void internalAttachObject(const char* name, carb::IObject* ptr) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use retrieveObject() with string_view instead")
carb::ObjectPtr<carb::IObject> retrieveObject(cpp::unbounded_string name)
{
// cannot pass ObjectPtr by value across ABI boundaries
carb::ObjectPtr<carb::IObject> ptr{};
CARB_IGNORE_DEPRECATION_BEGIN
internalRetrieveObject(name, ptr);
CARB_IGNORE_DEPRECATION_END
return ptr;
}
CARB_EVENTS_DEPRECATED_1_5("Use retrieveObject with cpp::string_view")
virtual void internalRetrieveObject(const char* name, carb::ObjectPtr<carb::IObject>& out) = 0;
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 4)
virtual void getObjectNames(omni::vector<RString>& out) const = 0;
#endif
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
template <typename ValueT>
void setValue(cpp::string_view name, ValueT&& value);
virtual void attachObject(carb::cpp::string_view name, carb::IObject* ptr) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use attachObject() with string_view instead")
void attachObject(cpp::unbounded_string name, carb::IObject* ptr)
{
CARB_IGNORE_DEPRECATION_BEGIN
internalAttachObject(name, ptr);
CARB_IGNORE_DEPRECATION_END
}
carb::ObjectPtr<carb::IObject> retrieveObject(carb::cpp::string_view name)
{
// cannot pass ObjectPtr by value across ABI boundaries
carb::ObjectPtr<carb::IObject> ptr{};
internalRetrieveObject(name, ptr);
return ptr;
}
virtual void internalRetrieveObject(carb::cpp::string_view name, carb::ObjectPtr<carb::IObject>& out) = 0;
virtual bool isConsumed() const noexcept = 0;
#endif
};
using IEventPtr = ObjectPtr<IEvent>;
class ISubscription : public IObject
{
public:
virtual void unsubscribe() = 0;
virtual cpp::zstring_view getNameS() const noexcept = 0;
CARB_EVENTS_DEPRECATED_1_5("Use getNameS() instead")
virtual const char* getName() const noexcept = 0;
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 3)
virtual Order getOrder() const noexcept = 0;
virtual void setOrder(Order order) noexcept = 0;
virtual bool isEnabled() const noexcept = 0;
virtual void setEnabled(bool enabled) noexcept = 0;
#endif
};
using ISubscriptionPtr = ObjectPtr<ISubscription>;
class IEventStream1_0 : public IObject
{
public:
virtual IEvent* createEventPtr(EventType eventType, SenderId sender) = 0;
template <typename... ValuesT>
ObjectPtr<IEvent> createEvent(EventType eventType, SenderId sender, ValuesT&&... values);
virtual void dispatch(IEvent* e) = 0;
virtual void push(IEvent* e) = 0;
virtual void pushBlocked(IEvent* e) = 0;
virtual size_t getCount() = 0;
ObjectPtr<IEvent> pop();
virtual IEvent* popPtr() = 0;
ObjectPtr<IEvent> tryPop();
virtual IEvent* tryPopPtr() = 0;
void pump();
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPop() with string_view instead")
ObjectPtr<ISubscription> createSubscriptionToPop(IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return stealObject(this->internalCreateSubscriptionToPopPtr(listener, order, subscriptionName));
}
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPopByType() with string_view instead")
ObjectPtr<ISubscription> createSubscriptionToPopByType(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return stealObject(this->internalCreateSubscriptionToPopByTypePtr(eventType, listener, order, subscriptionName));
}
virtual ISubscription* internalCreateSubscriptionToPopPtr(IEventListener* listener,
Order order,
const char* subscriptionName) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPop() with string_view instead")
ISubscription* createSubscriptionToPopPtr(IEventListener* listener, Order order, const char* subscriptionName = nullptr)
{
return internalCreateSubscriptionToPopPtr(listener, order, subscriptionName);
}
virtual ISubscription* internalCreateSubscriptionToPopByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPop() with string_view instead")
ISubscription* createSubscriptionToPopByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return internalCreateSubscriptionToPopByTypePtr(eventType, listener, order, subscriptionName);
}
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPush() with string_view instead")
ObjectPtr<ISubscription> createSubscriptionToPush(IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return stealObject(this->internalCreateSubscriptionToPushPtr(listener, order, subscriptionName));
}
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPushByType() with string_view instead")
ObjectPtr<ISubscription> createSubscriptionToPushByType(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return stealObject(this->internalCreateSubscriptionToPushByTypePtr(eventType, listener, order, subscriptionName));
}
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPushByTypePtr() with string_view instead")
ISubscription* createSubscriptionToPushByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName = nullptr)
{
return internalCreateSubscriptionToPushByTypePtr(eventType, listener, order, subscriptionName);
}
virtual ISubscription* internalCreateSubscriptionToPushPtr(IEventListener* listener,
Order order,
const char* subscriptionName) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use createSubscriptionToPush() with string_view instead")
ISubscription* createSubscriptionToPushPtr(IEventListener* listener, Order order, const char* subscriptionName = nullptr)
{
return internalCreateSubscriptionToPushPtr(listener, order, subscriptionName);
}
virtual ISubscription* internalCreateSubscriptionToPushByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
const char* subscriptionName) = 0;
virtual bool internalSetSubscriptionToPopOrder(const char* subscriptionName, Order order) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use setSubscriptionToPopOrder() with string_view instead")
bool setSubscriptionToPopOrder(const char* subscriptionName, Order order)
{
return internalSetSubscriptionToPopOrder(subscriptionName, order);
}
virtual bool internalSetSubscriptionToPushOrder(const char* subscriptionName, Order order) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use setSubscriptionToPushOrder() with string_view instead")
bool setSubscriptionToPushOrder(const char* subscriptionName, Order order)
{
return internalSetSubscriptionToPushOrder(subscriptionName, order);
}
virtual bool internalGetSubscriptionToPopOrder(const char* subscriptionName, Order* order) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use getSubscriptionToPopOrder() with string_view instead")
bool getSubscriptionToPopOrder(const char* subscriptionName, Order* order)
{
return internalGetSubscriptionToPopOrder(subscriptionName, order);
}
virtual bool internalGetSubscriptionToPushOrder(const char* subscriptionName, Order* order) = 0;
CARB_EVENTS_DEPRECATED_1_5("Use getSubscriptionToPushOrder() with string_view instead")
bool getSubscriptionToPushOrder(const char* subscriptionName, Order* order)
{
return internalGetSubscriptionToPushOrder(subscriptionName, order);
}
CARB_EVENTS_DEPRECATED_1_5("Use getNameS() instead")
virtual const char* getName() const noexcept = 0;
// Helpers //
template <typename... ValuesT>
IEvent* createEventPtr(EventType eventType, SenderId sender, ValuesT&&... values);
void pushWithSender(EventType eventType, SenderId sender);
template <typename... ValuesT>
void pushWithSender(EventType eventType, SenderId sender, ValuesT&&... values);
template <typename... ValuesT>
void push(EventType eventType, ValuesT&&... values);
void pushBlockedWithSender(EventType eventType, SenderId sender);
template <typename... ValuesT>
void pushBlockedWithSender(EventType eventType, SenderId sender, ValuesT&&... values);
template <typename... ValuesT>
void pushBlocked(EventType eventType, ValuesT&&... values);
template <typename... ValuesT>
void dispatch(EventType eventType, SenderId sender, ValuesT&&... values);
void dispatch(EventType eventType, SenderId sender);
};
// Apparently doxygen ignores @private on macros and complains that it's not documented.
#define CARBLOCAL_IEVENTSTREAM IEventStream1_0
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 3)
class IEventStream1_3 : public IEventStream1_0
{
public:
virtual size_t getSubscriptionToPopCount() const = 0;
virtual size_t getSubscriptionToPushCount() const = 0;
virtual bool walkSubscriptionsToPop(SubscriptionCallback callback, void* userData) const = 0;
virtual bool walkSubscriptionsToPush(SubscriptionCallback callback, void* userData) const = 0;
};
# undef CARBLOCAL_IEVENTSTREAM
# define CARBLOCAL_IEVENTSTREAM IEventStream1_3
#endif
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
class IEventStream1_5 : public IEventStream1_3
{
using BaseClass = IEventStream1_3;
public:
ObjectPtr<ISubscription> createSubscriptionToPop(IEventListener* listener,
Order order,
cpp::string_view subscriptionName);
ObjectPtr<ISubscription> createSubscriptionToPop(IEventListener* listener);
ObjectPtr<ISubscription> createSubscriptionToPopByType(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view subscriptionName);
ObjectPtr<ISubscription> createSubscriptionToPopByType(EventType eventType, IEventListener* listener);
virtual ISubscription* createSubscriptionToPopPtr(IEventListener* listener,
Order order,
cpp::string_view subscriptionName) = 0;
ISubscription* createSubscriptionToPopPtr(IEventListener* listener)
{
return createSubscriptionToPopPtr(listener, kDefaultOrder, {});
}
virtual ISubscription* createSubscriptionToPopByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view subscriptionName) = 0;
ISubscription* createSubscriptionToPopByTypePtr(EventType eventType, IEventListener* listener)
{
return createSubscriptionToPopByTypePtr(eventType, listener, kDefaultOrder, {});
}
ObjectPtr<ISubscription> createSubscriptionToPush(IEventListener* listener,
Order order,
cpp::string_view subscriptionName);
ObjectPtr<ISubscription> createSubscriptionToPush(IEventListener* listener);
ObjectPtr<ISubscription> createSubscriptionToPushByType(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view subscriptionName);
ObjectPtr<ISubscription> createSubscriptionToPushByType(EventType eventType, IEventListener* listener);
virtual ISubscription* createSubscriptionToPushPtr(IEventListener* listener,
Order order,
cpp::string_view subscriptionName) = 0;
ISubscription* createSubscriptionToPushPtr(IEventListener* listener)
{
return createSubscriptionToPushPtr(listener, kDefaultOrder, {});
}
virtual ISubscription* createSubscriptionToPushByTypePtr(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view subscriptionName) = 0;
ISubscription* createSubscriptionToPushByTypePtr(EventType eventType, IEventListener* listener)
{
return createSubscriptionToPushByTypePtr(eventType, listener, kDefaultOrder, {});
}
virtual bool setSubscriptionToPopOrder(cpp::string_view subscriptionName, Order order) = 0;
virtual bool setSubscriptionToPushOrder(cpp::string_view subscriptionName, Order order) = 0;
virtual bool getSubscriptionToPopOrder(cpp::string_view subscriptionName, Order* order) = 0;
virtual bool getSubscriptionToPushOrder(cpp::string_view subscriptionName, Order* order) = 0;
virtual cpp::zstring_view getNameS() const noexcept = 0;
};
# undef CARBLOCAL_IEVENTSTREAM
# define CARBLOCAL_IEVENTSTREAM IEventStream1_5
#endif
class IEventStream : public CARBLOCAL_IEVENTSTREAM
{
// Implementation note: MSVC builds its vtables grouping functions by name, not in the order they're listed in the
// class definition. So that means if we add functions to the end for minor versions, they can end up scattered
// throughout the vtable, and we get ABI breaks. That's why the class is inherited like so.
};
using IEventStreamPtr = ObjectPtr<IEventStream>;
struct IEvents
{
// 1.0 - Initial release
// 1.1 - added internalCreateEventStream
// 1.2 - added internalAttachObject() and retrieveObject() to IEvent
// 1.3 - API additions for more control over subscriptions
// 1.4 - added getObjectNames() to IEvent
CARB_PLUGIN_INTERFACE_EX("carb::events::IEvents", carb_events_IEvents_latest, carb_events_IEvents)
CARB_DEPRECATED("Use internalCreateEventStream instead") virtual IEventStream* createEventStreamPtr() = 0;
virtual SenderId acquireUniqueSenderId() = 0;
virtual void releaseUniqueSenderId(SenderId senderId) = 0;
virtual IEventStream* internalCreateEventStream(const char* name) noexcept = 0;
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
virtual IEventStream* internalCreateEventStreamS(cpp::string_view name) noexcept = 0;
IEventStreamPtr createEventStream(cpp::string_view name = {}) noexcept
{
return stealObject(internalCreateEventStreamS(name));
}
CARB_EVENTS_DEPRECATED_1_5("Use createEventStream(string_view)")
IEventStreamPtr createEventStream(cpp::unbounded_string name) noexcept
{
return stealObject(internalCreateEventStream(name));
}
#else
IEventStreamPtr createEventStream(const char* name = nullptr) noexcept
{
return stealObject(internalCreateEventStream(name));
}
#endif // CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
};
// Inline Functions //
template <typename ValueT>
inline void IEvent::setValues(const std::pair<const char*, ValueT>& param)
{
CARB_IGNORE_DEPRECATION_BEGIN
if constexpr (cpp::is_unbounded_character_sequence_v<ValueT, char>)
dictionary::detail::makeAtPath(getCachedInterface<dictionary::IDictionary>(), this->payload,
cpp::string_view(cpp::unsafe_length, param.first),
cpp::string_view(cpp::unsafe_length, param.second));
else
dictionary::detail::makeAtPath(getCachedInterface<dictionary::IDictionary>(), this->payload,
cpp::string_view(cpp::unsafe_length, param.first), param.second);
CARB_IGNORE_DEPRECATION_END
}
template <typename ValueT, typename... ValuesT>
inline void IEvent::setValues(const std::pair<const char*, ValueT>& param, ValuesT&&... params)
{
CARB_IGNORE_DEPRECATION_BEGIN
this->setValues<ValueT>(param);
this->setValues(std::forward<ValuesT>(params)...);
CARB_IGNORE_DEPRECATION_END
}
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
template <typename ValueT>
inline void IEvent::setValue(cpp::string_view name, ValueT&& value)
{
auto dict = getCachedInterface<dictionary::IDictionary>();
dictionary::detail::makeAtPath(dict, this->payload, name, std::forward<ValueT>(value));
}
#endif
template <typename... ValuesT>
inline IEvent* IEventStream1_0::createEventPtr(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender);
CARB_IGNORE_DEPRECATION_BEGIN
e->setValues(std::forward<ValuesT>(values)...);
CARB_IGNORE_DEPRECATION_END
return e;
}
// Removed deprecated inline implementations - now handled by templates
#if CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
// String view versions of subscription functions
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPop(IEventListener* listener,
Order order,
cpp::string_view name)
{
return stealObject(this->createSubscriptionToPopPtr(listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPop(IEventListener* listener)
{
return stealObject(this->createSubscriptionToPopPtr(listener));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPopByType(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view name)
{
return stealObject(this->createSubscriptionToPopByTypePtr(eventType, listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPopByType(EventType eventType,
IEventListener* listener)
{
return stealObject(this->createSubscriptionToPopByTypePtr(eventType, listener));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPush(IEventListener* listener,
Order order,
cpp::string_view name)
{
return stealObject(this->createSubscriptionToPushPtr(listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPush(IEventListener* listener)
{
return stealObject(this->createSubscriptionToPushPtr(listener));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPushByType(EventType eventType,
IEventListener* listener,
Order order,
cpp::string_view name)
{
return stealObject(this->createSubscriptionToPushByTypePtr(eventType, listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream1_5::createSubscriptionToPushByType(EventType eventType,
IEventListener* listener)
{
return stealObject(this->createSubscriptionToPushByTypePtr(eventType, listener));
}
#endif // CARB_VERSION_ATLEAST(carb_events_IEvents, 1, 5)
template <typename... ValuesT>
inline void IEventStream1_0::pushWithSender(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
push(e);
e->release();
}
inline void IEventStream1_0::pushWithSender(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
push(e);
e->release();
}
template <typename... ValuesT>
inline ObjectPtr<IEvent> IEventStream1_0::createEvent(EventType eventType, SenderId sender, ValuesT&&... values)
{
return carb::stealObject(this->createEventPtr(eventType, sender, std::forward<ValuesT>(values)...));
}
template <typename... ValuesT>
inline void IEventStream1_0::push(EventType type, ValuesT&&... values)
{
return pushWithSender(type, kGlobalSenderId, std::forward<ValuesT>(values)...);
}
template <typename... ValuesT>
inline void IEventStream1_0::pushBlockedWithSender(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
pushBlocked(e);
e->release();
}
inline void IEventStream1_0::pushBlockedWithSender(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
pushBlocked(e);
e->release();
}
template <typename... ValuesT>
inline void IEventStream1_0::pushBlocked(EventType type, ValuesT&&... values)
{
return pushBlockedWithSender(type, kGlobalSenderId, std::forward<ValuesT>(values)...);
}
template <typename... ValuesT>
inline void IEventStream1_0::dispatch(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
dispatch(e);
e->release();
}
inline void IEventStream1_0::dispatch(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
dispatch(e);
e->release();
}
inline void IEventStream1_0::pump()
{
const size_t eventCount = this->getCount();
for (size_t i = 0; i < eventCount; i++)
{
IEvent* e = this->tryPopPtr();
if (!e)
break;
e->release();
}
}
inline ObjectPtr<IEvent> IEventStream1_0::pop()
{
return carb::stealObject(this->popPtr());
}
inline ObjectPtr<IEvent> IEventStream1_0::tryPop()
{
return carb::stealObject(this->tryPopPtr());
}
} // namespace carb::events
#undef CARBLOCAL_IEVENTSTREAM