0
votes

Pipeline de filtre C ++

Je veux développer un pipeline de filtre pour mon application. Le pipeline doit être constitué de n'importe quel nombre de filtres.

pour les filtres I Déclarez une classe de base abstraite comme celle-ci: xxx

Chaque filtre doit hériter de cette classe de base et de mettre en œuvre La méthode exécuter . Comme: xxx

edit 1:

Le message doit être envoyé d'un filtre à l'autre dans le pipeline. Si le pipeline, par exemple, est comme celui-ci:

supérieure - printMessage - WriteToFile

Le message doit passer tous les 3 filtres. (Par exemple, si supérieur a terminé son travail, le message doit être envoyé à PrintMessage et ainsi de suite)

dans l'exemple ci-dessus si le message Hello World est envoyé au pipeline que la sortie doit être la sortie: xxx

edit 2:

Le filtre ne modifie que le contenu du message donné. Le type n'est pas changé. Chaque filtre doit fonctionner avec des ficelles ou une classe donnée. Le message n'est envoyé qu'à un destinataire.

Ma question est maintenant comment connecter ces filtres?

Ma première hypothèse était d'utiliser files d'attente . Donc, chaque filtre reçoit une entrée et sortie la file d'attente. Pour cela, je pense que chaque filtre doit fonctionner à l'intérieur de son propre fichier et d'être notifié si des données sont ajoutées à la file d'attente d'entrée . (La «file d'attente de la sortie de Filtera par exemple est également la Entrée File d'attente de filtreB)

My Devineuse devinait utiliser la chaîne de responsabilité et < Code> Boost :: signaux2 Donc, filtrer par exemple se connecte au signal de filtrage. Filtera appelle ce filtre quand il a terminé son travail.

Laquelle des deux solutions est la plus flexible? Ou existe-t-il même un meilleur moyen de connecter les filtres?

Une question supplémentaire est-il également possible d'exécuter tout le pipeline à l'intérieur d'un fil afin que je puisse commencer plusieurs pipelines? (Dans l'exemple, 3 du pipeline filtrant-filtre-filtrant-filtrant UP et fonctionnent-ils?)


7 commentaires

Il y a un bon exemple dans Boost Asio: Github.com/ BOOSTORG / ASIO / BLOB / Développement / Example / CPP14 / Executor S / ... (aussi C ++ 11 GITUB.COM/BOOSTORG/ASIO/BLOB/Devop/Example/cpp11/Executor S / ... )


Cela pourrait être un bon candidat pour les coroutines si vous avez un compilateur qui le soutient. Je pense que les coroutines sont C ++ 20


Oui, j'ai aussi pensé à les utiliser, mais malheureusement, je ne pouvais pas utiliser de compilateur avec C ++ 20.


Vos filtres ne modifient pas ce qu'ils sont donnés du tout, je ne les appellerais pas aux filtres. Aussi, pourquoi forcer les gens à mettre en œuvre une autre base de base quand il n'y a qu'une seule fonction? std :: fonction fournit suffisamment d'abstraction. Cela dit, je ne comprends pas vos exigences, c'est-à-dire quel comportement avez-vous besoin? Avez-vous besoin d'une commande? Une étape peut-elle terminer le pipeline?


@Ulricheckhardt désolé peut-être que les exemples ne sont pas si bons. Certains filtreurs doivent également être en mesure de modifier le message avant de les remettre. J'ai mis à jour les exemples.


Dans votre code, c'est la responsabilité du filtre de remettre le filtre suivant. Je préfère retourner le message changé. Ensuite, cependant, j'ai besoin de demander à nouveau: est-ce juste le contenu du message ou aussi le type qui change? En outre, je me demande si un filtre peut également transmettre à plus d'un autre filtre? Le cas qu'il n'envoie rien semble être manifestement nécessaire, mais s'il existe plusieurs destinataires, il semble que la réflexion sur les événements et les auditeurs d'événements seraient une meilleure approche. Pouvez-vous fournir un réel exemple d'utilisation?


@Lrichececkhardt Ce n'est que le contenu du message qui change. Pas le type. Chaque filtre doit fonctionner sur le même type (chaîne ou peut-être une classe). L'avant n'est que d'un destinataire.


3 Réponses :


1
votes

Je pense que AbstractFilter n'est pas nécessaire et je suggère d'utiliser STD :: Tuple pour définir un pipeline: xxx pré>

pour exécuter un message via un pipeline DO (en utilisant c ++ 17 ): P>

template<typename Pipeline>
void run_in_pipeline(const std::string& message, Pipeline& pipeline){
  std::apply([&message](auto&& ... filter) {
    (filter.execute(message), ...);
  }, pipeline);
}


2 commentaires

Merci pour la réponse, le filtre abstrait a été défini parce que je veux que le pipeline soit composé de filtre différent pouvant être défini dans un fichier de configuration afin que le pipeline soit créé de manière dynamique sur la configuration.


@Kevin Donc, s'il a le temps d'exécution configurable, un pipeline serait un vecteur des pointeurs à des filtres abstraits? Le run_in_pipeline réel serait une boucle. Si vous souhaitez éviter le pointeur de s'opposer aux raisons de performance, quelque chose d'autre sera nécessaire car même std :: Fonction alloue de manière dynamique la mémoire en interne ..



1
votes

Je ferais de cette façon: Créez une liste avec toutes les versions implémentées du filtre abstrait. Donc, après votre exmample, après avoir lu le fichier d'entrée, je recevrai une liste avec: xxx

puis un seul thread (ou un sondage de fil si vous devez traiter de nombreuses ficelles à l'heure) en attente d'un chaîne dans une file d'attente d'entrée. Lorsqu'une nouvelle chaîne apparaît dans la piscine, les boucles de thread sur la liste de filtres et à la fin publie le résultat dans une file d'attente de sortie.

Si vous souhaitez l'exécuter en parallèle, vous devez trouver un moyen Pour conserver l'ordre des chaînes d'entrée Anche NELLE Stringhe DI Sortie.


1 commentaires

J'ai bien peur que notre italien ne soit pas à la hauteur.



1
votes

Je pense que le modèle de chaîne de responsabilité est plus simple, permet un code de nettoyage et une plus grande flexibilité.

Vous n'avez pas besoin de bibliothèques tierces pour la mettre en œuvre.
Ce que vous appelez les filtres sont en réalité gestionnaires . Tous les gestionnaires mettent en œuvre une interface commune, définissant une méthode unique qui pourrait être nommée gérer () et pourrait même prendre un objet comme paramètre à partager l'état. Chaque gestionnaire stocke un pointeur au gestionnaire suivant. Il peut ou non appeler cette méthode à ce sujet; Dans ce dernier cas, le traitement est arrêté et agit comme un filtre .

Les étapes de pipeline en cours d'exécution en parallèle sont plus impliquées si certaines d'entre elles nécessitent la sortie des autres comme entrée. Pour que différents pipelines fonctionnent en parallèle, chacun fonctionnerait sur son propre thread et vous pouvez utiliser une file d'attente pour y passer des entrées.


0 commentaires