IMessageQueue.h#
Fully qualified name: carb/eventdispatcher/IMessageQueue.h
File members: carb/eventdispatcher/IMessageQueue.h
// SPDX-FileCopyrightText: Copyright (c) 2024-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 "MessageQueueTypes.h"
#include "../../omni/Expected.h"
#include "../IObject.h"
#include <type_traits>
#define carb_eventdispatcher_IMessageQueueFactory_latest CARB_HEXVERSION(1, 1)
#ifndef carb_eventdispatcher_IMessageQueueFactory
# define carb_eventdispatcher_IMessageQueueFactory CARB_HEXVERSION(1, 0)
#endif
namespace carb
{
namespace eventdispatcher
{
class IMessageQueue : public carb::IObject
{
public:
using ExpectedType = omni::expected<void, omni::core::Result>;
using UnexpectedType = omni::unexpected<omni::core::Result>;
virtual RStringKey getName() const = 0;
virtual thread::ThreadId getOwningThread() const = 0;
virtual bool hasMessages() const = 0;
virtual void internalPeek(ExpectedType& result, MessageFn fn, void* userData) const = 0;
virtual void internalPop(ExpectedType& result, MessageFn fn, void* userData) = 0;
virtual void internalAwaitMessage(ExpectedType& result, uint64_t nsToWait, NotifyFn notify, void* userData) const = 0;
virtual void internalStop(ExpectedType& result) = 0;
template <class Func>
ExpectedType peek(Func&& func) const;
template <class Func>
ExpectedType pop(Func&& func);
omni::expected<void, omni::core::Result> awaitMessage() const;
template <class Rep, class Period>
omni::expected<void, omni::core::Result> awaitMessageFor(const std::chrono::duration<Rep, Period>& duration) const;
template <class Clock, class Duration>
omni::expected<void, omni::core::Result> awaitMessageUntil(const std::chrono::time_point<Clock, Duration>& when) const;
ExpectedType stop();
virtual void internalPush(ExpectedType& result, const EventData& data, bool wait, NotifyFn notify, void* userData) = 0;
template <class... Args>
ExpectedType pushAsync(RString eventName, Args&&... payload);
template <class InIter>
ExpectedType pushAsyncIter(RString eventName, InIter begin, InIter end);
template <class R CARB_NO_DOC(
,
std::enable_if_t<std::is_same<void, std::void_t<decltype(std::begin(std::declval<R>()), std::end(std::declval<R>()))>>::value,
bool> = false)>
ExpectedType pushAsyncRange(RString eventName, R&& range)
{
// Implementation needs to be inline because certain compilers get very confused about the SFINAE
std::vector<NamedVariant> variants;
for (auto& r : range)
variants.emplace_back(detail::translate(r));
std::sort(variants.begin(), variants.end(), detail::NamedVariantLess{});
CARB_ASSERT(std::adjacent_find(variants.begin(), variants.end(), detail::NamedVariantEqual{}) == variants.end(),
"Message has duplicate keys");
EventData data{ eventName, variants.size(), variants.data() };
ExpectedType result;
internalPush(result, data, false, nullptr, nullptr);
return result;
}
#ifndef DOXYGEN_BUILD
// Enable implicit initializer_list since {} cannot be deduced to a type
template <class T>
ExpectedType pushAsyncRange(RString eventName, std::initializer_list<std::pair<RStringKey, T>> range)
{
return pushAsyncRange<std::initializer_list<std::pair<RStringKey, T>>>(eventName, std::move(range));
}
#endif
template <class... Args>
ExpectedType pushAndWait(RString eventName, Args&&... payload);
template <class R CARB_NO_DOC(
,
std::enable_if_t<std::is_same<void, std::void_t<decltype(std::begin(std::declval<R>()), std::end(std::declval<R>()))>>::value,
bool> = false)>
ExpectedType pushAndWaitRange(RString eventName, R&& range)
{
// Implementation needs to be inline because certain compilers get very confused about the SFINAE
std::vector<NamedVariant> variants;
for (auto& r : range)
variants.emplace_back(detail::translate(r));
std::sort(variants.begin(), variants.end(), detail::NamedVariantLess{});
CARB_ASSERT(std::adjacent_find(variants.begin(), variants.end(), detail::NamedVariantEqual{}) == variants.end(),
"Message has duplicate keys");
EventData data{ eventName, variants.size(), variants.data() };
ExpectedType result;
internalPush(result, data, true, nullptr, nullptr);
return result;
}
#ifndef DOXYGEN_BUILD
// Enable implicit initializer_list since {} cannot be deduced to a type
template <class T>
ExpectedType pushAndWaitRange(RString eventName, std::initializer_list<std::pair<RStringKey, T>> range)
{
return pushAndWaitRange<std::initializer_list<std::pair<RStringKey, T>>>(eventName, std::move(range));
}
#endif
template <class InIter>
ExpectedType pushAndWaitIter(RString eventName, InIter begin, InIter end);
};
using IMessageQueuePtr = carb::ObjectPtr<IMessageQueue>;
struct IMessageQueueFactory
{
CARB_PLUGIN_INTERFACE_EX("carb::eventdispatcher::IMessageQueueFactory",
carb_eventdispatcher_IMessageQueueFactory_latest,
carb_eventdispatcher_IMessageQueueFactory);
IMessageQueue*(CARB_ABI* internalCreateMessageQueue)(RStringKey name,
const MessageQueueParams& params,
omni::core::Result& result,
bool& existing);
IMessageQueue*(CARB_ABI* internalGetMessageQueue)(RStringKey name);
#if CARB_VERSION_ATLEAST(carb_eventdispatcher_IMessageQueueFactory, 1, 1)
bool(CARB_ABI* addAlias)(RStringKey target, RStringKey alias);
bool(CARB_ABI* removeAlias)(RStringKey target, RStringKey alias);
#endif
// ^^^^ Interface functions
// vvvv Helper functions
omni::expected<std::pair<IMessageQueuePtr, bool>, omni::core::Result> createMessageQueue(
RStringKey name, const MessageQueueParams& params);
IMessageQueuePtr getMessageQueue(RStringKey name);
};
} // namespace eventdispatcher
} // namespace carb
#ifndef __INTELLISENSE__
# include "IMessageQueue.inl"
#endif