IMessageQueue.h#
Fully qualified name: carb/eventdispatcher/IMessageQueue.h
File members: carb/eventdispatcher/IMessageQueue.h
// Copyright (c) 2024, 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 "MessageQueueTypes.h"
#include "../../omni/Expected.h"
#include "../IObject.h"
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, cpp::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, cpp::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("carb::eventdispatcher::IMessageQueueFactory", 1, 0);
IMessageQueue*(CARB_ABI* internalCreateMessageQueue)(RStringKey name,
const MessageQueueParams& params,
omni::core::Result& result,
bool& existing);
IMessageQueue*(CARB_ABI* internalGetMessageQueue)(RStringKey name);
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