carb/events/IEvents.h
File members: carb/events/IEvents.h
// Copyright (c) 2019-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 "../IObject.h"
#include "../Interface.h"
#include "../InterfaceUtils.h"
#include "../dictionary/IDictionary.h"
#include <utility>
namespace carb
{
namespace events
{
using EventType = uint64_t;
using SenderId = uint32_t;
constexpr SenderId kGlobalSenderId = 0;
using Order = int32_t;
constexpr Order kDefaultOrder = 0;
class IEvent : public IObject
{
public:
EventType type;
SenderId sender;
dictionary::Item* payload;
template <typename ValueT>
void setValues(const std::pair<const char*, ValueT>& param);
template <typename ValueT, typename... ValuesT>
void setValues(const std::pair<const char*, ValueT>& param, ValuesT&&... params);
virtual void consume() = 0;
virtual void attachObject(const char* name, carb::IObject* ptr) = 0;
carb::ObjectPtr<carb::IObject> retrieveObject(const char* name)
{
// cannot pass ObjectPtr by value across ABI boundaries
carb::ObjectPtr<carb::IObject> ptr{};
internalRetrieveObject(name, ptr);
return ptr;
}
virtual void internalRetrieveObject(const char* name, carb::ObjectPtr<carb::IObject>& out) = 0;
};
using IEventPtr = ObjectPtr<IEvent>;
class IEventListener : public IObject
{
public:
virtual void onEvent(IEvent* e) = 0;
};
using IEventListenerPtr = ObjectPtr<IEventListener>;
class ISubscription : public IObject
{
public:
virtual void unsubscribe() = 0;
virtual const char* getName() const noexcept = 0;
};
using ISubscriptionPtr = ObjectPtr<ISubscription>;
#define CARB_EVENTS_TYPE_FROM_STR(STR) CARB_HASH_STRING(STR)
inline EventType typeFromString(const char* str)
{
return carb::hashString(str);
}
class IEventStream : 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();
ObjectPtr<ISubscription> createSubscriptionToPop(IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr);
ObjectPtr<ISubscription> createSubscriptionToPopByType(EventType eventType,
IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr);
virtual ISubscription* createSubscriptionToPopPtr(IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr) = 0;
virtual ISubscription* createSubscriptionToPopByTypePtr(EventType eventType,
IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr) = 0;
ObjectPtr<ISubscription> createSubscriptionToPush(IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr);
ObjectPtr<ISubscription> createSubscriptionToPushByType(EventType eventType,
IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr);
virtual ISubscription* createSubscriptionToPushPtr(IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr) = 0;
virtual ISubscription* createSubscriptionToPushByTypePtr(EventType eventType,
IEventListener* listener,
Order order = kDefaultOrder,
const char* subscriptionName = nullptr) = 0;
virtual bool setSubscriptionToPopOrder(const char* subscriptionName, Order order) = 0;
virtual bool setSubscriptionToPushOrder(const char* subscriptionName, Order order) = 0;
virtual bool getSubscriptionToPopOrder(const char* subscriptionName, Order* order) = 0;
virtual bool getSubscriptionToPushOrder(const char* subscriptionName, Order* order) = 0;
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);
};
using IEventStreamPtr = ObjectPtr<IEventStream>;
struct IEvents
{
// 1.0 - Initial release
// 1.1 - added internalCreateEventStream
// 1.2 - added attachObject() and retrieveObject() to IEvent
CARB_PLUGIN_INTERFACE("carb::events::IEvents", 1, 2)
IEventStreamPtr createEventStream(const char* name = nullptr) noexcept;
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;
};
// Inline Functions //
template <typename ValueT>
inline void IEvent::setValues(const std::pair<const char*, ValueT>& param)
{
carb::getCachedInterface<dictionary::IDictionary>()->makeAtPath<ValueT>(this->payload, param.first, param.second);
}
template <typename ValueT, typename... ValuesT>
inline void IEvent::setValues(const std::pair<const char*, ValueT>& param, ValuesT&&... params)
{
this->setValues<ValueT>(param);
this->setValues(std::forward<ValuesT>(params)...);
}
template <typename... ValuesT>
inline IEvent* IEventStream::createEventPtr(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender);
e->setValues(std::forward<ValuesT>(values)...);
return e;
}
inline ObjectPtr<ISubscription> IEventStream::createSubscriptionToPop(IEventListener* listener,
Order order,
const char* name)
{
return stealObject(this->createSubscriptionToPopPtr(listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream::createSubscriptionToPopByType(EventType eventType,
IEventListener* listener,
Order order,
const char* name)
{
return stealObject(this->createSubscriptionToPopByTypePtr(eventType, listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream::createSubscriptionToPush(IEventListener* listener,
Order order,
const char* name)
{
return stealObject(this->createSubscriptionToPushPtr(listener, order, name));
}
inline ObjectPtr<ISubscription> IEventStream::createSubscriptionToPushByType(EventType eventType,
IEventListener* listener,
Order order,
const char* name)
{
return stealObject(this->createSubscriptionToPushByTypePtr(eventType, listener, order, name));
}
template <typename... ValuesT>
inline void IEventStream::pushWithSender(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
push(e);
e->release();
}
inline void IEventStream::pushWithSender(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
push(e);
e->release();
}
template <typename... ValuesT>
inline ObjectPtr<IEvent> IEventStream::createEvent(EventType eventType, SenderId sender, ValuesT&&... values)
{
return carb::stealObject(this->createEventPtr(eventType, sender, std::forward<ValuesT>(values)...));
}
template <typename... ValuesT>
inline void IEventStream::push(EventType type, ValuesT&&... values)
{
return pushWithSender(type, kGlobalSenderId, std::forward<ValuesT>(values)...);
}
template <typename... ValuesT>
inline void IEventStream::pushBlockedWithSender(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
pushBlocked(e);
e->release();
}
inline void IEventStream::pushBlockedWithSender(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
pushBlocked(e);
e->release();
}
template <typename... ValuesT>
inline void IEventStream::pushBlocked(EventType type, ValuesT&&... values)
{
return pushBlockedWithSender(type, kGlobalSenderId, std::forward<ValuesT>(values)...);
}
template <typename... ValuesT>
inline void IEventStream::dispatch(EventType type, SenderId sender, ValuesT&&... values)
{
IEvent* e = createEventPtr(type, sender, std::forward<ValuesT>(values)...);
dispatch(e);
e->release();
}
inline void IEventStream::dispatch(EventType type, SenderId sender)
{
IEvent* e = createEventPtr(type, sender);
dispatch(e);
e->release();
}
inline void IEventStream::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> IEventStream::pop()
{
return carb::stealObject(this->popPtr());
}
inline ObjectPtr<IEvent> IEventStream::tryPop()
{
return carb::stealObject(this->tryPopPtr());
}
inline ObjectPtr<IEventStream> IEvents::createEventStream(const char* name) noexcept
{
return carb::stealObject(this->internalCreateEventStream(name));
}
} // namespace events
} // namespace carb