src/core/messenger/delegates.h

List of internal messenger delegates. More…

Namespaces

Name
allpix
Helper class to hold support layers for a detector model.

Classes

Name
struct allpix::DelegateTypes
Container of the different delegate types.
class allpix::BaseDelegate
Base for all delegates.
class allpix::ModuleDelegate
Base for all delegates operating on modules.
class allpix::StoreDelegate
Delegate to store the message in memory for fetching the history.
class allpix::FilterDelegate
Delegate for filtering messages using a function.
class allpix::FilterAllDelegate
Delegate for invoking a filter listening to all messages also getting the name.
class allpix::SingleBindDelegate
Delegate for binding a single message.
class allpix::VectorBindDelegate
Delegate for binding multiple message to a vector.

Types

Name
enum class uint32_t MsgFlags { NONE = 0, REQUIRED = (1 « 0), ALLOW_OVERWRITE = (1 « 1), IGNORE_NAME = (1 « 2), UNNAMED_ONLY = (1 « 3)}
Flags to change the behaviour of delegates.

Functions

Name
MsgFlags **[operator
MsgFlags operator&(MsgFlags f1, MsgFlags f2)
Give the set of flags present in both sets of message flags.

Detailed Description

List of internal messenger delegates.

Copyright: Copyright (c) 2017-2024 CERN and the Allpix Squared authors. This software is distributed under the terms of the MIT License, copied verbatim in the file “LICENSE.md”. In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an Intergovernmental Organization or submit itself to any jurisdiction. SPDX-License-Identifier: MIT

Types Documentation

enum MsgFlags

Enumerator Value Description
NONE 0 No enabled flags.
REQUIRED (1 « 0) Require a message before running a module.
ALLOW_OVERWRITE (1 « 1) Allow overwriting a previous message.
IGNORE_NAME (1 « 2) Listen to all ignoring message name (equal to * as a input configuration parameter)
UNNAMED_ONLY (1 « 3) Listen to all messages without explicit name (equal to ? as configuration parameter)

Flags to change the behaviour of delegates.

All flags are distinct and can be combined using the | (OR) operator. The flags should be passed to the Messenger when registering a filter or when binding either a single or multiple messages. It depends on the delegate which combination of flags is valid.

Functions Documentation

function operator|

inline MsgFlags operator|(
    MsgFlags f1,
    MsgFlags f2
)

Combine two sets of message flags.

Parameters:

  • f1 First set of flag
  • f2 Second set of flag

Return: New set of flag representing the combination of the two given sets

function operator&

inline MsgFlags operator&(
    MsgFlags f1,
    MsgFlags f2
)

Give the set of flags present in both sets of message flags.

Parameters:

  • f1 First flag
  • f2 Second flag

Return: New flag representing the flags present in both sets of flags

Source code


#ifndef ALLPIX_DELEGATE_H
#define ALLPIX_DELEGATE_H

#include <cassert>
#include <memory>
#include <typeinfo>
#include <utility>

#include "Message.hpp"
#include "core/geometry/Detector.hpp"
#include "core/messenger/exceptions.h"

// TODO [doc] This should partly move to a source file

namespace allpix {
    struct DelegateTypes { // NOLINT
        std::shared_ptr<BaseMessage> single;
        std::vector<std::shared_ptr<BaseMessage>> multi;
        std::vector<std::pair<std::shared_ptr<BaseMessage>, std::string>> filter_multi;
    };
    // TODO [doc] Is DelegateFlags or MessengerFlags a better name (and in separate file?)
    enum class MsgFlags : uint32_t {
        NONE = 0,                   
        REQUIRED = (1 << 0),        
        ALLOW_OVERWRITE = (1 << 1), 
        IGNORE_NAME = (1 << 2),     
        UNNAMED_ONLY = (1 << 3)     
    };
    inline MsgFlags operator|(MsgFlags f1, MsgFlags f2) {
        return static_cast<MsgFlags>(static_cast<uint32_t>(f1) | static_cast<uint32_t>(f2));
    }
    inline MsgFlags operator&(MsgFlags f1, MsgFlags f2) {
        return static_cast<MsgFlags>(static_cast<uint32_t>(f1) & static_cast<uint32_t>(f2));
    }

    class BaseDelegate {
    public:
        explicit BaseDelegate(MsgFlags flags) : flags_(flags) {}
        virtual ~BaseDelegate() = default;


        BaseDelegate(const BaseDelegate&) = delete;
        BaseDelegate& operator=(const BaseDelegate&) = delete;


        BaseDelegate(BaseDelegate&&) = default;
        BaseDelegate& operator=(BaseDelegate&&) = default;

        bool isRequired() const { return (getFlags() & MsgFlags::REQUIRED) != MsgFlags::NONE; }

        MsgFlags getFlags() const { return flags_; }

        virtual std::shared_ptr<Detector> getDetector() const = 0;

        virtual std::string getUniqueName() = 0;

        virtual void process(std::shared_ptr<BaseMessage> msg, std::string name, DelegateTypes& dest) = 0;

    protected:
        MsgFlags flags_;
    };

    template <typename T> class ModuleDelegate : public BaseDelegate {
    public:
        explicit ModuleDelegate(MsgFlags flags, T* obj) : BaseDelegate(flags), obj_(obj) {}

        std::string getUniqueName() override { return obj_->getUniqueName(); }

        std::shared_ptr<Detector> getDetector() const override { return obj_->getDetector(); }

    protected:
        T* const obj_;
    };

    template <typename T> class StoreDelegate : public ModuleDelegate<T> {
    public:
        StoreDelegate(MsgFlags flags, T* obj) : ModuleDelegate<T>(flags, obj) {}

        void process(std::shared_ptr<BaseMessage> msg, std::string, DelegateTypes&) override {
            // Store the message and mark as processed
            messages_.push_back(msg);
        }

    private:
        std::vector<std::shared_ptr<BaseMessage>> messages_;
    };

    template <typename T, typename R> class FilterDelegate : public ModuleDelegate<T> {
    public:
        using FilterFunction = bool (T::*)(const std::shared_ptr<R>&) const;

        FilterDelegate(MsgFlags flags, T* obj, FilterFunction filter) : ModuleDelegate<T>(flags, obj), filter_(filter) {}

        void process(std::shared_ptr<BaseMessage> msg, std::string, DelegateTypes& dest) override {
#ifndef NDEBUG
            // The type names should have been correctly resolved earlier
            const BaseMessage* inst = msg.get();
            assert(typeid(*inst) == typeid(R));
#endif
            // Filter the message, and store it if it should be kept
            if((this->obj_->*filter_)(std::static_pointer_cast<R>(msg))) {
                dest.filter_multi.emplace_back(std::static_pointer_cast<R>(msg), "");
            }
        }

    private:
        FilterFunction filter_;
    };

    template <typename T> class FilterAllDelegate : public ModuleDelegate<T> {
    public:
        using FilterFunction = bool (T::*)(const std::shared_ptr<BaseMessage>&, const std::string&) const;

        FilterAllDelegate(MsgFlags flags, T* obj, FilterFunction filter) : ModuleDelegate<T>(flags, obj), filter_(filter) {}

        void process(std::shared_ptr<BaseMessage> msg, std::string name, DelegateTypes& dest) override {
            // Filter the message, and store it if it should be kept
            if((this->obj_->*filter_)(std::static_pointer_cast<BaseMessage>(msg), name)) {
                dest.filter_multi.emplace_back(std::static_pointer_cast<BaseMessage>(msg), name);
            }
        }

    private:
        FilterFunction filter_;
    };

    template <typename T, typename R> class SingleBindDelegate : public ModuleDelegate<T> {
    public:
        SingleBindDelegate(MsgFlags flags, T* obj) : ModuleDelegate<T>(flags, obj) {}

        void process(std::shared_ptr<BaseMessage> msg, std::string, DelegateTypes& dest) override {
#ifndef NDEBUG
            // The type names should have been correctly resolved earlier
            const BaseMessage* inst = msg.get();
            assert(typeid(*inst) == typeid(R));
#endif
            // Raise an error if the message is overwritten (unless it is allowed)
            if(dest.single != nullptr && (this->getFlags() & MsgFlags::ALLOW_OVERWRITE) == MsgFlags::NONE) {
                throw UnexpectedMessageException(this->obj_->getUniqueName(), typeid(R));
            }

            // Save the message
            dest.single = std::static_pointer_cast<R>(msg);
        }
    };

    template <typename T, typename R> class VectorBindDelegate : public ModuleDelegate<T> {
    public:
        VectorBindDelegate(MsgFlags flags, T* obj) : ModuleDelegate<T>(flags, obj) {}

        void process(std::shared_ptr<BaseMessage> msg, std::string, DelegateTypes& dest) override {
#ifndef NDEBUG
            // The type names should have been correctly resolved earlier
            const BaseMessage* inst = msg.get();
            assert(typeid(*inst) == typeid(R));
#endif
            // Add the message to the vector
            dest.multi.push_back(std::static_pointer_cast<R>(msg));
        }
    };
} // namespace allpix

#endif /* ALLPIX_DELEGATE_H */

Updated on 2025-02-27 at 14:14:46 +0000