C++ Broker Pattern und Smartpointer

#7767411
Lesenswert?

Hoí da

Kontext ich schreibe an einer Struktur, die sich am Broker-Pattern orientiert und bidirektional funktioniert - also Clients können beim Broker Daten requesten und der reicht die Anfrage weiter. Es gibt also Broker, welcher Clients mit Servern verbindet. Dabei kann ein Broker mehrere Server und mehrere Clients haben und Client und Server sind immer in einer Klasse kombiniert, da es eine Kettenstruktur mit Verzweigungen wird. Der Broker führt etwas Logik aus, bevor er die Daten der Server an die als Client angemeldeten Objekte weiter gibt.

Frage In den Guidelines gibt es eine Regel 20, welche sagt

Use unique_ptr or shared_ptr to represent ownership Ich bin noch nicht sicher, ob der Broker in dem Sinne eine Ownership an den Servern und Clients hat, aber das automatisierte Memorymanagement, welches mit Smartpointern kommt, würde dafür sorgen, dass ein ClientServer-Object deleted wird, wenn seine letzte Instanz bei einem Broker entfernt wurde. Von der Warte her, wäre ja sinnvoll sharepointer zu verwenden und die list´s of raw pointer durch smartpointer typen zu ersetzten?

Viele Grüße

1
class BrokerBase
2
{
3
public:
4
    BrokerBase();
5

6
    void RegisterServer(ClientServerBase* _server);
7
    void Serve(int& itterration, float _pos);
8

9
    void RegisterClient(ClientServerBase* _client);
10
    void Request(int& itterration);
11

12
private:
13
    list<ClientServerBase*> serverList;
14
    list<ClientServerBase*> clientList;
15

16
    unsigned int serverCntr;
17
    int curItterration;
18
};
Persönliche Seite #7767656
Lesenswert?

Jasson J. schrieb:

Ich bin noch nicht sicher, ob der Broker in dem Sinne eine Ownership an den Servern und Clients hat,

Wenn der Broker Ownership an beiden hat - wann werden dann überhaupt jemals Server und Clients gelöscht? Ich denke mal der Broker ist eine Art globale Instanz?

ClientServerBase ist eine gemeinsame Basisklasse für Clients und Server? Das klingt verkehrt.

Jasson J. schrieb:

list<ClientServerBase*> serverList;

list<> sollte man nur relativ selten verwenden, meistens lieber vector<>.

Jasson J. schrieb:

unsigned int serverCntr;

Wäre da nicht ein std::size_t sinnvoller?

Harald K. schrieb:

Aus irgendeinem Grund muss ich jetzt an diesen Kommentar hier denken:

Wenn jemand Quantenphysik macht, kommst du dann auch vorbei und sagst "Früher hat uns F=m*a gereicht"?

#7767809
Lesenswert?

Versuche zuerst alle Funktionalitäten (nicht Funktionen im Sinne der Programmiersprache) zu sammeln. Dann erkennt man meistens schnell dass bestimmte Konstrukte passen oder nicht passen.

  • Wie sieht es mit einem "Unregister" von Server oder Client aus? Gibt es das nicht?
  • Wie werden Fehler signalisiert? Was passiert bei Timeouts?
  • Was ist das Kriterium, welcher Client mit welchem Server sprechen soll?
  • Welche Funktionalitäten soll eine ClientServer Klasse haben?

Jasson J. schrieb:

Es gibt also Broker, welcher Clients mit Servern verbindet. Dabei kann ein Broker mehrere Server und mehrere Clients haben und Client und Server sind immer in einer Klasse kombiniert, da es eine Kettenstruktur mit Verzweigungen wird.

Verstehe ich nicht. Gibt es eine 1:1 Beziehung zwischen Server und Client, sprich ein Server kann immer nur mit einem Client kommunizieren?

#7767865
Lesenswert?

Die einfache Frage wurde ja oben schon gestellt: wer oder was hat die ownership für Server und clients?

BrokerBase::RegisterServer bekommt ja eine Instanz übergeben. Wo kommt die her? Soll BrokerBase die Ownership für die ServerInstanz übernehmen, und im Extremfall die ServerInstanz deleten, wenn die nicht mehr benötigt wird, oder passiert das ausserhalb?

Oliver

#7768604
Lesenswert?

Niklas G. schrieb:

Jasson J. schrieb:

list<ClientServerBase*> serverList;

list<> sollte man nur relativ selten verwenden, meistens lieber vector<>.

Stimmt - guter Punkt

Jasson J. schrieb:

unsigned int serverCntr;

Wäre da nicht ein std::size_t sinnvoller?

Da hab ich den Zweck nicht als Kommentar geschrieben - der Member zählt nicht die Anzahl der registrierten Server. Weil es mir beim Start vom Thread nur um die Ownership-Frage ging, hab ich die Gesamtidee nicht beschreiben, um den thematischen Fokus zu behalten.

Ich will Elemente schreiben, mit denen ich eine verzweigte Kettenstruktur aufbauen kann, dem Prinzip folgend wie im Bild. Sever und Client sind dabei mehr als eine Input und eine Output-Seite des selben Objektes zu sehen, deren Seiten jeweils zu verschiedenen Brokern gelinkt sind. Dabei handelt es sich nicht um Server und Clients im Sinne von PC´s und Handys, sondern eher um die Ausdrücke aus dem Client-Server-Pattern.

Lirum Larum - der Broker kann von nem Client gepingt werden, Daten bereit zu stellen - in meiner Anwendung ganz simpel ein float Wert. Den Ping reicht er erstmal bis nach oben weiter an alle Server die registiert sind. Die Daten / Werte die dann kommen addiert er auf und gibt die Summe erst weiter, wenn alle Server geantwortet haben. if(serverCntr == serverList.size())

Oliver S. schrieb:

Die einfache Frage wurde ja oben schon gestellt: wer oder was hat die ownership für Server und clients? ... oder passiert das ausserhalb?

Oliver

Danke auf jeden Fall für die Denkanstöße, beantworten kann ich das gerade noch nicht.

Angehängte Dateien:
#7768674
Lesenswert?

Niklas G. schrieb:

Also ein Graph? Gerichtet oder ungerichtet? Azyklisch oder nicht?

Auf jeden Fall jetzt schon nah dran und mit einer Überlegung, die ich noch klären muss, könnte das letztendlich der Fall sein.

Wenn es keine konzeptionelle Notwenigkeit oder sinnvollen Hintergrund gibt, das das bisschen Logik, was im Moment im Broker ist (damit meine ich nicht das register und ausstehende unregister), sondern das mit die im Moment so genannten ClientServer Objekte zu verlagern

dann bin ich bei nem Graph angekommen.

Wobei ich glaube, dass das den Character der Eingangsfrage nicht ändert. Das sich ClientServer-Instanzen gegenseitig besitzen klingt wenig sinnig - aber das Auto-Delete-Feature / bzw. Memorymanagement via Smartpointer ist weiterhin attraktiv.

Also die Hausaufgabe an mich bleibt die selbe - "Wem gehören die Instanzen?"

Persönliche Seite #7768804
Lesenswert?

Jasson J. schrieb:

dann bin ich bei nem Graph angekommen.

Naja, ein Graph kann auch unterschiedliche Knoten haben. Also sowohl Broker und ClientServer können Knoten sein. Bei vielen Implementationen von Graphen gibt es eine "große" Graph-Klasse welches alle Knoten (und Kanten) besitzt, z.B. ein schlichter vector<ClientServer>. Wird der Graph zerstört, sind auch alle ClientServer weg.

Die Frage ist ob das für dich passt oder ob der Graph zwischendurch "umgebaut" werden soll, also z.B. Teile davon zwischendurch löschen. Wenn nicht, reicht o.g. simpler Ansatz.

#7768870
Lesenswert?

Niklas G. schrieb:

Es kann aber logischerweise nur einen unique_ptr auf ein Objekt geben. Oft braucht man aber noch weitere non-owning-Referenzen auf eine Objekt. Wenn diese nie Null sein können, nimmt man eine Referenz (&), ansonsten einen klassischen Pointer.

Es gibt keinen Grund in modernem C++ raw pointer einzusetzen (ausser vielleicht zum austausch mit low-level code). Mittlerweile sind genug Sprachmittel vorhanden um korrekteren/sicheren code in C++ zu schreiben, raw pointer gehoeren definitiv nicht dazu.

#7769056
Lesenswert?

Roger S. schrieb:

Mittlerweile sind genug Sprachmittel vorhanden um korrekteren/sicheren code in C++ zu schreiben,

Ohne Pointer gehts halt manchmal nicht. Seh ich auch kein Problem darin - wo unterscheidet sich denn ein 'const T* const' z.B. groß von einem 'const T&', außer dass es auch nullptr werden kann? Klar, sind plain-refs oder rvaluie-refs besser als Ptr, aber wie oben schon von Niklas erwähnt - bei nem Baum mit Parent-Pointer und Childlist wirds mit Smartpointern mitunter schon ziemlich lustig, spätestens wenn die Referenzzählung nie mehr 0 werden kann.

Und realistisch betrachtet, spätestens beim 3rdParty- oder Legacy-APIs kommt man oft schlicht nicht drumrum.

Jasson J.:

ich schreibe an einer Struktur, die sich am Broker-Pattern orientiert und bidirektional funktioniert - also Clients können beim Broker Daten requesten und der reicht die Anfrage weiter.

Klingt mir irgendwie nach eierlegender Wollmilchsau-Ansatz, der genererisch für alle erdenklichen Eingaben magischerweise den Goldenen Hammer darstellt, kurz gesagt: Overengineering in Lauerstellung.

Warum nicht nen normales MVC-Pattern in der Spielart ECB, dafür aber ausimplementiert für jeweils ein konkretes Client-Server-Paar. Wenn dann noch Abstraktion nötig ist, halt einfach den Controller noch polymorph zu irgendeiner Schnittstelle machen und fertig ist.

Gast #7769255
Lesenswert?

Ach du liebe Zeit! Was immer noch für ein Sprachschrott: Raw Pointer, Unique Pointer, Shared Pointer die im Prinzip Ownerpointer sind, Weak Pointer, Dexter Pointer, Montagspointer, Weihnachtspointer, Sindney Pointier.

Glasklarer Designfail, Kernschrott C++ bleibt eben Kernschrott, in der Sprachdauerbaustelle nix neues.

Wenn man oben schon das vermurkste Diagramm anschaut, weiss man gleich welche Experten diesen Müll verwenden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren