iceoryx_posh/popo/listener.hpp🔗
Namespaces🔗
Name |
---|
iox |
iox::popo |
iox::popo::internal |
Classes🔗
Name | |
---|---|
class | iox::popo::ListenerImpl The Listener is a class which reacts to registered events by executing a corresponding callback concurrently. This is achieved via an encapsulated thread inside this class. |
class | iox::popo::Listener |
Source code🔗
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_POSH_POPO_LISTENER_HPP
#define IOX_POSH_POPO_LISTENER_HPP
#include "iceoryx_hoofs/cxx/expected.hpp"
#include "iceoryx_hoofs/cxx/method_callback.hpp"
#include "iceoryx_hoofs/cxx/type_traits.hpp"
#include "iceoryx_hoofs/internal/concurrent/loffli.hpp"
#include "iceoryx_hoofs/internal/concurrent/smart_lock.hpp"
#include "iceoryx_posh/internal/popo/building_blocks/condition_listener.hpp"
#include "iceoryx_posh/popo/enum_trigger_type.hpp"
#include "iceoryx_posh/popo/notification_attorney.hpp"
#include "iceoryx_posh/popo/notification_callback.hpp"
#include "iceoryx_posh/popo/trigger_handle.hpp"
#include "iceoryx_posh/runtime/posh_runtime.hpp"
#include <thread>
namespace iox
{
namespace popo
{
namespace internal
{
class Event_t
{
public:
~Event_t() noexcept;
bool isEqualTo(const void* const origin, const uint64_t eventType, const uint64_t eventTypeHash) const noexcept;
bool reset() noexcept;
bool init(const uint64_t eventId,
void* const origin,
void* const userType,
const uint64_t eventType,
const uint64_t eventTypeHash,
internal::GenericCallbackRef_t callback,
internal::TranslationCallbackRef_t translationCallback,
const cxx::MethodCallback<void, uint64_t> invalidationCallback) noexcept;
void executeCallback() noexcept;
bool isInitialized() const noexcept;
private:
static constexpr uint64_t INVALID_ID = std::numeric_limits<uint64_t>::max();
void* m_origin = nullptr;
uint64_t m_eventType = INVALID_ID;
uint64_t m_eventTypeHash = INVALID_ID;
internal::GenericCallbackPtr_t m_callback = nullptr;
internal::TranslationCallbackPtr_t m_translationCallback = nullptr;
void* m_userType = nullptr;
uint64_t m_eventId = INVALID_ID;
cxx::MethodCallback<void, uint64_t> m_invalidationCallback;
};
} // namespace internal
enum class ListenerError
{
LISTENER_FULL,
EVENT_ALREADY_ATTACHED,
EMPTY_EVENT_CALLBACK,
EMPTY_INVALIDATION_CALLBACK
};
template <uint64_t Capacity>
class ListenerImpl
{
public:
ListenerImpl() noexcept;
ListenerImpl(const ListenerImpl&) = delete;
ListenerImpl(ListenerImpl&&) = delete;
~ListenerImpl() noexcept;
ListenerImpl& operator=(const ListenerImpl&) = delete;
ListenerImpl& operator=(ListenerImpl&&) = delete;
template <typename T,
typename EventType,
typename ContextDataType,
typename = std::enable_if_t<std::is_enum<EventType>::value>>
cxx::expected<ListenerError> attachEvent(T& eventOrigin,
const EventType eventType,
const NotificationCallback<T, ContextDataType>& eventCallback) noexcept;
template <typename T, typename ContextDataType>
cxx::expected<ListenerError> attachEvent(T& eventOrigin,
const NotificationCallback<T, ContextDataType>& eventCallback) noexcept;
template <typename T, typename EventType, typename = std::enable_if_t<std::is_enum<EventType>::value>>
void detachEvent(T& eventOrigin, const EventType eventType) noexcept;
template <typename T>
void detachEvent(T& eventOrigin) noexcept;
static constexpr uint64_t capacity() noexcept;
uint64_t size() const noexcept;
protected:
ListenerImpl(ConditionVariableData& conditionVariableData) noexcept;
private:
class Event_t;
void threadLoop() noexcept;
cxx::expected<uint32_t, ListenerError>
addEvent(void* const origin,
void* const userType,
const uint64_t eventType,
const uint64_t eventTypeHash,
internal::GenericCallbackRef_t callback,
internal::TranslationCallbackRef_t translationCallback,
const cxx::MethodCallback<void, uint64_t> invalidationCallback) noexcept;
void removeTrigger(const uint64_t index) noexcept;
private:
enum class NoEnumUsed : EventEnumIdentifier
{
PLACEHOLDER = 0
};
class IndexManager_t
{
public:
IndexManager_t() noexcept;
bool pop(uint32_t& index) noexcept;
void push(const uint32_t index) noexcept;
uint64_t indicesInUse() const noexcept;
using LoFFLi = concurrent::LoFFLi;
LoFFLi::Index_t m_loffliStorage[LoFFLi::requiredIndexMemorySize(Capacity) / sizeof(uint32_t)];
LoFFLi m_loffli;
std::atomic<uint64_t> m_indicesInUse{0U};
} m_indexManager;
std::thread m_thread;
concurrent::smart_lock<internal::Event_t, std::recursive_mutex> m_events[Capacity];
std::mutex m_addEventMutex;
std::atomic_bool m_wasDtorCalled{false};
ConditionVariableData* m_conditionVariableData = nullptr;
ConditionListener m_conditionListener;
};
class Listener : public ListenerImpl<MAX_NUMBER_OF_EVENTS_PER_LISTENER>
{
public:
using Parent = ListenerImpl<MAX_NUMBER_OF_EVENTS_PER_LISTENER>;
Listener() noexcept;
protected:
Listener(ConditionVariableData& conditionVariableData) noexcept;
};
} // namespace popo
} // namespace iox
#include "iceoryx_posh/internal/popo/listener.inl"
#endif
Updated on 18 December 2023 at 13:11:43 CET