Die bereits vorhandene Kommunikationsschicht CM mit prozeduraler Schnittstelle soll von einer objektorientierten Kommunikationsschicht OC überlagert werden. OC ist als objektorientiertes Framework zu realisieren. Trotzdem soll möglich sein, daß reine CM-Anwendungen mit OC-Anwendungen miteinander kommunizieren können.
[...]
Inhalt
1 Einleitung
1.1 Tätigkeitsbereich der Abteilung ATD IT PS 2
1.2 Motivation für das Kommunikations-Framework OC
1.3 Kommunikation mit Hilfe der CM-Schnittstelle
1.3.1 CM und OC
1.3.2 Schnittstelle der CM-Bibliothek
1.4 Kommunikation: dienstorientiert vs. datenorientiert
1.5 Realisierung von OC als Kommunikations-Framework
1.5.1 Allgemeines
1.5.2 Anforderungen an OC
1.6 Entwicklungsumgebung von OC
1.6.1 Dokumentation
1.6.2 Programmierung
2 Kommunikation zwischen Threads
2.1 Untersuchung von Threadkommunikationsarten auf Performance
2.1.1 Testanwendung
2.1.2 Asynchronous Procedure Calls (APC) als Kommunikationsbasis
2.1.3 Threadkommunikation mit Window-Messages
2.1.4 CM als allgemeine Kommunikationsschicht
2.1.5 Auswertung des Performance-Tests
2.2 Threadkonzept in OC
2.2.1 Threadklassen
2.2.2 Klassen für die Threadsynchronisation
3 Grobentwurf von OC
3.1 OC im Schichtenmodell
3.2 Wesentliche Klassen
4 Feinentwurf von OC
4.1 Aufbau eines Telegramms
4.1.1 Telegrammarten
4.1.2 Wrapper um Datenobjekt
4.1.3 Sichten eines Telegramms
4.1.4 Realisierung des Sichtenkonzepts
4.2 Verteilen der Telegramme im Dispatcher
4.2.1 Motivation
4.2.2 Telegramme innerhalb eines Frames verteilen
4.2.3 Weiterleiten eines gewöhnlichen Telegramms
4.2.4 Weiterleiten eines Ack-Telegramms
4.3 Auswertung der Telegramme in Handler
4.3.1 Behandlungsroutine
4.3.2 Handler-Basisklassen
4.3.3 Verwaltung der Handler
4.3.4 Verkettung der Handler - Forwardergraph
4.4 Telegrammerzeugung beim Empfang
4.4.1 Idee 1: Dispatcher erzeugt Telegrammobjekte
4.4.2 Idee 2: Handler erzeugt Telegrammobjekte
4.4.3 Möglichkeiten der Realisierung einer Telegramm-Factory
4.5 Telegramme versenden
4.5.1 Senden ohne Erwartung einer Quittung
4.5.2 Senden mit Erwartung einer Quittung
4.5.3 Versenden einer Quittung
4.6 Die Hauptklassen des Frameworks
4.6.1 Frame als Repräsentant eines Kommunikationspartners
4.6.2 Der Frame-Manager
5 Hilfsklassen für den Anwender
5.1 Bündeln einzelner Telegramme in ein Containertelegramm
5.1.1 Motivation
5.1.2 Anwendung von Containertelegrammen
5.1.3 Quittung des Containertelegramms
5.1.4 Aufbau des Containertelegramms
5.1.5 Kommunikation mit Containertelegrammen
5.2 Telegrammauswertung im Thread des Forwardinghandlers
6 Parametrierung der Kommunikationspartner
6.1 Struktur der Parameterdatei
6.2 Parser
6.3 Handler anhand der Parameterdatei erzeugen
7 Fehlerbehandlung
7.1 Synchrone Fehler
7.2 Asynchrone Fehler
8 OC aus Anwendersicht
8.1 Telegrammklasse erstellen
8.2 Handler erstellen
8.3 Kommunikationspartner erzeugen und registrieren
8.4 Senderklassen anwenden
8.5 Hilfsklassen anwenden
9 Probleme bei der Realisierung
9.1 Schwächen von C++
9.1.1 friend-Klassen vs. Packages
9.1.2 Interfaces vs. abstrakte Klassen
9.1.3 Templates in Bibliotheken
9.2 Schwächen von OC
9.2.1 Verwaltung der Telegramme und Handler
9.2.2 CM spezifisches Design
9.2.3 OC-Bibliothek
9.2.4 Telegramm-Factory
10 Ausblick
10.1 Generierung benutzerdefinierter Klassen mit einen Assistenten
10.2 Tool für die Parametrierung der Kommunikationspartner
11 Verzeichnisse
11.1 Literaturverzeichnis
11.2 Abbildungen
11.3 Index
1 Einleitung
1.1 Tätigkeitsbereich der Abteilung ATD IT PS 2
Eine Hauptaufgabe der Abteilung ATD IT PS 2 der Siemens AG ist die Bereitstellung von Software für den Anlagenbau. Für die Kommunikation der Komponenten in der Anlage wurde die Kommunikationsschicht „Communication Manager“ (CM) entwickelt. Diese Schicht kann direkt vom Anwendungsprogrammierer genutzt werden, indem er Funktionen der CM-Bibliothek benutzt. Kernaufgabe der Anlagenautomatisierung ist die Überwachung und Steuerung von Prozessen (Brauereien, Wasserkraftwerke, etc.). Die Bedienrechner und der Prozeßrechner sowie die Prozeßrechner untereinander kommunizieren mittels CM. In zukünftigen Anwendungen könnte die Kommunikation über eine objektorientierte Kommunikationsschicht „Object Communication“ (OC) erfolgen. OC ist Gegenstand der Diplomarbeit; es handelt sich hier lediglich um eine Art Design Studie, deshalb kann davon ausgegangen werden, daß das erstellte Design und die Implementierung von OC nicht direkt zum Einsatz kommen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 1: Typische Konfiguration einer Anlage
In Abbildung 1 senden Automatisierungsgeräte Telegramme an die Prozeßrechner bzw. die Prozeßrechner senden Telegramme an die Geräte. Der Prozeßrechner führt prozeßrelevante Berechnungen durch und steuert die Automatisierungsgeräte.
Die Bedien-/Überwachungsrechner repräsentieren einen Ausschnitt des Prozesses (z. B. Temperaturen, Drücke, Ereignisse, etc.). Der Anwender des Bedienrechners kann je nach Implementierung auch die Möglichkeit haben, in den Prozeß einzugreifen, zum Beispiel indem er die Kesseltemperatur ändert. Der Prozeßrechner kann deshalb als Server betrachtet werden, die Bedienrechner fungieren dann als Clients.
Häufig sind in einer Anlage mehrere bzw. gedoppelte Prozeßrechner vorhanden, um die Last zu verteilen bzw. die Ausfallsicherheit zu erhöhen. Die Kommunikation zwischen diesen Prozeßrechnern erfolgt ebenfalls über CM.
1.2 Motivation für das Kommunikations-Framework OC
Die Anwendungen in der Anlagenautomatisierung benutzen alle ähnliche Verfahren, um Telegramme mittels CM auszutauschen. Auch wird in vielen Anwendungen eine ähnliche Telegrammstruktur verwendet. Beim Versenden und Empfangen werden in der Regel ähnliche Codesequenzen benutzt. Beispielsweise befinden sich viele Anwendungen in einer einzigen Schleife, warten dort auf ein Telegramm und werten diesen nach dem Empfang entsprechend des Telegrammtyps aus.
Um nicht jedesmal beim Erstellen einer neuen Kommunikationsanwendung viele Codesequenzen einer bereits erstellten Anwendung duplizieren oder neu schreiben zu müssen, soll ein objektorientiertes Framework geschaffen werden, das für die Kommunikation Basisfunktionalitäten bereitstellt. Durch die Wiederverwendbarkeit des Frameworks in mehreren zukünftigen Anwendungen soll die Produktivität in der Softwareentwicklung erhöht werden. Damit sind Kosteneinsparungen zu erwarten.
Die bereits vorhandene prozedurale Kommunikationsschicht CM soll von einer objektorientierten Kommunikationsschicht OC überlagert werden, über diese sollen dann zukünftige Anwendungen miteinander kommunizieren. Die bisherige Kommunikation über CM soll aber weiterhin möglich sein (Mischbetrieb!), d. h., ein OC-Telegramm ist prinzipiell nicht von einem CM-Telegramm zu unterscheiden, da es keinen zusätzlichen Header an das CM-Telegramm anhängt. Der Mischbetrieb war gefordert, daß alte Anwendungen mit neue Anwendungen (die OC benutzen) miteinander kommunizieren können.
1.3 Kommunikation mit Hilfe der CM-Schnittstelle
CM wird für die Kommunikation von Anwendungen, die sich auf unterschiedliche Rechner befinden können, eingesetzt. Aber auch für Prozeß- und Threadkommunikation ist CM beim Transport großer Datenmengen gut geeignet.
1.3.1 CM und OC
CM wurde in der Siemens AG entwickelt, um ein zuverlässiges Kommunikationsmodul zu verwenden, das sowohl unter UNIX als auch unter Windows NT eine einheitliche Schnittstelle aufweist. Außerdem kann es sowohl für die Kommunikation über Rechnergrenzen hinweg als auch für die Kommunikation innerhalb eines Computers verwendet werden, z. B. für Prozeßkommunikation. Dadurch können Anwendungen erstellt werden, die eine hohe Portabilität aufweisen. Da CM vorwiegend in der Anlagenautomatisierung eingesetzt wird, wurde beim Design von CM viel Wert auf Robustheit, Determiniertheit und Performance gelegt. Außerdem wurde großen Wert auf asynchrone Kommunikation gelegt – es soll möglich sein, Telegramme versenden zu können, ohne auf eine Quittung warten zu müssen.
Die bessere Determiniertheit und die Asynchronität werden durch einen Shared Memory erreicht, der jedem CM-Partner[1] zugeordnet ist. Beim Versenden eines CM-Telegramms werden die Daten jedesmal in den bereits reservierten Puffer des Empfängers kopiert. Dadurch wird ein dynamisches Reservieren von Speicher verhindert. Dies ist erwünscht, denn die C++-Funktionen new bzw. malloc weisen aufgrund der Speicherverwaltung von Windows NT ein äußerst nichtdeterministisches Verhalten auf und sind sogar im Mittel zeitraubende Operationen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2: Aufbau des Puffers eines CM-Partners
Beim Versenden eines CM-Telegramms kann die Priorität angegeben werden (normal oder hoch). Deshalb enthält der Puffer eines CM-Partners- zumindest abstrakt betrachtet - zwei FIFOs. Der eine enthält die noch nicht abgeholten Telegramme mit gewöhnlicher Priorität. Der zweite Puffer enthält nur Telegramme mit hoher Priorität, die noch nicht abgeholt wurden. Will ein CM-Partner ein Telegramm empfangen, so wird zuerst sein Puffer mit Telegrammen hoher Priorität geleert, falls ein Telegramm vorhanden ist. Falls keines vorhanden ist, dann wird der Puffer mit normalpriorisierten Telegrammen geleert. Die Priorisierung von Telegrammen ist im Normalbetrieb nicht von Bedeutung. Lediglich für das Beenden einer Anwendung wird sie gelegentlich benutzt, die „Beenden“-Message wird dann mit hoher Priorität versendet.
Jeder CM-Partner eines Kommunikationssystems erhält einen Eintrag in der Datei CMPartners.cfg. Dort sind zu jedem CM-Partner die Parameter wie Name und Puffergröße eingetragen. Außerdem ist dort festgelegt, auf welche Rechner sich die CM-Partner befinden. Auf jedem Rechner des Kommunikationssystems befindet sich die gleiche CMPartners.cfg-Datei. Bei der CM-Installation wird dem Rechner eine System-Id zugewiesen, die dann für die Kommunikation über Rechnergrenzen hinweg verwendet wird, um den gewünschten CM-Partner zu lokalisieren.
Der Anwender[2] des OC-Frameworks muß sich mit folgenden Schichten auseinandersetzen:
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3: Komponenten einer OC-Anwendung
Eine typische Kommunikationsanwendung wird zusätzlich zu den Diensten von OC noch die API des Betriebssystems nutzen. Um während des Betriebs einer Anwendung Fehler oder kritische Zustände an den Benutzer auszugeben, wurde von der Siemens AG eine Trace-Modul (TR) entwickelt. Wenn sich eine Anwendung bei TR mit TROpen() anmeldet, kann sie mit TR_Text() und einigen weiteren Funktionen Text an TR senden. Der Anwender kann dann bei Bedarf bisherige Ausgaben der Anwendung mit Hilfe der Trace-Komponente ansehen.
In der Siemens-Abteilung IT PS 24 ist es üblich, jeden Funktionsaufruf dem Tracesystem mitzuteilen. Falls beim Kunden Fehler auftreten, können diese mit Hilfe der Traces lokalisiert und schnell gefunden werden. Teilweise wird TR auch beim Debugging verwendet. OC gibt beim Auftreten eines Fehlers den Fehlertext an das Tracesystem aus. Dem Anwender von OC steht das Tracesystem auch explizit zur Verfügung; er muß dem Framework mitteilen, unter welchen Namen (Kanal) bei TR mitgezeichnet werden soll.
CM selbst implementiert nur die lokale Kommunikation, also die innerhalb eines Rechners. Will man über Rechnergrenzen hinweg mit einem CM-Partner kommunizieren, so wird das „Remote Communication“-Modul (RC[3]) verwendet. Es stellt in Windows NT eine Verbindung zu anderen Rechnern über Sockets[4] her und überwacht die Verbindung.
1.3.2 Schnittstelle der CM-Bibliothek
Folgende CM-Funktionen können vom Anwendungsprogrammierer genutzt werden:
CMInit: Die Anwendung meldet sich damit unter einen systemweit eindeutigen Namen bei CM an. Sie ist damit als Sender und Empfänger registriert. Rückgabewert der Funktion ist ein CM-Handle, der die registrierte Anwendung als CM-Partner identifiziert. Der CM-Handle wird für Funktionen zum Versenden und Empfangen von Telegrammen benutzt.
CMClose: Trennt die Anwendung von CM und gibt Ressourcen frei.
CMSnd: Versendet ein Telegramm. Es wird keine Quittung erwartet.
CMRcv: Wartet auf den Empfang eines Telegramms und nimmt beim Eintreffen die empfangenen Daten entgegen.
CMSndExpAck: Versendet ein Telegramm, das eine Quittung erwartet.
CMSndAck: Versendet eine Quittung auf ein zuvor empfangenes Telegramms.
CMRcvAck: Wartet auf den Empfang eines Quittungstelegramms.
1.4 Kommunikation: dienstorientiert vs. datenorientiert
Benutzt man einen typischen Object Request Broker (ORB[5]) wie den in DCOM[6] für die Kommunikation von Anwendungen, so findet die Kommunikation mit Hilfe von Funktionsaufrufen auf Komponenten anderer Anwendungen (Komponenten) statt. Die Datenübergabe findet mit Hilfe der Parameterübergabe an Funktionen statt. Für den Transport großer Datenmengen sind handelsübliche ORBs eher ungeeignet, da meistens ein Konzept fehlt, große Datenmengen effizient an andere Anwendungen zu übertragen.
In DCOM werden Komponenten als Dienste bezeichnet. Durch den Methodenaufruf einer Komponente wird ein bestimmter Dienst ausgeführt. Dieser kann z. B. auf einen anderen Rechner ausgeführt werden. Man spricht hier, da Dienste ausgeführt werden und diese bereits beim Aufruf direkt angesprochen werden, auch von einer dienstorientierten Kommunikation. Für viele Anwendungen ist diese Architektur sinnvoll. Für den Transport großer Datenmengen, wie im Anlagenbau üblich, ist diese Architektur eher ungeeignet. Außerdem wurde die Robustheit und die Möglichkeit der asynchronen Kommunikation bei der Realisierung gängiger ORBs nicht wesentlich berücksichtigt. Ein weiterer Nachteil handelsüblicher ORBs ist die mangelhafte Portabilität.
Deshalb ist die Siemens-Abteilung ATD IT PS 2 im Anlagenbau noch nicht auf die ORB-Technologie für die Kommunikation von Anwendungen umgestiegen. Das Framework OC soll deshalb wie CM datenorientiert sein. Allerdings soll der Anwender mit Telegrammobjekten operieren und nicht mit reinen Datentelegrammen (C struct s).
1.5 Realisierung von OC als Kommunikations-Framework
1.5.1 Allgemeines
Für den Begriff Framework bzw. „Application Framework“ gibt es viele Definitionen (siehe auch [Fayad99] S. 4), die alle mehr oder weniger ähnlich sind, deshalb soll hier keine explizit zitiert werden. Inhalt der meisten Definitionen ist, daß es sich um wiederverwendbare Komponenten (Klassen) handelt, die ein bewährtes Design für eine Anwendung vorgeben. Ein „Application Framework“ kann auch als eine Art vorgefertigte Anwendung verstanden werden, in der an einigen Stellen vom Anwender noch Spezialisierungen vorzunehmen sind, um eine fertige Anwendung zu erhalten. Ein Framework deckt immer nur eine Gruppe von Anwendungen ab. Im Fall OC sind es Kommunikationsanwendungen, die mittels CM mit anderen Anwendungen kommunizieren und die Kommunikation als Schwerpunkt der Anwendung betrachten.
Wichtig ist der Unterschied zwischen Klassenbibliothek und Framework. Bei einer Klassenbibliothek handelt es sich lediglich um eine Ansammlung von Klassen, deren Klassen vom Anwender in der Regel unmittelbar genutzt werden können. Ein Beispiel dafür ist die STL (Standard Template Library, siehe Kapitel 1.6.2). Sie enthält wichtige Containerklassen und Algorithmen, um Container zu verwenden und zu modifizieren. Auch ein Framework enthält eine Sammlung von Klassen. Allerdings arbeitet in der Regel keines der Klassen unabhängig, sondern sie sind alle voneinander abhängig, geben also bereits das grobe Klassenmodell der zukünftigen Anwendung wieder und legen das Zusammenwirken der Klassen fest. Viele Klassen muß der Anwender erst spezialisieren, das Framework besitzt daher viele abstrakte Klassen.
In den Klassen wird häufig schon der Algorithmus eines Vorgangs vorgegeben, häufig werden rein virtuelle Methoden[7] verwendet. In dem Zusammenhang spricht man auch von einer „template method“ (siehe [Gamma95] S. 325). Der Polymorphismus wird so eine notwendige Eigenschaft der Sprache, mit der ein Framework zu realisieren ist.
Charakteristisch für Frameworks ist der inverse Kontrollfluß. Bei der Benutzung einer Klassenbibliothek wird in der Regel die gewünschte Klasse in das Programm eingebettet. Die Kommunikation zwischen den Klassen gibt der Anwender vor, d. h., welche Methoden in der Klasse in welcher Abfolge aufgerufen werden, bestimmt der Anwender. Die Methoden der wiederverwendbaren Komponenten ruft im Fall der Klassenbibliothek der Anwender auf. Bei Benutzung eines Frameworks wird der Code des Anwenders von der wiederverwendbaren Komponente durchlaufen – deshalb inverser Kontrollfluß.
Bei einem Framework steht das Design der Anwendungsvorlage im Vordergrund. Dadurch, daß abstrakte Klassen häufig noch eine Implementierung enthalten, wird nicht nur Design, sondern auch Code wiederverwendet.
Ziel der Realisierung eines Frameworks ist, daß die spezialisierte Anwendung effizient, einfach zu pflegen und zuverlässig ist. Deshalb ist es wichtig, daß das Design eines Frameworks gut durchdacht ist, schließlich soll es ja durch den Einsatz in vielen Anwendungen wiederverwendet werden. Durch die Wiederverwendbarkeit sollen Kosten bei der Softwareentwicklung gesenkt werden, da das Design und gewisse Codeabschnitte für viele Anwendungen nur einmal entwickelt werden müssen und eine Anwendung mit einem bekannten Design leichter zu pflegen ist. Allerdings ist der „return on investment“ für die Entwicklung eines Frameworks erst ab einer gewissen Benutzungsanzahl zu erwarten. Diese Anzahl hängt von vielen Faktoren ab, insbesondere aber davon, wieviel die Entwicklung des Frameworks kostet.
OC kann auch als ein „Application Framework“ für Kommunikationsanwendungen betrachtet werden – daher Kommunikations-Framework. Aber OC ist nicht nur eine Anwendungsvorlage, sondern kann auch als Kommunikationsmodul für eine Anwendung benutzt werden. Beispielsweise kann eine Windowsanwendung, die mit Hilfe des Frameworks Microsoft Foundation Classes (MFC) erstellt wurde, OC als Kommunikationsmodul enthalten. OC kann deshalb in andere Frameworks integriert werden, und ist deshalb nicht nur als Anwendungsvorlage zu verstehen sondern auch als Vorlage für das Kommunikationsmodul einer Anwendung.
1.5.2 Anforderungen an OC
Wie dem obigen Kapitel entnommen werden kann, wird mit der Realisierung von OC das Ziel verfolgt, Kommunikationsanwendungen, die mittels CM kommunizieren, schnell und daher kostensparend zu erstellen. Da das Design der Anwendungen bereits vorgegeben ist, lassen sich diese leicht pflegen.
Ein Anforderung an OC ist, daß ein Telegramm nicht als reine Datenstruktur (C- struct) betrachtet wird, sondern als eine Instanz einer C++-Klasse – das Telegramm enthält daher auch Methoden.
Weiterhin war gefordert, daß Handler definiert werden, deren Aufgabe es ist, Telegramme auszuwerten. Wenn ein Telegramm im Frame[8] eingetroffen ist, dann soll dies an den verantwortlichen Handler weitergeleitet werden.
Erfahrungsgemäß haben viele Anwendungen den gleichen Aufbau, nur daß sie unterschiedliche Telegramme auswerten können. Deshalb sollen die Handler dynamisch beim Initialisieren des Frames geladen werden. Welche Handler im Frame[9] zu laden sind, steht in der Parameterdatei, die dem Frame zugeordnet ist.
Um Klassen mit hoher Wiederverwendbarkeit zu erstellen, wurde neben Vererbung/Polymorphismus das Templatekonzept von C++ intensiv genutzt.
Die Implementierung von OC soll unter Windows NT erfolgen. OC soll so implementiert werden, daß der Quellcode leicht auf andere Plattformen (z. B. UNIX) portiert werden kann.
1.6 Entwicklungsumgebung von OC
1.6.1 Dokumentation
Dieses Dokument wurde in Microsoft Word 97 erstellt. Die UML-Modelle wurden, soweit möglich, in der Demoversion 4.0.3 von Rational Rose erstellt. Die übrigen Graphiken wurden mit ABC-Flow-Charter 3 von Micrografx gezeichnet. Als UML-Referenz wurde [Alhir98] verwendet. Bei Sequenzdiagrammen ohne Aktivierungsline kann angenommen werden, daß es sich immer nur um synchrone Aufrufe innerhalb eines Threads handelt. Die für den Entwurf verwendeten Design Patterns sind in [Gamma95] genau beschrieben.
1.6.2 Programmierung
Als Entwicklungsumgebung wurde das Visual Studio (Visual C++ 6.0) gewählt. Es dient in der Abteilung ATD IT PS 2 als Standardtool für die Softwareentwicklung unter Windows NT. Obwohl Visual C++ benutzt wurde, kam die MFC nicht zum Einsatz, um den Code einfach auf eine UNIX-Plattform portieren zu können.
Betriebssystemaufrufe, zum Beispiel um einen Thread zu erzeugen oder Threads zu synchronisieren, erfolgten mit Hilfe der Win32-API[10]. Als Alternative stand die POSIX[11] -Schnittstelle zur Verfügung. Allerdings konnte keine bewährte POSIX-Implementierung für Windows NT gefunden werden. Die Win32-API wurde, soweit notwendig, in selbsterstellte Klassen gekapselt. Beim Portieren von OC auf eine andere Plattform müssen dann nur diese auf die neue Plattform angepaßt werden.
Die Threadkommunikation erfolgte mit Hilfe von CM, um beim Portieren eine Erleichterung zu haben. CM ist nämlich auch auf UNIX verfügbar.
Um nicht übliche Algorithmen und Datenstrukturen neu implementieren zu müssen, wurde die Klassenbibliothek STL (Standard Template Library) eingesetzt. Sie existiert auch unter UNIX und enthält alle gängigen Containerklassen und Algorithmen, um Container zu modifizieren.
2 Kommunikation zwischen Threads
Eine OC-Anwendung ist immer multithreaded, da zusätzlich zum Mainthread[12] der Dispatcher - der Empfänger aller Telegramme im Frame - einen Thread enthält. Deshalb wurden Klassen erstellt, um den Umgang mit Threads zu vereinfachen. Diese werden dann in OC eingesetzt.
Threads mit gleicher Priorität laufen in Windows NT nach dem Round-Robin-Prinzip. Alle bereiten Threads bekommen den Prozessor immer höchstens eine Zeitscheibe zugeordnet. Am Ende einer Zeitscheibe findet ein Wechsel zum nächsten Thread statt. Das „Aushungern“ von Threads wird in OC vermieden, indem alle Threads mit der gleichen Priorität parametriert werden.
2.1 Untersuchung von Threadkommunikationsarten auf Performance
Die wichtigsten Threadoperationen sind in einer Klasse gekapselt. In OC synchronisieren sich die Threads nicht nur miteinander sondern es sollen zwischen den Threads auch Daten ausgetauscht werden. Eine Interthreadkommunikation ist notwendig. Die Threadklasse soll dafür eine Messagequeue[13] verwenden. Für die Implementierung der Threadkommunikation stehen mehrere Alternativen zur Verfügung – diese sollen auf Performance untersucht werden. Für den Test wird eine Anwendung erstellt; sie enthält für jede Threadkommunikationsart eine Threadklasse. Die Threadklassen haben eine gemeinsame Basisklasse CThread, um das Testprogramm einfacher zu realisieren.
CThread-Klasse:
Die Threadklasse CThread enthält neben den Methoden Start und Stop noch GetMsg und SndMsg für die Threadkommunikation.
void* GetMsg(UINT *puMsgSize): In der Threadfunktion wird GetMsg aufgerufen, wenn eine Message erwartet wird. Die Message ist ein Datenblock. Auf diesen wird ein Zeiger zurückgegeben. Außerdem wird noch die Größe des Datenblocks zurückgegeben. Falls sich keine Message in der Queue befindet, wird beim GetMsg -Aufruf auf eine Message gewartet.
BOOL SndMsg(void* pMsg, UINT uMsgSize): Die Instanz, die an den Thread Daten übergeben will, ruft vom Threadobjekt SndMsg auf. Die Methode erwartet einen Zeiger auf den Datenblock und die Größe des Datenblocks.
void Do(): Diese Methode ist vom Anwender der Threadklasse zu implementieren und wird im erzeugten Thread ausgeführt.
In Windows benötigen viele API-Funktionen eine Callback-Funktion als Parameter, dies gilt auch für das Erzeugen eines Threads mit der Funktion _beginthreadex der C++-Laufzeitbibliothek. Sie erwartet einen Zeiger auf die Threadfunktion.
Memberfunktionen können in C++ nicht als Callback-Funktionen verwendet werden, da der C++-Compiler eine Memberfunktion in der Regel wie eine gewöhnliche Funktion mit einen zusätzlichen Parameter (this -Zeiger) übersetzt. Dies würde beim Aufruf der Callback-Funktion Probleme bereiten. Klassenfunktionen (static -Funktionen) können jedoch als Callback-Funktion implementiert werden, da sie nicht über diesen impliziten Parameter verfügen. In CThread wurde die Threadfunktion Run deshalb als Klassenfunktion deklariert. Sie benötigt als Parameter this, um Do von CThread aufrufen zu können.
2.1.1 Testanwendung
Die Performance der unterschiedlichen Threadkommunikationsarten soll mit Hilfe einer Testanwendung untersucht werden.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 4: Klassenmodell der Threadanwendung
Es werden drei Threadklassen erstellt, die unterschiedliche Kommunikationsarten implementieren. Diese sollen in den folgenden Kapiteln näher erläutert werden. Der Performance-Test ermittelt die Zeit, wie schnell eine Message einer bestimmten Größe versendet wird und beim Empfänger angekommen ist.
Für diesen Zweck wurde die Klasse CTestThread implementiert, die von einer Threadklasse abgeleitet ist. Sie enthält folgende Implementierungen:
SetStart: Setzt die Zeit auf 0 und übergibt die Anzahl, wie oft das Senden/Empfangen für einen Testlauf wiederholt wird.
GetLoopTime: Wartet, bis der Test zu Ende ist und liest die Zeitdauer des Testlaufs
Do: Implementierung der Threadfunktion – sie signalisiert den Aufrufer von GetLoopTime, wenn der Thread alle Messages des Testlaufs empfangen hat.
CTestThread wurde als Templateklasse realisiert. Der Templateparameter soll eine Threadklasse sein und wird als Basisklasse für CTestThread verwendet (siehe Abbildung 4).
2.1.2 Asynchronous Procedure Calls (APC) als Kommunikationsbasis
Die Threadklasse CAPCThread realisiert die Threadkommunikation (GetMsg / SndMsg) mit Hilfe von APC-Messages. Um APC besser verstehen zu können, sollen zuerst einige I/O-Funktionen der Win32-API vorgestellt werden, die APC benutzen.
I/O-Funktionen in Windows:
Will man in Windows aus einer Datei (oder Gerät, Pipe[14], etc.) lesen oder in eine Datei schreiben, so sind die Funktionen ReadFile beziehungsweise WriteFile zu verwenden. Als Parameter kann den Funktionen übergeben werden, ob sie synchron oder asynchron auszuführen sind. Im asynchronen Fall wird unmittelbar nach dem Funktionsaufruf wieder zum Aufrufer zurückgekehrt; mit GetOverlappedResult kann dann erst bei Bedarf auf das Ergebnis gewartet werden.
Zusätzlich sind in der Win32-API die I/O Funktionen ReadFileEx und WriteFileEx vorhanden. Es handelt sich um Funktionen, wo die I/O-Operation immer asynchron ausgeführt wird, sie benötigen zusätzlich einen Zeiger auf eine Callback-Funktion, die auch I/O Completion Routine genannt wird. Diese wird beim Beenden der asynchronen Operation aufgerufen. Dann braucht (und kann) nicht mehr mit GetOverlappedResult auf das Ergebnis der I/O-Funktion gewartet werden, da das Ergebnis in der Callback-Funktion ausgewertet wird.
APC-Queue:
In Win32 enthält jeder Thread eine APC-Queue. Jede Message in der Queue enthält einen 32bit-Wert und einen Zeiger auf die APC-Routine (auch I/O Completion Routine). Hat sich nun die asynchrone Funktion ReadFileEx / WriteFileEx beendet, so wird eine APC-Message in die Queue abgelegt. Die Messages werden immer dann abgearbeitet, wenn sich der Thread im „alertable state“ befindet (siehe unten).
„Alertable state“ eines Threads:
Es gibt einige Win32-Funktionen, die den Thread beim Aufruf in den „alertable state“ versetzen. Als Beispiel soll hier die Funktion WaitForSingleObjectsEx genannt werden. Ihr wird als Parameter ein Event-Objekt, ein Timeout-Wert und ein alertable-Flag übergeben. Das alertable-Flag muß auf TRUE gesetzt sein, damit der Thread beim Aufruf in den „alertable state“ übergeht. Denn nur dann wird die APC-Queue abgearbeitet, falls Messages vorhanden sind. Beim Abarbeiten der Messages werden die korrespondierenden APC-Routinen aufgerufen. Diese werten den 32bit-Wert der APC-Message aus.
Der Thread bleibt im Fall von WaitForSingleObjectsEx solange im Wartemodus, bis das Eventobjekt signalisiert wird, der Timeout abgelaufen ist oder APC-Messages abgearbeitet wurden.
Die APC-Routinen werden innerhalb der Funktion aufgerufen, die den Thread in den „alertable state“ versetzt (z. B. innerhalb von WaitForSingleObjectEx); d. h. die APC-Routinen werden im Thread, dem die APC-Message zugeordnet ist, ausgeführt.
Im Fall ReadFileEx/WriteFileEx wird implizit eine APC-Message in die Queue eingereiht. Mit der Funktion QueueUserAPC lassen sich explizit APC-Messages in die Queue des gewünschten Threads einreihen, sie wurde bei der Realisierung der Klasse CAPCThread für das Versenden verwendet.
Die Threadkommunikation mit APC-Messages wird im Gegensatz zu Window-Messages (siehe unten) als Low-Level Kommunikation bezeichnet und soll unter Windows besonders schnell sein, deshalb wurde sie beim Performance-Test berücksichtigt. Nachteilig ist, daß beim Versenden von APC-Messages keine Prioritäten vergeben werden können. Außerdem besteht nicht die Möglichkeit, beim Empfang nur Messages eines bestimmten Typs abzuholen.
Beim Integrieren der APC-Kommunikation in eine Klasse ist folgende Einschränkung in Kauf zu nehmen.
Einschränkung bei der Implementierung:
Im APC-Fall ist es nicht möglich, eine Do -Methode zu schreiben, die in einer Schleife mehrmals GetMsg aufruft. Ein Message-Empfang ist immer mit einem Aufruf der APC-Funktion verbunden. Die APC-Funktion und die eigentliche Threadfunktion (die bei _beginthreadex angegeben wurde) können sich nicht explizit synchronisieren, sie werden ja im gleichen Thread ausgeführt. Weiterhin kann nach dem Ausführen der „alertable“ Win32-Funktion nicht festgestellt werden, wieviele APC-Messages abgearbeitet wurden – bevor die Win32-Funktion aus den „alertable state“ zurückkehrt, wird die APC-Queue vollständig abgearbeitet.
Die tatsächliche Threadfunktion (Parameter von _beginthreadex) wartet in einer Schleife im „alertable state“ und arbeitet gegebenenfalls die APC-Messages ab. Die Do -Methode wird in der APC-Funktion ausgeführt.
Exkurs: APC und I/O-Completion Ports:
Die APC-Funktionen finden Verwendung bei der Realisierung von Client-/Server-Anwendungen – zumindest auf Low-Level Ebene. Typischerweise wartet der Server an einer Pipe mit ReadFileEx auf eine Nachricht, die der Client sendet. Die Nachricht wird dann in der I/O-Completion-Routine ausgewertet und das Ergebnis wird an den Client zurückgesendet.
APC ist allerdings nicht für jede Architektur geeignet, weil der Thread mit dem ReadFileEx -Aufruf auch die empfangene Message in der I/O Completion Routine auswerten muß. Dieses Modell wird auch „serial model“ genannt (siehe auch [Richter97]).
Die I/O Completion Ports in Windows NT realisieren das „concurrent model“. Dort gibt es einen Empfangsthread. Dieser ist für das Entgegennehmen der Message verantwortlich und übergibt sie an einen Thread im Threadpool (Sammlung von Threads). Dieser wertet die Clientanfrage aus. Bei Multiprozessor-Systemen hat man den Vorteil, daß dann Clientanfragen echt parallel ausgeführt werden können (im Idealfall pro Prozessor ein Thread).
2.1.3 Threadkommunikation mit Window-Messages
CWinMsgThread realisiert die Threadkommunikation mit Hilfe von Window-Messages.
Wenn mit _beginthreadex ein Thread erzeugt wird, geht Windows davon aus, daß es sich um einen Worker-Thread handelt, ein Thread, der lediglich eine länger andauernde Operation asynchron ausführt. Es wird die APC-Queue erzeugt, weitere Ressourcen, beispielsweise für die Programmierung mit Fenstern werden nicht bereitgestellt. Erst wenn eine USER- oder GDI-Funktion[15] aufgerufen wird, erhält der Thread zusätzlichen Overhead. Es werden drei Queues bereitgestellt, die für die Kommunikation von Window-Messages erforderlich sind; sie werden weiter unten beschrieben.
Daraus folgt, wenn der Workerthread zwar keine Fenster aber die Messagequeues für Window-Messages benutzen will, so muß im Workerthread ein Dummy-Aufruf erfolgen (z. B. die USER-Funktion PeekMessage – sie liest eine Window-Message, ohne sie zu verbrauchen).
Posted-Message-Queue:
Mit Hilfe von PostThreadMessage kann eine Message in die Posted-Message-Queue eines anderen Threads eingereiht werden. Es handelt sich um eine asynchrone Operation. Ob der Empfänger die Nachricht tatsächlich empfangen hat und sie sinnvoll interpretieren konnte, kann der Absender nicht unmittelbar feststellen.
Send-Message-Queue:
Mit Hilfe von SendMessage kann eine Window-Message direkt an eine Behandlungsroutine eines anderen Threads gesendet werden. Beim SendMessage -Aufruf wird die Message in die Send-Message-Queue des Empfängerthreads eingereiht. Der SendMessage -Aufruf blockiert den Aufrufer solange, bis die Antwort des Empfangsthreads in der eigenen Reply-Message-Queue (siehe unten) eingetroffen ist. Daraus folgt, wenn der Empfangsthread die Message nicht abholt (nie GetMessage aufruft), dann hängt der Aufrufer.
Mit der Funktion SendMessageTimeout kann dies verhindert werden, als Parameter wird zusätzlich zur Message der Timeout-Wert übergeben, der angibt, wie lange maximal auf die Quittung gewartet wird.
Mit GetMessage kann eine Message aus der Send-Message- oder aus der Posted-Message-Queue geholt werden; die Funktion hat der Empfänger von Window-Messages aufzurufen. Mit GetMessage werden zuerst die Messages der Send-Message-Queue geholt. Der Grund ist, daß der Absender der Message in der Send-Message-Queue synchron auf die Quittung wartet und deshalb nicht allzu lange blockiert werden soll. Erst anschließend wird die Posted-Message-Queue ausgelesen (ebenfalls mit GetMessage).
Reply-Message-Queue:
In der Behandlungsroutine einer Message aus der Send-Message-Queue wird mit ReplyMessage dem Aufrufer von SendMessage mitgeteilt, daß ein Ergebnis auf die empfangene Message bereits vorliegt. Das System setzt den Aufrufer von SendMessage wieder frei, indem der Ergebniswert in seine Reply-Message-Queue eingereiht wird.
Window-Messages haben im Gegensatz zu APC-Messages den Vorteil, daß mit Hilfe der Send-Message- und Reply-Message-Queue auch Messages quittiert werden können. Außerdem ist nicht jede Message mit einem expliziten Funktionsaufruf verbunden.
In der Klasse CWinMsgThread wurde die Threadkommunikation mit Hilfe der Posted-Message-Queue realisiert.
Sowohl APC als auch Window-Messages sind ausführlich in [Richter97] beschrieben.
2.1.4 CM als allgemeine Kommunikationsschicht
Sowohl bei APC als auch beim Window-Messages handelt es sich um eine Kommunikationsart, die ausschließlich für Threadkommunikation verwendbar ist. Der Vorteil, daß sowohl der Sender- als auch der Empfangsthread im selben Speicherbereich arbeiten, kann deshalb bei der Implementierung dieser Kommunikationsarten ausgenützt werden (und wurde hoffentlich ausgenutzt). Die Kommunikation sollte daher besonders effizient sein.
In der Klasse CCMThread wird CM für die Threadkommunikation verwendet. Wie im Kapitel 1.3.1 bereits beschrieben, wird CM auch für die Kommunikation zwischen Anwendungen verwendet. Deshalb befindet sich der CM-FIFO in einem Shared-Memory. Der Zugriff auf den Shared Memory wird mit Hilfe von Funktionen für die Prozeßsynchronisation realisiert. Prozeßsynchronisation ist in der Regel aufwendiger als Threadsynchronisation.
Trotzdem hat CM den Vorteil daß kein new / delete erforderlich ist, da der FIFO als Shared Memory bereits existiert und die zu versendeten Messages in diesen Bereich kopiert werden. Bei APC/Window-Messages muß jede Message explizit mit new angefordert werden. new ist unter Windows eine zeitaufwendige Operation, besonders dann, wenn größere Speicherblöcke angefordet werden.
Bei der Kommunikation mit CM repräsentiert der Thread einen CM-Partner. Dieser muß in der Konfigurationsdatei CMPartners.cfg eingetragen werden. Dies erweist sich als nachteilig, insbesondere deshalb, weil der Anwender mit diesen CM-Partner nur bei der Parametrierung in Berührung kommt. Bei APC/Window-Messages wird der Empfangsthread über die Thread-Id bzw. über den Threadhandle angesprochen, daher ist von Anwenderseite keine Parametrierung der Threads erforderlich. CM bringt jedoch Vorteile beim Portieren der Anwendung von der Windows- auf die UNIX-Plattform, da auch eine CM-Implementierung unter UNIX zur Verfügung steht. Weiterhin steht ein Naming-Service zur Verfügung, beim Versenden ist deshalb schon der Empfänger bekannt ohne zu wissen, auf welchen Rechner er sich genau befindet.
2.1.5 Auswertung des Performance-Tests
Für den Test wurden unterschiedliche Telegrammgrößen verwendet. Das Senden/Empfangen erfolgte pro Telegrammgröße 1000 mal. In Abbildung 5 wurde dann jeweils der Mittelwert der Zeit Senden/Empfangen eingetragen.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 5: Auswertung des Performance-Tests
Wie aus dem Diagramm ersichtlich, ist die Kommunikation über CM erst bei sehr großen Telegrammen (> 12 Kbyte) schneller als die Kommunikation über Window-Messages. APC ist aufgrund der Low-Level-Kommunikation sehr schnell, hat allerdings die Nachteile, wie bereits in Kapitel 2.1.2 beschrieben. Vermutlich enthält die APC-Queue aufgrund des Schedulings von Threads nicht so viele Messages wie die Window-Message-Queue. Je mehr Speicher angefordert wird, desto langsamer wird vermutlich der new -Aufruf, daher ist APC um ein vielfaches schneller. Der Peek im Graph von Window-Messages (s. Abbildung 5) läßt sich wahrscheinlich durch ein (mehr oder weniger zufälliges) Auslagern von Daten auf die Festplatte erklären.
CM wurde letztendlich als Kommunikationsart für Threads in OC verwendet. Dem Nachteil, daß explizit ein CM-Name für den Thread anzugeben ist steht der Vorteil gegenüber, daß für eine beliebige Kommunikation (Threads, Prozesse, Anwendungen) immer die selbe Schnittstelle verwendet wird (sowohl unter UNIX als auch unter Windows NT).
2.2 Threadkonzept in OC
Die CM-Threadklasse der Testanwendung wurde für OC nochmals angepaßt. Außerdem orientiert sich das Klassenmodell für Threads an dem von Java - siehe auch [Flanagan99] S. 370.
2.2.1 Threadklassen
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 6: Threadklassen in OC
Die Klasse CThread umfaßt noch keine Kommunikationsmethoden, sie kann direkt verwendet werden. Für manche Zwecke reicht es, daß sich Threads lediglich synchronisieren und kein Daten mit andere Threads austauschen. CCMThread erweitert die Klasse CThread um die Methoden SndMsg und GetMsg für die Threadkommunikation.
Die eigentliche Threadfunktion, die asynchron auszuführende Operation ist in den Threadklassen noch nicht implementiert. Dies kann realisiert werden, indem man zu einer der beiden Threadklassen eine Subklasse erstellt und dort die Do -Methode überschreibt. Um nicht nur wegen dem Überschreiben von Do eine eigene Klasse erstellen zu müssen, kann auch das Interface IRunnable verwendet werden. Ein Klasse, die IRunnable implementiert, muß die Do -Methode implementieren. Sie kann der Threadklasse CThread bzw. CCMThread im Konstruktor mit einem IRunnable -Zeiger übergeben werden.
2.2.2 Klassen für die Threadsynchronisation
2.2.2.1 Zugriff auf Membervariablen
Um den Zugriff auf Variablen zu synchronisieren, wurden die Klassen CCritSection und CSyncObject implementiert.
CSyncObject:
Es handelt sich um eine Synchronisationsklasse, sie enthält zwei Methoden:
void Lock(): Der Aufrufer wird blockiert, falls bereits ein anderer das CSyncObject -Objekt mit Lock belegt hat, um auf die Ressource (Variable) zuzugreifen, andernfalls wird die Ressource belegt.
void Unlock(): Gibt den Lock auf die Ressource wieder frei. Der Code zwischen Lock und Unlock gilt als geschützt. Dort kann dann auf Membervariablen zugegriffen werden, die von mehreren Thread durch Methodenaufrufe geändert werden können.
CCriticalSection:
Die Klasse erwartet im Konstruktor einen Zeiger auf ein COCSyncObject -Objekt. Im Konstruktor findet auf das Synchronisationsobjekt ein Lock -Aufruf statt. Im Destruktor wird die Ressource wieder mit Unlock freigegeben.
Typischerweise hat eine Multilthreaded-Klasse ein COCSyncObject -Objekt. In jeder public -Methode (die auf Membervariablen zugreift) wird zu Beginn ein CCritSection -Objekt angelegt und mit dem Synchronisationsobjekt initialisiert. Dadurch wird sichergestellt, daß das Modifizieren der Membervariablen „atomar“ abläuft.
2.2.2.2 Threads über Signal synchronisieren
Falls Thread A auf eine Aktion von Thread B warten will, dann muß Thread B dies dem Thread A mit einem Signal mitteilen. Diese Synchronisationsart wurde in die Klasse COCSimpleEvent gekapselt. Sie enthält folgende Methoden:
BOOL Wait(UINT uTimeoutSec): Wartet solange, bis der Thread signalisiert wurde bzw. bis der Timeout abgelaufen ist.
void Signal(): Signalisiert den Thread, der mit Wait auf das Signal wartet.
3 Grobentwurf von OC
3.1 OC im Schichtenmodell
OC benötigt bei der Kommunikation zwar keinen zusätzlichen Header im CM-Telegramm, ist aber trotzdem als eine Kommunikationsschicht zu verstehen. Im folgenden sollen OC und die benachbarten Schichten kurz beschrieben werden.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 7: Umgebung von OC
Anwendung:
Die Anwendungen nutzen die Dienste (Klassen) von OC, um mit andere Teilnehmer zu kommunizieren. OC wird die Dienste (Funktions-API) von CM nutzen, um Telegramme an einen anderen Kommunkikationspartner zu senden.
Das frameworkspezifische an OC ist, daß der Anwender spezialisierte Klassen in das Framework „einhängen“ bzw. registrieren kann. Wann Methoden der registrierten Klassen aufgerufen werden, entscheidet das Framework (siehe inverser Kontrollfluß, Kapitel 1.5.1).
OC:
Das Framework kann in folgende Module gegliedert werden.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 8: Prinzipieller Aufbau von OC
OC unterstützt dem Anwender bei der Realisierung von Telegrammklassen. Jede Telegrammklasse korrespondiert mit einem Datenobjekt. dieses repräsentiert ein CM-Telegramm. Über den Puffer des CM-Telegramms wird für den einfacheren Zugriff eine Struktur (C- struct) darüber gelegt.
Die Kommunikation gliedert sich in zwei Teile. Zum Versenden von Telegrammen werden Klassen zur Verfügung gestellt. Der Dispatcher[16] ist die erste Instanz eines Kommunikationspartners, die Telegramme empfängt. Er entscheidet anhand einer Zuordnungstabelle, an welchen Handler[17] das empfangene Telegramm für die Auswertung übergeben werden soll.
CM:
OC wird über die CM-Schnittstelle (siehe Kapitel 1.3.2) in der Regel mit anderen OC-Partnern kommunizieren.
3.2 Wesentliche Klassen
Um das Gesamtsystem gut verstehen zu können, sind im folgenden Klassenmodell nur die wesentlichen Klassen aufgeführt.
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 9: Vereinfachtes Klassenmodell
Ein Frame (COCFrame) ist im folgenden immer eine Instanz, das einen Kommunikationspartner (CM-Dienstnehmer) repräsentiert. Es ist möglich, daß einer Anwendung mehrere CM-Adressen zugeordnet sind. Dies wird dann über mehrere Frames realisiert; sie werden vom Frame-Manager (COCFrameManager) verwaltet.
Ein Handler (COCSyncHandler) hat die Aufgabe, ein Telegramm, das vom Dispatcher (COCDispatcher) empfangen wurde, auszuwerten. Beim Erstellen eines Handlers muß der Anwender seinen benutzerdefinierten Handler von der Handlerbasisklasse COCSyncHandler ableiten und die Run -Methode (Telegramm-Auswertung) implementieren. Die Handlerbasisklassen COCSyncHandler und COCRcvHandler sind als Template realisiert und erwarten als Parameter eine benutzerdefinierte Telegrammklasse. Damit kann der Handler mit Hilfe einer Telegramm-Factory (COCMultiTelFactory oder COCSingleTelFactory) beim Datenempfang das zugehörige Telegrammobjekt erzeugen, es wird dann in der Run -Methode für dessen Auswertung benutzt.
Um bei der Auswertung nicht direkt auf ein CM-Telegramm (char -Puffer oder C- struct) operieren zu müssen, hat der Anwender eine Wrapperklasse um das CM-Telegramm mit den speziellen Messagetyp zu implementieren. Der Anwender wird bei der Implementierung einer Telegrammklasse durch eine Telegrammbasisklasse (COCTel) unterstützt, daß er nur noch Get- und Set-Methoden implementieren muß, um auf das CM-Telegramm zugreifen zu können.
Empfangsseite:
Jeder Frame enthält einen Dispatcher. Er nimmt in einem eigenen Thread die Telegrammdaten entgegen und sucht nach dem Empfang eines CM-Telegramms anhand des Messagetyps den Handler, der das Telegramm auswerten soll. Gesucht wird dabei in der Handlertabelle (COCHandlerTable) des Dispatchers, diese enthält eine Messagetyp-Handler-Zuordung. Die Telegrammdaten werden nach dem Empfang vom Dispatcher anhand der Handlertabelle an den entsprechenden Handler übergeben.
[...]
[1] CM-Partner: eine Instanz, die Dienste von CM nutzt und selbst eine CM-Adresse repräsentiert
[2] Anwender: ist im folgenden immer ein Entwickler, der OC benutzt
[3] RC, CM und TR : Module des Softwarepakets Winbase; dieses wurde von der Firma Siemens AG entwickelt
[4] Socket: Netzwerk-Programmierschnittstelle, über die Anwendungen unter Windows Daten austauschen; sie abstrahiert das zugrundeliegende Netzwerk (z. B. TCP/IP) – siehe auch www.msdn.microsoft.com
[5] ORB: Middleware, die eine Kommunikation (lokal oder remote) zwischen Softwarekomponenten zuläßt
[6] DCOM: Distributed Component Object Model, ORB-Implementierung von Microsoft; DCOM ist bereits in Windows 9x/NT enthalten
[7] rein virtuelle Methode: Methode einer Klasse, die noch keine Implementierung enthält
[8] Frame: im folgenden eine Instanz, die mittels OC über CM kommuniziert
[9] Frame: Kommunikationspartner
[10] Win32-API: Sammlung von Systemfunktionen unter Windows 9x/NT
[11] POSIX: standardisierte Funktions-API für Betriebssysteme
[12] Mainthread: Thread, der die main-Funktion in einer C++ Anwendung durchläuft
[13] Messagequeue: FIFO, der für asynchrone Kommunikation verwendet wird
[14] Pipe: Kommunikationskanal, über den Prozesse Daten austauschen
[15] USER- oder GDI-Funktion: Win32-Funktion für die Oberflächenprogrammierung.
[16] Dispatcher: Instanz, die empfangene Telegramme an die entsprechende Subinstanzen verteilt
[17] Handler: Instanz, die Telegramme auswertet
-
-
-
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X. -
-
Upload your own papers! Earn money and win an iPhone X.