Das Frisör-Problem - Multitasking, Petrinetze und IPC mit Toolbook
Transcription
Das Frisör-Problem - Multitasking, Petrinetze und IPC mit Toolbook
Projektarbeit Sleeping Barber Inhalt Inhalt Inhalt ............................................................................................................ 1 Abbildungsverzeichnis ...................................................................................... 3 Vorwort.......................................................................................................... 4 Ursprüngliches Konzept.................................................................................... 5 Aufgabenstellung.......................................................................................... 5 Werkzeuge .................................................................................................. 5 Gliederung................................................................................................... 5 Startseite.................................................................................................. 6 Intro ........................................................................................................ 6 Textuelle Beschreibung des Problems ........................................................... 6 Aufstellen eines Systemmodells ................................................................... 6 Animiertes Petrinetz ................................................................................... 6 Logisches Programm Pseudocode................................................................. 8 Konkretes Programm mit Animation ............................................................. 8 Extro........................................................................................................ 8 Ablauf ...................................................................................................... 8 Gestaltung ................................................................................................ 9 Inhalt des Intro ....................................................................................... 10 Inhalt der textuellen Beschreibung................................................................ 11 Das Problem des schlafenden Friseurs ........................................................ 11 Inhalt Aufstellen eines Systemmodells/Petrinetz ............................................. 12 Inhalt Pseudocode ...................................................................................... 14 Änderungen am Konzept ................................................................................ 15 Gestaltung ................................................................................................. 15 Intro ......................................................................................................... 15 Aufstellen eines Systemmodells.................................................................... 15 Animiertes Petrinetz.................................................................................... 15 Sonstiges .................................................................................................. 16 Die Programmteile......................................................................................... 17 Intro und Extro als Flash-Animation .............................................................. 17 Einbinden der Flash-Animationen in Toolbook................................................. 18 C-Code...................................................................................................... 22 Behandlung von Windows Ressourcen ........................................................ 23 Barber .................................................................................................... 24 Customer................................................................................................ 27 DLL ........................................................................................................ 29 OpenScript-Code ........................................................................................ 32 Kommunikation Toolbook->Dll .................................................................. 32 Kommunikation Prozesse->Toolbook .......................................................... 33 Windows Botschaften ............................................................................... 33 Animation ............................................................................................... 35 Aufgetretene Probleme................................................................................... 37 Bedienungsanleitung...................................................................................... 40 Anforderungen: .......................................................................................... 40 Installationshinweis: ................................................................................... 40 Bedienung ................................................................................................. 40 Nachtrag ...................................................................................................... 42 Animation .................................................................................................. 42 Miriam Hofmann Bernd Frick Seite - 1 - Projektarbeit Sleeping Barber Inhalt WindowsXP ................................................................................................ 45 Blockade ................................................................................................... 46 Setup........................................................................................................ 47 Miriam Hofmann Bernd Frick Seite - 2 - Projektarbeit Sleeping Barber Abbildungsverzeichnis Abbildungsverzeichnis Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung Abbildung 1: Petrinetz...................................................................................... 7 2: Grundlayout................................................................................. 9 3: Gestaltungsraster ....................................................................... 15 4: Zeitleiste mit verschiedenen Ebenen ............................................. 17 5: Bibliothek mit den Symbolen von Gampp....................................... 18 6: Symbol "gamp_seite_gehen" ....................................................... 18 7: Toolbook Instructor Catalog ......................................................... 19 8: Eigenschaftsfenster vom Media Player ........................................... 20 9: Object Browser .......................................................................... 20 10: Eigenschaften von Shockwave Flash Object.................................. 21 11: Ein alter Friseur ........................................................................ 22 12: Toolbook fasst zu...................................................................... 37 13: Bedienungsleiste....................................................................... 41 Miriam Hofmann Bernd Frick Seite - 3 - Projektarbeit Sleeping Barber Vorwort Vorwort Danken möchten wir den folgenden Personen, die sich freiwillig uns zur Verfügung gestellt haben: Frau Keller, Herr Bernhard, Herr Brümmer, Herr Gampp, Herr Koch, Herr Mayenberger und Herr Usadel. Miriam Hofmann Bernd Frick Seite - 4 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Ursprüngliches Konzept Aufgabenstellung Es soll eine Lern-CD-Rom erstellt werden, die ein Problem der Interprozesskommunikation beispielhaft behandelt. Am „Problem des schlafenden Friseurs“ (Sleeping Barber) soll den Studenten vorgeführt werden, welche Probleme auftreten können und wie diese zu beheben sind. Hierzu wird das Friseurproblem in ein Petrinetz überführt und die Begriffe „Transition“ und „Stelle“ eingeführt. Das Petrinetz soll grafisch dargestellt und animiert sein. Aus dem Petrinetz soll sich Pseudocode und schließlich ein CProgramm ableiten lassen. Werkzeuge • Toolbook • Flash • Adobe Photoshop • Borland C++ Builder • Sonstige Grafikwerkzeuge Gliederung Die Lern-CD-Rom soll in folgende Kapitel gegliedert werden: • Startseite • Intro • Textuelle Beschreibung des Problems • Aufstellen eines Systemmodells • Animiertes Petrinetz • Logisches Programm, Pseudocode • Konkretes Programm • Extro • Als Erweiterung ist eine Lernzielkontrolle geplant. Miriam Hofmann Bernd Frick Seite - 5 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Startseite Hier wird der Titel der CD-Rom und die Autoren genannt. Intro Das Intro soll eine Einführung in das „Friseurproblem“ geben. Zu sehen sind ein Friseursalon, ein Friseur, ein Friseurstuhl, 1-7 Kunden und fünf Wartestühle. Die vorkommenden Personen sollen bekannte Professoren aus der FH sein. Eventuell werden wir uns auch selbst verewigen. Geplant sind Prof. Koch als Friseur, Prof. Keller, Usadel, Gampp, Brümmer, Mayenberger, Herr Bernhard als Kunden. Zuerst wird ein reibungsloser Ablauf dargestellt: Friseur schläft, Kunde kommt, weckt Friseur, bekommt Haare geschnitten, nächste Kunden kommen, setzen sich auf Wartestühle bis alle besetzt sind. Wenn kein Wartestuhl frei ist, gehen die Kunden wieder. Mit der Zeit verzählt sich der Friseur, d.h. er schläft, obwohl noch ein Kunde da ist. Der Kunde bewegt sich von Zeit zu Zeit, kratzt sich, bohrt in der Nase, liest. Koch schnarcht. Es wird Nacht. Das Intro kann vom Benutzer abgebrochen werden. Das Intro soll mit Musik aus Rossinis „Barbier von Sevilla“ unterlegt sein. Die Figuren sind gezeichnet. Das Intro wird mit Flash erstellt und in Toolbook durch den universellen Mediaplayer abgespielt. Textuelle Beschreibung des Problems Hier soll der Ablauf und die Problemstellung der Interprozesskommunikation beispielhaft erklärt werden. Der Student soll in diesem Abschnitt erfahren, welche Prozesse und Daten anstehen und wie diese miteinander kommunizieren und auf gemeinsame Daten zugreifen. Weitere Probleme zum Beispiel die Situation in einer Druckerwarteschlange sollen herangezogen werden (mit Zeichnung). Aufstellen eines Systemmodells Hier soll erklärt werden, wie man praktisch an ein Interprozesskommunikationsproblem herangeht. Es soll Schritt für Schritt ein Systemmodell erstellt werden. Animiertes Petrinetz Aus dem Systemmodell soll ein Petrinetz erstellt werden, dieses soll auch wieder Schritt für Schritt aufgebaut werden. Die Schaltregeln sollen anhand von Animationen erläutert werden. Dabei hat der Benutzer Schalter, um den Friseur und die Kunden zu starten und Schalter, um den Mutex oder eine der Semaphore durch ein oder mehrere Flag/s zu ersetzen. Miriam Hofmann Bernd Frick Seite - 6 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Mit den Aktionen des Benutzers werden Prozesse generiert, die tatsächlich konkurrieren und dies auf der Toolbook-Oberfläche sichtbar machen: Marken wandern und aktivieren die Transitionen, zu denen sie wandern. Diese werden entsprechend der Windows-Optik aktiv. OpenScript teilt hierzu dem globalen Speicher einer Laufzeitbibliothek seine FensterID mit. Auf Knopfdruck generiert diese Dll dann auch einen Barberprozess, der seinerseits über Toolbook-eigene Windows-Botschaften Befehle zur Steuerung der Toolbook-Oberfläche absetzt. So ist es möglich, die einzelnen Prozessphasen in Echtzeit in Toolbook darzustellen. Ebenso agieren die Kunden, von denen der Anwender bis zu fünf einzeln starten kann. Der Benutzer soll die Möglichkeit haben, fehlerhaften Quelltext (Flags statt Semaphore, kein Mutex auf Waiting) ablaufen zu lassen. Die Prozesse sollen in korrekter und fehlerhafter Version mehrfach gestartet werden können. Abbildung 1: Petrinetz Miriam Hofmann Bernd Frick Seite - 7 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Logisches Programm Pseudocode Pseudocode mit textuellen Erläuterungen. Konkretes Programm mit Animation Darüber hinaus wäre es schön, aber noch ungewiss, wenn es uns gelänge, dass die tatsächlich ablaufenden konkurrierenden Prozesse auch das Intro steuerten. Extro Friseurladen, Nacht, der Kunde ist gegangen. Herr Bernhard kommt mit Besen kehrt Haare auf, schließt Tür ab, und geht. Koch schläft immer noch, und schläft und schläft. Ablauf Die CD-ROM besteht aus sieben „Kapiteln“, der Benutzer wird linear durch den Inhalt geführt, hat aber die Möglichkeit über ein Inhaltsverzeichnis gezielt ein Kapitel auszuwählen. Das Intro wird am Anfang der CD abgespielt und kann abgebrochen werden. Danach kann sich der Benutzer alle Kapitel anschauen. Das Extro wird mit der letzten Seite automatisch abgespielt. Animationen sind für die Kapitel Intro, Petrinetz, Konkretes Programm und Extro geplant. Interaktivität: Petrinetz, Konkretes Programm Miriam Hofmann Bernd Frick Seite - 8 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Gestaltung Die verschiedenen Kapitelseiten besitzen alle das gleiche Grundlayout, das sieht folgendermaßen aus: Oben in der Mitte ist die aktuelle Überschrift des Kapitels, darunter die Seite mit dem eigentlichen Inhalt. Im unteren Bereich ist die Navigationsleiste, links und rechts sind Pfeile für die Vorund Zurück-Navigation. Dazwischen sind sieben Buttons mit denen man zu den einzelnen Anfangskapitelseiten wechseln kann. Die Kapitel werden durch Symbole repräsentiert, die einerseits in der Überschrift und andererseits auf den Buttons vorkommen. Sollte ein Kapitel aus mehreren Seiten bestehen wird das im Symbol in der Überschrift durch aktuelle Seitenzahl/Seitenanzahl angezeigt. Es wird die Schriftart Verdana benutzt. Schriftgröße in der Überschrift 22 pkt und im Textblock 16 pkt. Kapitelüberschrift Text, Bild, Animation Zurück Kap 2 Kap 3 Kap 4 Kap 5 Kap 6 Kap 7 Vor Abbildung 2: Grundlayout Auflösung: 1024 x 768 Miriam Hofmann Bernd Frick Seite - 9 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Inhalt des Intro Beschreibung Friseursalon: Es sind zu sehen • Friseurstuhl • Friseur schläft auf Friseurstuhl (schnarcht, kratzt sich, sabbert) • Frisierwagen mit Werkzeug (Schere, Kamm) • Fünf Wartestühle • Tischchen mit Zeitschriften • Schaufenster mit Aufschrift „Hugo“ • Tür mit Glocke Der Friseur zählt seine wartenden KundInnen anhand des Klingens der Türglocke. Denkblasen zeigen seinen Zählerstand an. Jedes Mal wenn Kunde bezahlt singt Koch: Lalala! 1. Usadel kommt Straße entlang, betritt Laden, Tür macht „Palimpalim“. Koch wacht durch Türglocke auf (zuckt zusammen), richtet sich. Denkblase=1 Usadel setzt sich. Koch fängt an ihn zu rasieren 2. Keller kommt, tritt ein, grüßt, sieht, dass Friseur beschäftigt ist, geht zur Warteecke, setzt sich, nimmt Zeitschrift und blättert darin. Denkblase=2 3. Es kommen Mayenberger und gleich dahinter Brümmer, treten gleichzeitig ein, setzen sich ans andere Ende von den Wartestühlen, sie plauschen. Türglocke läutet nur einmal. Denkblase=3 4. Usadel ist fertig, bezahlt, geht. Koch singt lalala 5. Koch zählt runter. Denkblase=3-1=2 6. Koch bittet Keller Platz zu nehmen 7. Gampp tritt ein, grüßt, setzt sich, nimmt Zeitschrift und ließt. Denkblase=3 8. Keller fertig, zahlt, geht 9. Koch zählt, 2 10.Brümmer kommt an die Reihe 11.Brümmer fertig, zahlt, geht 12.Koch zählt, 1 13.Mayenberger bekommt Haare geschnitten 14.Mayenberger fertig, zahlt, geht 15.Koch zählt 0, geht schlafen 16.Gampp langweilt sich, starrt Löcher in die Luft, bastelt Papierflieger, popelt in der Nase 17.Es wird Nacht 18.Gampp geht Miriam Hofmann Bernd Frick Seite - 10 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Inhalt der textuellen Beschreibung Das Problem des schlafenden Friseurs Das Beispiel des schlafenden Friseurs zeigt anschaulich, was passieren kann, wenn es keinen gegenseitigen Ausschluss durch Semaphoren für die Synchronisation von Prozessen oder Threads gibt. Im Intro ist die Türglocke der Zähler, jedes Mal wenn die Tür aufgeht, klingelt die Türglocke und der Friseur zählt seinen Kundenzähler um eins hoch. Wenn der Friseur mit einem Haarschnitt bei einem Kunden fertig ist, zählt er seinen Zähler um eins herunter. Beim Hinausgehen klingelt die Glocke nicht. Die Fehlerquelle liegt bei der Türglocke, da gleichzeitig mehrere Kunden hereinkommen können, während die Türglocke nur einmal bimmelt. Um den Fehler zu verhindern, müsste gewährleistet werden, dass immer nur ein Kunde durch die Tür kann. In der Interprozesskommunikation wäre diese Schutzmöglichkeit ein Semaphor. In der Praxis könnte man das Friseurproblem anhand eines Druckerspoolers demonstrieren. Jeder Prozess, der eine Datei ausdrucken möchte, muss den Namen der Datei in ein spezielles Spooler-Verzeichnis schreiben. Der Drucker-Dämon überprüft periodisch, ob dort auszudruckende Dateien eingetragen worden sind, druckt sie gegebenenfalls aus und löscht die Namen aus dem Verzeichnis. Es gibt zwei Variablen, die eine verweist auf den nächsten freien Platz, die andere auf die nächste zu druckende Datei. Diese beiden Variablen stehen in einer Datei auf die alle Prozesse zugreifen können. Nun kann es vorkommen, dass zwei Prozesse mehr oder weniger gleichzeitig eine Datei ausdrucken möchten. Der Prozess A, der gerade ausgeführt wird, liest die Variable mit dem nächsten freien Platz und merkt sie sich. Der Prozess A wird unterbrochen, da seine Prozessorzeit um ist. Das Betriebssystem veranlasst einen Prozesswechsel zum Prozess B, der auch drucken möchte. Dieser liest ebenfalls die Variable mit den freien Platz im Verzeichnis, merkt sie sich, schreibt den Dateinamen an die freie Stelle und erhöht den Wert um 1 (auf den nächsten freien Platz). Seine restliche Prozessorzeit verwendet er für andere Dinge. Irgendwann wird der Prozess A, der zuerst drucken wollte, an der Stelle weiter ausgeführt an der er unterbrochen wurde. Er hat sich die freie Stelle gemerkt und schreibt nun seinen Dateinamen an diese Stelle, dabei überschreibt er den anderen Dateinamen. Die Datei vom zweiten Prozess B wird also nie gedruckt. Dieses Problem kann durch gegenseitigen Ausschluss (Mutual Exclusion) der Prozesse beim Zugriff auf das Spooler-Verzeichnis umgangen werden. Miriam Hofmann Bernd Frick Seite - 11 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Inhalt Aufstellen eines Systemmodells/Petrinetz Zwischen konkurrierenden Prozessen kommt es zu Wettkampfbedingungen („race conditions“) wenn zwei oder mehrere von ihnen gleichzeitig versuchen, auf eine einzelne Systemressource zuzugreifen. Um die Wettkampfbedingungen in den Griff zu bekommen, ist es notwendig einen Systementwurf zu machen, der die Vorgänge in ihrer zeitlichen Abfolge abbilden kann. Eine Möglichkeit der Darstellung ist die Modellierung als Petrinetz. Petrinetze sind ein wichtiges Hilfsmittel zur Modellierung nebenläufiger, asynchroner, verteilter oder paralleler Prozesse. Ein Petrinetzmodell kennt viererlei Elemente: Stellen („places“) repräsentieren Bedingungen. Das könnten Zustände, Signale oder bereitgestellte Daten sein. Auch Stellen mit mehreren Marken sind möglich und könnten zum Beispiel einen Materialbehälter darstellen. Bei uns sind es die Signale „Kunde ist da“ oder „Friseur ist bereit“ oder der Semaphor zum Schutz der Zählvariablen. Stellen sind im Petrinetz durch einen Kreis symbolisiert. Transitionen(„transitions“) stehen für Aktionen. Dies können Ereignisse, Vorgänge oder Berechnungsschritte sein. Im Beispiel sind es die einzelnen Aktivitäten der Prozesse, also zum Beispiel das Haarschneiden, das Schlafen und das Warten. Symbol für eine Transition ist im Petrinetz das Rechteck. Kanten verbinden Stellen und Transitionen und zeigen damit die Vor- und Nachbedingungen der Aktionen an und geben damit die Fließrichtung der Marken vor. Marken wandern durch das Petrinetz und ermöglichen durch Besetzen der Stellen die Veränderung der Bedingungen und damit die Ausführung der Aktionen. Man nennt dies das „Schalten“ der Transitionen. In unserem Beispiel braucht der Friseur eine Marke um aufzuwachen und die Kunden je eine um bedient zu werden. Das Symbol der Marke ist ein gefüllter Kreis. Miriam Hofmann Bernd Frick Seite - 12 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Das Petrinetz ist ein Bedingungs-Ereignisnetz. Hier gelten die folgenden Regeln: • Jedes Petrinetz hat eine Anfangsmarkierung. • Transitionen sind im Petrinetz immer über Stellen miteinander verbunden. • Eine Transition kann nur schalten, wenn alle nachgeschalteten Stellen frei und alle vorgelagerten Stellen mit Marken belegt sind. • Ausnahmen hiervon sind: • Stellen, die gleichzeitig Ein- und Ausgang sind: Durch das Schalten wird hier die Stelle frei und nach dem Schalten von der gleichen Transition wieder belegt • Transitionen ohne vor- oder nachgelagerte Stellen. Deren Schalten ist nur von ihrem Aus- bzw. Eingang abhängig. • Die Transition verzehrt beim Schalten je eine Marke an allen ihren Eingängen. • Bei Beenden ihrer Aktion belegt die Transition alle ihren Ausgangsstellen mit je einer Marke. • Es ist möglich, Konfliktstellen darzustellen, bei denen je nach Ergebnis einer Bedingungsprüfung die Marke in die eine oder andere Richtung wandert. • Miriam Hofmann Bernd Frick Seite - 13 - Projektarbeit Sleeping Barber Ursprüngliches Konzept Inhalt Pseudocode Algorithmus für den Friseur: Wenn kein Kunde (Kundenzähler = 0) da ist, schlafe. Wenn Türglocke bimmelt, wache auf und zähle den Kundenzähler um eins hoch und schneide Haare. Wenn fertig mit Haare schneiden, zähle Kundenzähler um eins herunter. Solange Kundenzähler nicht Null ist, schneide Haare. Algorithmus für Kunden: Wenn Friseur schläft, wecke ihn. Wenn Friseur beschäftigt, warte auf Wartestuhl. Wenn schon fünf Kunden warten, gehe wieder und komm später wieder. Eine geeignete Lösung für dieses Problem, ohne dass es unter den einzelnen Kunden (Threads) zu Wettkampfbedingungen kommt, wäre folgender Pseudocode: Binary semaphore mutex = 1; Counting semaphore customers = 0, barber=0; int waiting = 0; … void Barber(void) { while(true) { P(customers); // wait for or get next customer P(mutex); Waiting--; V(barber); V(mutex); Cut_Hair(); } } void Customer(void) { while(true) { P(mutex); //check waiting room if(waiting < numChairs) { waiting++; V(customers); V(mutex); P(barber); //wait for barber get_hair_cut(); } else V(mutex); } } Miriam Hofmann Bernd Frick Seite - 14 - Projektarbeit Sleeping Barber Änderungen am Konzept Änderungen am Konzept Gestaltung Das Raster wurde auf Grund der Inhalte geändert. Es besteht nun aus vier Blöcken, die zu je einem drittel Text, Bild oder Animation und zu zwei drittel Text, Bild oder Animation enthalten. Kapitelüberschrift Zurück Kap 2 Kap 3 Kap 4 Kap 5 Kap 6 Kap 7 Vor Abbildung 3: Gestaltungsraster Intro Das Intro wurde insofern geändert, dass aus Zeitgründen kleine Zwischenanimationen wie „Keller liest“ und „Brümmer und Mayenberger plaudern“ herausgenommen wurden. Aufstellen eines Systemmodells Im Kapitel „Aufstellen eines Systemmodells“ kann der Benutzer kleine Animationen ablaufen lassen, die ihm die Regeln eines Petrinetzes veranschaulichen. Animiertes Petrinetz Für das animierte Petrinetz lassen sich Barber- und Customer-Prozesse starten, die durch ihren Ablauf die Animation steuern. Miriam Hofmann Bernd Frick Seite - 15 - Projektarbeit Sleeping Barber Änderungen am Konzept Sonstiges • • Die Steuerung des eines Filmes durch real ablaufende Prozesse wurde bald aufgegeben: Ob und wie sich Flash von außen steuern lässt ist ungewiss. Den Einsatz eines anderen Werkzeuges (Director?) zu evaluieren, fehlte die Zeit. Der Anwender hat in dieser Version keine Möglichkeit, fehlerhaften Quelltext ablaufen zu lassen. Prozesse, die ohne Mutex auf das Shared Memory zugreifen, wurden zwar versuchsweise implementiert, doch erscheint dadurch ein Fehler in endlicher Zeit nicht provozierbar. Hierzu müsste auf die Animation verzichtet und die Erzeugung der Customer automatisiert werden, damit die Prozesse in rascher Folge auf das Shared Memory zugreifen. Dem Benutzer müsste man dann durch Zählerstände eventuelle Fehler sichtbar machen, doch wäre immer noch ungewiss, ob und wann diese eintreten. Miriam Hofmann Bernd Frick Seite - 16 - Projektarbeit Sleeping Barber Die Programmteile Die Programmteile Intro und Extro als Flash-Animation Das Intro und Extro wurde in Flash erstellt, da Flash eine komfortable Umgebung bietet um kleine Animationsfilme zu gestalten. Die Filme besitzen mehrere Ebenen für Hinter-, Vordergrund, Darsteller und Sounds. Abbildung 4: Zeitleiste mit verschiedenen Ebenen Der Hintergrund ist auf die unteren Ebenen verteilt. Jeder Darsteller besitzt mehrere Ebenen, je nach seiner Position im Film. Wenn er z.B. von draußen in den Friseurladen kommt, liegt die Darstellerebene unter der Ebene mit den Wänden. Im Fenster ist der Darsteller sichtbar, da die Fenster einen Alphawert von 53% besitzen, d.h. alle unter dieser Ebene liegenden Ebenen sind mit 47% sichtbar. Um die Hauptdarsteller ihren lebenden Vorbildern so ähnlich wie möglich zu gestalten, wurden die Personen fotografiert und die Fotos eingescannt. In Flash wurden die Bilder unter die aktuelle Zeichenebene gelegt und abgezeichnet. Die Ebene mit dem Foto wurde danach wieder gelöscht. Jede Figur besitzt in der Bibliothek einen eigenen Ordner in denen die jeweiligen Animationen als Symbole abgelegt werden. Ein Symbol ist eine Animation mit eigener Zeitleiste. Das Symbol wird in die Szene eingefügt und läuft als Schleife ab. Zum Beispiel besitzt eine Figur verschieden Laufanimationen, die jeweils aus drei bis zehn Bildern bestehen. In die Szene eingefügt, wird die Laufanimation bis zum nächsten Schlüsselbild in Schleife abgespielt. Um die Figur nicht nur auf der Stelle laufen zu lassen wird in der Szene ein Bewegungstweening von dem gewünschten Start- bis Endpunkt erzeugt. Miriam Hofmann Bernd Frick Seite - 17 - Projektarbeit Sleeping Barber Die Programmteile Abbildung 5: Bibliothek mit den Symbolen von Gampp Abbildung 6: Symbol "gamp_seite_gehen" Einbinden der Flash-Animationen in Toolbook Das Intro und Extro werden als SWF-Dateien im Toolbook eingebunden. Im Toolbook Instructor Catalog gibt es unter dem Ordner Media Players einen Universal Media Player. Dieser wird mit der Maus an die gewünschte Stelle auf der Oberfläche gezogen. Miriam Hofmann Bernd Frick Seite - 18 - Projektarbeit Sleeping Barber Die Programmteile Abbildung 7: Toolbook Instructor Catalog Sobald der Mediaplayer losgelassen wird, geht ein Fenster auf. In diesem wird der Pfad des Flashfilmes angegeben und Autostart aktiviert. D.h. wenn die Seite mit dem Film aufgerufen wird, wird der Film abgespielt. Miriam Hofmann Bernd Frick Seite - 19 - Projektarbeit Sleeping Barber Die Programmteile Abbildung 8: Eigenschaftsfenster vom Media Player Im Objekt Browser sieht man, welche Objekte der Universal Media Player besitzt. Das Objekt „Group media Controls“ bietet die Möglichkeit eine Abspielsteuerung für den Film einzublenden. Die Objekte „mediaStage“, „OCXArea“ und „ShockwaveFlash“ sollten alle die gleiche Größe und Position besitzen. Abbildung 9: Object Browser Im „ShockwaveFlash“-Objekt müssen noch Einstellungen vorgenommen werden: Miriam Hofmann Bernd Frick Seite - 20 - Projektarbeit Sleeping Barber Die Programmteile Abbildung 10: Eigenschaften von Shockwave Flash Object Bei Qualität, Skalieren, Ausrichten und Fenstermodus kann die Standardeinstellung übernommen werden. Abspielen muß aktiviert sein, Wiederholung sollte nicht aktiviert sein, da der Film sonst in einer Schleife abgespielt wird. Geräteschriftart und Menü brauchen nicht aktiviert zu werden. Film einbetten sollte aktiviert sein, damit der Film in die Toolbook–Datei eingebunden wird. Mit diesen Einstellungen wird der Film abgespielt, wenn die Seite angezeigt wird. Am Ende des Filmes bleibt der Film auf dem letzten Bild stehen. Miriam Hofmann Bernd Frick Seite - 21 - Projektarbeit Sleeping Barber Die Programmteile C-Code Zuerst wurden der Barber- und Customer-Prozesses als Windows-Programme mit jeweils eigenem Fenster unter Borlands C++ Builder implementiert, um den Code vor dem Einbau in Toolbook zu testen und zu erproben. Abbildung 11: Ein alter Friseur Um eine Bedienung mit der Maus zu ermöglichen, während die Barber- und Customer-Prozesse aktiv sind, wurde die eigentliche Funktionalität in beiden Prozessen als Thread ausgeführt. Dies bleibt auch nach deren Anbindung an Toolbook, obwohl hierzu eigentlich keine Notwendigkeit mehr besteht. Im nächsten Schritt machten wir uns mit der Toolbook-Umgebung vertraut und testeten den Aufruf von Funktionen einer Laufzeitbibliothek durch Toolbook und umgekehrt das Auslösen von Toolbookfunktionalität von ausserhalb. Schließlich waren die Barber- und Customer-Prozesse sind aus Toolbook heraus start- und terminierbar. Im letzten Schritt ersetzten wir die Ausgaben der Borland-Programme durch Toolbook-Animationen, die von den Prozesse durch das Aussenden von WindowsBotschaften aufgerufen werden. Miriam Hofmann Bernd Frick Seite - 22 - Projektarbeit Sleeping Barber Die Programmteile Behandlung von Windows Ressourcen Windows stellt die im Projekt verwendeten Systemressourcen binäre Semaphore, zählend Semaphore und das Shared Memory auf ähnliche Weise zur Verfügung: HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // pointer to // attributes BOOL bInitialOwner, // flag for initial ownership LPCTSTR lpName // pointer to mutex-object name ); HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, security // pointer to security // attributes LONG lInitialCount, // initial count LONG lMaximumCount, // maximum count LPCTSTR lpName // pointer to semaphore-object name ); HANDLE CreateFileMapping( HANDLE hFile, // handle to file to map LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security // attributes DWORD flProtect, // protection for mapping object DWORD dwMaximumSizeHigh, // high-order 32 bits of object size DWORD dwMaximumSizeLow, // low-order 32 bits of object size LPCTSTR lpName // name of file-mapping object ); Durch den Aufruf von CreateMutex() bzw. CreateSemaphore() erzeugt man ein Semaphorobjekt und erhält ein Handle darauf. Beim Aufruf von CreateSemaphore() wird außerdem der Wertebereich der zählenden Semaphore und deren Startwert festgelegt. Der jeweils letzte Parameter gibt der Semaphore einen Namen. CreateFileMapping() verlangt als ersten Parameter eigentlich einen Handle auf eine physikalisch vorhandenen Datei. Alternativ kann hier mit dem Parameter (HANDLE)0xFFFFFFFF ein Pagingfile angegeben sein, dessen Größe dann durch den fünften Parameter bestimmt sein muss. Mit dem letzten Parameter wird das Objekt benamst. Auch hier ist es eine einfache Zeichenkette, über die das Shared Memory systemweit von allen Prozessen angesprochen werden kann. Vor dem Zugriff auf die Ressourcen müssen sich die Prozesse durch Aufruf der Funktion OpenSemaphore() einen Handle generieren und diesen nach der Manipulation der Ressource durch CloseHandle(HANDLE) wieder freigeben. Wie das im Einzelnen geschieht, sollen die konkreten Vorgänge zeigen. Miriam Hofmann Bernd Frick Seite - 23 - Projektarbeit Sleeping Barber Die Programmteile Barber Der Barber-Prozess fordert als erstes die benötigten Systemressourcen beim Betriebssystem an. TSharedMemory *Msg;// = new TSharedMemory; hCustomer = CreateSemaphore(NULL, 0, 5, "SemCustomer"); hBarber = CreateSemaphore(NULL, 0, 1, "SemBarber"); Der zweite Parameter bei der Erzeugung des Mutex-Objektes bedeutet, dass Barber den Mutex mit der Erzeugung gleich besitzt. hMutex = CreateMutex(NULL, TRUE, "Mutex"); hWaiting = ::CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,PAGE_READWRITE, 0, sizeof(TSharedMemory), "MemWait"); Die Grösse des FileMapping-Objekts ergibt sich aus folgender Struktur: struct TSharedMemory { int Zaehler; char Zeichen[128]; }; Schließlich öffnet Barber das FileMapping-Objekt für einen schreibenden Zugriff und initialisiert dessen Zähler: Msg = (TSharedMemory*)::MapViewOfFile(hWaiting, FILE_MAP_WRITE, 0, sizeof(TSharedMemory)); Msg->Zaehler = 0; 0, Der Zugriff auf das Shared-Memory wird beendet ::UnmapViewOfFile(Msg); und der Mutex wieder freigegeben: ReleaseMutex(hMutex); Semaphore werden unter Windows durch den Aufruf von ReleaseMutex(HANDLE) bzw. ReleaseSemaphore(HANDLE) wieder freigegeben. Barber muss an dieser Stelle die Handles auf die generierten Ressourcen ausnahmsweise offen halten. Später wird er das nicht mehr tun, denn Handles sind nach Benutzung gleich wieder zu schliessen. Allerdings registriert Windows die Anzahl der offenen Handles und entfernt eine Ressource automatisch, sobald kein Prozess mehr darauf zugreift. Würde Barber seine Handles hier schon wieder freigeben, würden auch die neuangelegten Ressourcen wieder aufgegeben. Miriam Hofmann Bernd Frick Seite - 24 - Projektarbeit Sleeping Barber Die Programmteile Barber erzeugt dann ein neues Thread-Objekt und ruft es auf. Die weiteren Aktionen übernimmt der Thread, doch bleibt sich der Ablauf gleich wie bei einem Prozess ohne Threads: BarbThread = new TBarbThread(1); BarbThread->Resume(); Die meisten Systemressourcen werden in Windows mit der Funktion WaitForSingleObject(HANDLE, time) angefordert, wobei das ‚Object’ ein Semaphor- oder Mutex-Objekt, aber auch ein Prozesses oder Thread oder ein Timer-Objekt sein kann. Parameter dieser Funktion ist immer ein Handle auf das Objekte und eine eventuelle Wartezeit. Zuerst lief Barber als eigenständiges Windows-Programm. Ein Thread führte die ‚Barber’-Schleife aus, der hiermit vom Hauptprogramm beendet werden konnte: while(!Terminated) { Barber blockiert sich an der Customer-Semaphore: if(WaitForSingleObject(BarbForm->hCustomer, 100) == WAIT_OBJECT_0) { Wenn ein Kunde da ist, schickt Barber Nachrichten an Toolbook (dies später ausführlich): SendTBMessage(WacheAuf); SendTBMessage(BHoleMutex); Barber verschafft sich wieder ein Handle auf das Mutex-Objekt: hMutex = OpenMutex(MUTEX_ALL_ACCESS|SYNCHRONIZE, 0, "Mutex"); if(hMutex != NULL) { und blockiert bis er den Mutex hat: if((WaitForSingleObject(hMutex, INFINITE))== WAIT_OBJECT_0) { TSharedMemory *Msg; Ein Handle auf das SharedMemory: hWaiting = ::OpenFileMapping(FILE_MAP_WRITE, 0, "MemWait"); if (hWaiting) { Öffnen des SharedMemory und Erniedrigen des Zählers ‚Waiting’: Msg = (TSharedMemory*)::MapViewOfFile(hWaiting,FILE_MAP_WRITE, 0, 0, sizeof(TSharedMemory)); Msg->Zaehler --; SendTBMessage(BWaiting); Miriam Hofmann Bernd Frick Seite - 25 - Projektarbeit Sleeping Barber Die Programmteile Schließen des SharedMemory, Handle freigeben und Mutex freigeben: ::UnmapViewOfFile(Msg); ::CloseHandle(hWaiting); ReleaseMutex(hMutex); } } } SendTBMessage(BGebeMutex); Schließlich die Barber-Semaphore erhöhen und frisieren: ReleaseSemaphore(BarbForm->hBarber, 1, NULL); SendTBMessage(ErhoeheBarber); SendTBMessage(Schneide); SendTBMessage(Schlafe); } } } Abgesehen von den Messages an Toolbook entspricht dies genau dem Pseudocode in Tanenbaums Buch. Genauso einfach sind die Dinge beim Customer-Prozess. Miriam Hofmann Bernd Frick Seite - 26 - Projektarbeit Sleeping Barber Die Programmteile Customer Aus Gründen der Handhabbarkeit erhielt auch der Customer-Prozess einen Thread. Die Grundfunktionalität ändert sich dadurch aber nicht. Customer prüft als erstes die Anzahl der bereits wartenden Prozesse. Hierzu braucht er den Mutex auf das Shared Memory. Diesen kann er einfach über den von Barber vergebenen Namen ansprechen: Handle au Mutex herstellen: hMutex = OpenMutex(MUTEX_ALL_ACCESS|SYNCHRONIZE, 0, "Mutex"); if(hMutex != NULL) { Auf Mutex warten: if((WaitForSingleObject(hMutex, INFINITE))== WAIT_OBJECT_0) { TSharedMemory *Msg; SharedMemory zum Schreiben öffnen: hWaiting = ::OpenFileMapping(FILE_MAP_WRITE, 0, "MemWait"); if (hWaiting) { Msg = (TSharedMemory*)::MapViewOfFile(hWaiting,FILE_MAP_WRITE, 0, 0, sizeof(TSharedMemory)); Zähler prüfen, gegebenenfalls erhöhen: if(Msg->Zaehler < 5) { Msg->Zaehler++; SendTBMessage(CWaiting); ::UnmapViewOfFile(Msg); ::CloseHandle(hWaiting); ReleaseMutex(hMutex); SendTBMessage(CGebeMutex); Thread erzeugen: aCustThread = new CustThread(1); } Oder terminieren: else { ::UnmapViewOfFile(Msg); ::CloseHandle(hWaiting); ReleaseMutex(hMutex); SendTBMessage(CCancle); Application->Terminate(); } }//hWaiting }//waitfor } Miriam Hofmann Bernd Frick Seite - 27 - Projektarbeit Sleeping Barber Die Programmteile Für den Fall, dass Barber noch nicht gestartet ist, war das folgende implementiert. Für den Start aus Toolbook heraus wird dies nicht mehr benötigt: else { MessageDlg("No Barber", mtError, TMsgDlgButtons() << mbOK, 0); MessageDlg("No Way", mtError, TMsgDlgButtons() << mbOK, 0); Application->Terminate(); } }//if mutex Der Thread des Customer führt folgenden Code aus: void __fastcall CustThread::Execute() { SendTBMessage(ErhoeheCustomer); Handle auf eigene zählende Semaphore herstellen: hCustomer = OpenSemaphore(SEMAPHORE_MODIFY_STATE, false, "SemCustomer"); Diese erhöhen und Handle darauf wieder schließen: ReleaseSemaphore(hCustomer, 1, NULL); CloseHandle(hCustomer); Handle auf Barber-Semaphore generieren: hBarber = OpenSemaphore(SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, false, "SemBarber"); if(NULL != hBarber) { SendTBMessage(Warte); An Barber-Semaphore terminieren: blockieren und auf Haarschnitt warten, schließlich if((WaitForSingleObject(hBarber, INFINITE))== WAIT_OBJECT_0) { CloseHandle(hBarber); SendTBMessage(Haarschnitt); SendTBMessage(Gehe); Terminate(); } } } Die SendTBMessage()-Funktionen sind im Abschnitt „Kommunikation“ eingehend erläutert. Miriam Hofmann Bernd Frick Seite - 28 - Projektarbeit Sleeping Barber Die Programmteile DLL Beide Programme sollten zum einen aus Toolbook heraus gestartet werden können und zum anderen deren Aktionen in Toolbook sichtbar sein. Open Script kann hierzu einerseits die Funktionen einer DLL benutze, andererseits kann Toolbook über Windows-Nachrichten von Prozessen angesprochen werden. Diese benötigen hierzu den Fenster-Handle von Toolbook. Die DLL sollte also folgendes leisten: • • • Anlage eines Shared Memory, um das Handle des Toolbook-Fensters abspeichern zu können Funktionen in das Shared Memory zu schreiben und daraus lesen zu können Funktionen um die einzelnen Prozesse zu starten und zu beenden Jeder aufrufende Prozess erhält bei Einbinden der DLL ein Handle auf das SharedMemory „dllmemfilemap“ und die Berechtigung zu lesen und zu schreiben. Meldet sich ein Prozess ab, so werden dessen Ressourcen wieder freigegeben. BOOL DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved) { HANDLE hMapObject = NULL; // handle to file mapping BOOL fInit; switch (fdwReason) { case DLL_PROCESS_ATTACH: hMapObject = CreateFileMapping( (HANDLE) 0xFFFFFFFF, // use paging file NULL, // no security attributes PAGE_READWRITE, // read/write access 0, // size: high 32-bits SHMEMSIZE, // size: low 32-bits "dllmemfilemap"); // name of map object if(hMapObject == NULL) return FALSE; fInit = (GetLastError() != ERROR_ALREADY_EXISTS); lpvMem = MapViewOfFile(hMapObject, // object to map view of FILE_MAP_WRITE, // read/write access 0, // high offset: map from 0, // low offset: beginning 0); // default: map entire file if(lpvMem == NULL) return FALSE; if (fInit) memset(lpvMem, '\0', SHMEMSIZE); break; case DLL_PROCESS_DETACH: UnmapViewOfFile(lpvMem); CloseHandle(hMapObject); break; default: break; } return TRUE; } Miriam Hofmann Bernd Frick Seite - 29 - Projektarbeit Sleeping Barber Die Programmteile Beim Öffnen der Seite mit der Petrinetz-Animation schreibt Toolbook seinen Windows-Handle in das Shared Memory. Barber und Customer lesen es aus sobald sie gestartet sind und haben damit einen Adressaten für ihre Messages. Hierfür werden die folgenden Lese- und Schreibmethoden verwendet: VOID SetSharedMem(LPTSTR lpszBuf) { LPTSTR lpszTmp; // Get the address of the shared memory block. lpszTmp = (LPTSTR) lpvMem; // Copy the null-terminated string into shared memory. while (*lpszBuf) *lpszTmp++ = *lpszBuf++; *lpszTmp = '\0'; } VOID GetSharedMem(LPTSTR lpszBuf, DWORD cchSize) { LPTSTR lpszTmp; // Get the address of the shared memory block. lpszTmp = (LPTSTR) lpvMem; // Copy from shared memory into the caller's buffer. while (*lpszTmp && --cchSize) *lpszBuf++ = *lpszTmp++; *lpszBuf = '\0'; } Für das Starten der Prozesse benutzt die Dll die API Funktion CreateProcess(): LPCTSTR szMyApp = "Barber.exe"; STARTUPINFO StartupInfo; ZeroMemory(&StartupInfo, sizeof(STARTUPINFO)); StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.dwFlags = STARTF_USESHOWWINDOW; StartupInfo.lpReserved = NULL; StartupInfo.wShowWindow = SW_HIDE; if(CreateProcess(szMyApp, NULL, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInfoBarb[iBarbCounter])) { iBarbCounter++; } Diese Funktion benötigt als Parameter im wesentlichen den Namen einer ausführbaren Datei und Zeiger auf verschiedene Datenstrukturen. Das in StartupInfo abgelegte SW_HIDE, um die Anzeige des Programmfensters zu unterdrücken, blieb übrigens mit den verwendeten Borland-Programmen wirkungslos. Miriam Hofmann Bernd Frick Seite - 30 - Projektarbeit Sleeping Barber Die Programmteile Laut Dokumentation ist der zweite Aufrufparameter von CreateProcess() ein String mit optionalen weiteren Kommandozeilenparametern. Der Versuch, die Prozesse über diesen zweiten Parameter mit verschiedenen Kommandozeilen zu starten, blieb vergebens. Erst das Folgende funktionierte: CreateProcess(NULL, "Barber.exe woutMutex", NULL, NULL, TRUE, NORMAL_ PRIORITY_CLASS, NULL, NULL, &StartupInfo, &ProcessInfoBarb[iBarbCounter]) Von Customer und Barber können mit CreateProcess() mehrere Prozesse angelegt werden. Ihre Anzahl wird intern gezählt, um sie einzeln beenden zu können und ihre Ressourcen wieder freizugeben: bool KillBarber() { int iEC; iBarbCounter--; TerminateProcess(ProcessInfoBarb[iBarbCounter].hProcess, iEC); CloseHandle(ProcessInfoBarb[iBarbCounter].hProcess); CloseHandle(ProcessInfoBarb[iBarbCounter].hThread); } TerminateProcess() ist an dieser Stelle sehr fragwürdig, denn der Prozess selbst hat keine Zeit, sich z.B. bei einer DLL abzumelden. Hierzu müsste er ExitProcess() ausführen, doch das müsste er selbst tun. Hierzu müsste man ihm wohl eine Nachricht schicken. Die Funktion SendTBMessage() der DLL, die Barber und Customer für ihre Nachrichten an Toolbook nutzen, wird im Abschnitt Toolbook näher betrachtet. Funktionen einer DLL müssen im Deklarationsteil folgendermaßen deklariert sein: extern "C" __export int SendTBMessage(UINT uiMsgNr); Beim aufrufenden Prozess lautet die Entsprechung: extern "C" __declspec(dllimport) int SendTBMessage(UINT MsgNr); Bei der Kompilierung einer DLL wird eine *.lib Datei erzeugt, aus der die zugreifenden Prozesse die Einsprungspunkte der Funktionen lesen. Diese Datei muss bei der Kompilierung der einzelnen Prozesse jeweils mit eingebunden sein. Miriam Hofmann Bernd Frick Seite - 31 - Projektarbeit Sleeping Barber Die Programmteile OpenScript-Code Kommunikation Toolbook->Dll Die Programmiersprache von Toolbook kann dynamisch Laufzeitbibliotheken einbinden, deren Funktionen aus OpenScript heraus nutzen und hierüber auch mit anderen Programmen interagieren. Verschiedene DLLs werden mit Toolbook schon mitgeliefert und bieten zum Beispiel API-Funktionen. Die OpenScript Dokumentation befasst sich in einem eigenen Kapitel mit DLLs und beschreibt, wie diese zu benutzen sind: -- Bibliothek laden LinkDLL(„MyLib.dll“) -- Funktion deklarieren INT Testfunktion() -- Bibliothek entladen end -- Funktion benutzen a = Testfunktion() Leider funktioniert es so nicht. Der richtige Befehl lautet linkDll32() und auch ist dem Funktionsnamen sowohl in der Deklaration als auch im Aufruf ein Unterstrich voranzusetzen. Das sieht dann beim Starten des Barbers zum Beispiel so aus: to handle buttonClick if Caption of button "BtnCreateBarb" = "Starte Friseur" linkDLL32 "SleepingDll.dll" INT _CreateBarber() INT _KillBarber() end as = _CreateBarber() enabled of button "BtnCreatecust" = true Enabled of button "BtnStopCust" = false Enabled of button "BtnCreateMulCust" = true Enabled of button "BtnStopAll" = true Caption of button "BtnCreateBarb" = "Stoppe Friseur" else as = _Killbarber() enabled of button "BtnCreatecust" = false Caption of button "BtnCreateBarb" = "Starte Friseur" Enabled of button "BtnStopCust" = false Enabled of button "BtnCreateMulCust" = false Enabled of button "BtnStopAll" = false end if end Toolbook kommt mit nur wenigen DLL Befehlen aus: Es soll neben dem Speichern seines Fenster-Handles die Prozesse nur starten und beenden können. Miriam Hofmann Bernd Frick Seite - 32 - Projektarbeit Sleeping Barber Die Programmteile Kommunikation Prozesse->Toolbook Laut OpenScript –Dokumentation meldet Toolbook bei Start zwei spezielle WindowsBotschaften an, mit der es von anderen Prozessen angesprochen werden kann: TBM_EXECUTE um eine Funktion auszuführen, und TBM_EVALUATE, um einen Parameter auszuwerten. Nachdem diese Botschaften in der aufrufenden Funktion registriert sind: WORD wExecute = RegisterWindowMessage("TBM_EXECUTE"); WORD wEvaluate = RegisterWindowMessage("TBM_EVALUATE"); werden sie verwendet, wie andere Windows Botschaften auch. SendMessage(hwndMain,wExecute,TRUE,(LONG)(LPSTR)Command); } Lange Versuche, Toolbook mit diesen Botschaften irgendetwas mitzuteilen, blieben leider vergebens: Toolbook stürzte durch das Senden einer TBM_EXECUTE-Botschaft aus einer Testfunktion regelmäßig ab. Windows Botschaften Mit SendMessage() ist es in Windows aber auch möglich, beliebige selbstdefinierte Botschaften zu versenden. Windows stellt hierfür einen Bereich seiner MessageNummern zur Verfügung. Diese sind ab der Botschaft WM_USER(= 0x400) hochzuzählen. Den verwendeten Nummern wurden in der Datei Konstanten.h sprechende Namen gegeben. Das ist in Toolbook leider nicht möglich. Damit Toolbook auf diese Botschaften reagieren kann, ist es notwendig, einen Handler für das Toolbook-Event Idle zu schreiben. Hier ist das ein einfacher Dispatcher, der die empfangenen User-Messages auf die verschiedenen OpenScript-Funktionen verteilt: to handle idle translateWindowMessage on 0x700 send WacheAuf on 0x710 send BHoleMutex on 0x720 send BWaiting on 0x730 send BGebeMutex on 0x740 send ErhoeheBarber on 0x750 send Schneide ... .. . Wesentlich ist hier die Verwendung von SendMessage(). SendMessage() wartet mit seiner Rückkehr auf die Beendigung des ausgelösten Message-Handlers. So können durch die zeitliche Dauer der Animationen die Prozesse auf ein beobachtbares Maß verlangsamt werden, etwas, das bei den Borland-Testprogrammen durch die Verwendung von sleep()-Funktionen erzwungen werden musste. Miriam Hofmann Bernd Frick Seite - 33 - Projektarbeit Sleeping Barber Die Programmteile Barber und Customer nutzen die Funktion SendTBMessage(UINT) aus der DLL, um Toolbook ihre Botschaften mitzuteilen. int SendTBMessage(UINT uiMsgNr) { if(iCustCounter < 1) { char lpszBuf[30]; int zahl; LPTSTR pmem = lpszBuf; DWORD cchSize = sizeof lpszBuf; GetSharedMem(lpszBuf, cchSize); zahl = atoi(lpszBuf); hToolbook = (HWND)zahl; } SendMessage(hToolbook, uiMsgNr, 0, 0); return uiMsgNr; } Bei Customer sieht das dann zum Beispiel so aus: if(NULL != hBarber) { SendTBMessage(Warte); if((WaitForSingleObject(hBarber, INFINITE))== WAIT_OBJECT_0) { CloseHandle(hBarber); SendTBMessage(Haarschnitt); SendTBMessage(Gehe); Terminate(); } } Diese Messages sind die eigentlichen Transitionen unseres Petrinetzes. Ihre Gestaltung beschreibt das nächste Kapitel. Miriam Hofmann Bernd Frick Seite - 34 - Projektarbeit Sleeping Barber Die Programmteile Animation Jede der Botschaften von Barber und Customer löst eine Animation auf der Toolbook-Seite aus. Die Message Handler beschreiben also im Wesentlichen nur, was sich auf der Oberfläche der Seite bewegen soll. Folgende Funktion beschreibt beispielsweise wie die Barber-Marke auf die freie Stelle wandert und diese aktiviert erscheint: to handle BGebeMutex visible of ellipse "MarkeMu" = true get Ellimove(ellipse "MarkeMu", arc "Arcmuvonba1", q3r, 1) get Ellimove(ellipse "MarkeMu", arc "Arcmuvonba", q4r, 1) get TransMoveout(ellipse "MarkeBa", button "BtnBWaiting", 2) get shineon(ellipse "StWait", KR) end Die Message-Handler benutzen Grundfunktionen, die einzelne Bewegungen oder Aktionen definieren. Beispielhaft hier die Bewegung entlang einer elliptischen Linie, deren Parameter die Ellipse, die zu bewegende Marke, die Bewegungsrichtung und ein Geschwindigkeitsfaktor sind. Die Berechnung des Weges ergibt sich aus der speziellen Ellipsengleichung: to get Ellimove Marke, Kreis, Richtung, Fakt get setspeed() speed = it speed = speed * Fakt i = 0 a =(Width of kreis)/2 qa =((Width of kreis)/2)^2 b =(height of kreis)/2 hm = (height of Marke)/2 wm = (width of Marke)/2 lk = Left of Kreis tk = Top of Kreis rk = Left of Kreis + Width bk = Top of Kreis + Height conditions when Richtung = Q1r while i <= a Move Marke to lk + a i = i + speed end while when Richtung = Q1l i = a while i >= 0 Move Marke to lk + a i = i - speed end while when Richtung = Q2L ... .. . of Kreis of Kreis + i - wm, tk + b - sqrt(1 - i*i/qa) * b - hm + i - wm, tk + b - sqrt(1 - i*i/qa) * b - hm Miriam Hofmann Bernd Frick Seite - 35 - Projektarbeit Sleeping Barber Die Programmteile Ferner gibt es Funktionen, um Stellen oder Transitionen zu aktivieren und zu deaktivieren. Für den Mehrmarkenplatz und die Anzeige der wartenden Customer sind eigene Zähler implementiert. Schließlich gibt es eine Rücksetzfunktion, die alle Bildschirmelemente in einen definierten Ausgangszustand bringt. Miriam Hofmann Bernd Frick Seite - 36 - Projektarbeit Sleeping Barber Aufgetretene Probleme Aufgetretene Probleme Solange Toolbook seine Skripten abarbeitet, ist Windows nicht bzw. nur mit extremer Verzögerung ansprechbar. Auch unter Windows NT ist von Prozesswechseln nichts mehr zu bemerken. Toolbook belegt die CPU laut Task Manager fast zu 100%. Das liegt vermutlich daran, dass Teile der Toolbook Umgebung noch als 16-Bit Programme programmiert sind und von Windows nur exklusiv ausgeführt werden. Dies ist auch in der letzten Version 8.5 noch so. Abbildung 12: Toolbook fasst zu Solche Prozesse lassen sich „von Hand“ durch den Aufruf von PeekMessage() unterbrechen. Das Betriebssystem arbeitet dann auch die Message-Queues anderer anstehender Prozesse ab. Versuchsweise wurde eine Funktion implementiert, die dies tut und bei der Abarbeitung der Skripten immer wieder aufgerufen wird: void Peeky() { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } Dadurch reagiert das System etwas schneller auf Benutzereingaben während der Abarbeitung der Skripts, doch kommt dadurch auch die Reihenfolge der Abarbeitung der Botschaften im animierten Petrinetz ziemlich durcheinander. Beim Starten vieler Customer-Prozesse wird sichtbar, dass die Darstellung nicht ganz angemessen ist: Dargestellt werden die Inhalte der Nachrichten in der Reihenfolge ihres Einganges und nicht die Vorgänge selbst in. Das führt zeitweise zu einem chaotischen Herumspringen der Marken. Verbesserung brächte hier eventuell die Darstellung jedes einzelnen Customer-Prozesses, doch reicht dazu der Platz nicht. Wünschenswert wäre, OpenScript-Kommandos von aßen direkt absetzen zu können. Die Dokumentation von OpenScript entspricht nicht dem Stand der 32Bit Programmierung. linkDll32() ist darin nicht erwähnt, auch nicht ein eventuelles Name-Mangling beim Linken der DLL. Miriam Hofmann Bernd Frick Seite - 37 - Projektarbeit Sleeping Barber Aufgetretene Probleme Die Verwendung der „speziellen“ Toolbook-Nachrichten TBM_EVALUATE und TBM_EXECUTE ist im Handbuch nur unzureichend dokumentiert. Auch lange Recherche bei den einschlägigen Newsgroups und die Benutzung von dort gefundenem Beispielcode löste nicht das Problem eines abstürzenden Toolbook beim Empfang solcher Botschaften. Die Syntaxprüfung des OpenScript-Editors funktioniert nur rudimentär: Nicht einmal falsch geschriebenen Schlüsselwörter werden beanstandet. Die Dokumentation der Windows-API ist stellenweise falsch: Mit dem Parameter SW_HIDE lässt sich ein Borland-Programmfenster nicht verstecken. Will man mit CreateProcess() einem Programm Aufrufparameter übergeben, so muss der erste Parameter des Aufrufs leer bleiben und Programmname und Aufrufparameter im zweiten Parameter übergeben werden. Miriam Hofmann Bernd Frick Seite - 38 - Projektarbeit Sleeping Barber Aufgetretene Probleme Resümee Scheiß Toolbook! Vor allem gegen Ende der Projektarbeit, als es darum ging die verschiedenen Elemente zu einem „Book“ zusammenzufügen, zeigte Toolbook genau das, was schlecht programmierte Software ausmacht: Aus unerfindlichen Gründen stürzte es ständig ab und riss dabei immer das Gesamtsystem(Windows 2000) mit in die Tiefe. Anscheinend soll laut Asymetrix mit dem Service Pack 3 von Microsoft dieses Problem behoben sein. Der sogenannte Packager war minutenlang beschäftigt, und dabei nicht in der Lage sein Fenster zu aktualisieren. Die erstellten Installationen hatten entweder keinen Ton oder es funktionierten die Animationen nicht. Unter 98 erstellte Installationen laufen nicht unter XP. Dies ist mit der letzten Version (8.5) keineswegs besser. Diese besteht nach wie vor zu Hauptteilen aus 16-Bit Modulen. Für die nächste Version 9.0 verspricht Asymetrix eine vollständige Portierung auf 32Bit. Miriam Hofmann Bernd Frick Seite - 39 - Projektarbeit Sleeping Barber Bedienungsanleitung Bedienungsanleitung Anforderungen: Bildschirmauflösung: 1048 x 768 Farbeinstellung: 32-Bit Sound Windows XP Installationshinweis: 1. Legen Sie die CD-Rom in Ihr Laufwerk und starten sie die Setup.exe mit einem Doppelklick. Folgen Sie den Anweisungen der Installationsprogramms. 2. Die Lern-CD-Rom sollte sich nun nach erfolgreicher Installation über das Startmenü starten lassen. Bedienung Die Bedienung der Software erfolgt entweder über Maus oder Tastatur. Mit der Enter-Taste können Sie sequenziell die einzelnen Kapitel anschauen. Mit der Maus haben Sie die Möglichkeit die Kapitel einzeln über die Bedienungsleiste unten in der Mitte auszuwählen oder auch sequentiell über die Pfeiltasten anzuschauen. Schaltfläche Beschreibung/ Kapitel Eine Seite zurück Intro Beschreibung des Friseurproblems Aufstellen eines Systemmodells Animiertes Petrinetz Pseudocode Quellcode Extro Eine Seite weiter Tabelle 1 Beschreibung der Buttons Miriam Hofmann Bernd Frick Seite - 40 - Projektarbeit Sleeping Barber Abbildung 13: Bedienungsleiste Anmerkungen zu einigen Kapiteln: • Das Intro wird frühzeitig beendet indem Sie einfach auf eine andere Seite gehen. • Die Animationen im Systemmodellkapitel werden durch einen Klick auf die Start-Buttons gestartet. • Im Petrinetzkapitel haben Sie die Möglichkeit ein Petrinetz in Aktion zu sehen. Zuerst muß der Friseur gestartet werden, danach können bis zu sieben Kunden gestartet werden, diese können sie einzeln oder durch einen Klick auf die Schaltfläche „Starte 7 Kunden „ mehrfach starten. Sie können die Seite mit einem Klick auf „Seite zurücksetzen“ in den Anfangszustand zurücksetzen. Sollte Ihnen die Geschwindigkeit zu langsam oder zu schnell sein, können Sie diese Ihren Wünschen entsprechend den Radio-Buttons anpassen, dies sollten Sie vor dem Start der einzelnen Prozesse tun. Vor dem Verlassen der Seite sollten Sie alle Prozesse stoppen mit einem Klick auf „Stoppe Alle“. Beendet wird die Software über einen Mausklick auf das Kreuz oben rechts in der Caption Bar. Miriam Hofmann Bernd Frick Seite - 41 - Projektarbeit Sleeping Barber Nachtrag Nachtrag Zum Abgabetermin hatten wir noch zwei ungelöste Probleme: • Die Animationen des animierten Petrinetzes funktionierten nur auf Rechnern, auf denen bereits Toolbook installiert war • Während die Animationen liefen, waren die Rechner völlig blockiert. Animation Die Zeichenobjekte schienen ihre Eigenschaften „Left“, „Top“, „Width“ usw. verloren zu haben. Nach Art der Umstände war bald klar, dass eine Unterstützungsdatei fehlen musste. Diese durch Probieren zu ermitteln, gaben wir bald auf. Wir posteten an eine entsprechend Newsgroup und mailten der Supportabteilung von Click2Learn das folgende: Hello everybody, as a student projekt we made a Toolbook book with ToolBook Instructor 7.1 dealing the "Sleeping Barber" problem as described in A.Tanenbaum's book. Among pages with text there is a page with an animated Petri net, visualizing the states of the semaphores and the processes, controlled by a real barber process and several customer processes using Windows messages. We used object properties like "left", "top" and "width" to move the tokens through the Petri net. All works fine in author mode and also as a runtime made with the AutoPackager, but when we tested on a computer without ToolBook Instructor installed, the moving functions failed. The objects, though present and e.g. changeable in their colour, seemed to have lost their 'numerical' properties. Test functions returned NOTHING from the "width" of a button or the "top" of it. We wonder, what files are needed to make our ToolBook book work correct. Thanks, Vom Support erhielten wir die folgende Antwort: Left, Top and Width are not standard controllable using OpenScript...such as: ToolBook object properties left of button "foo" = 50 Normally if you want to move the object you would say: item 1 of position of button "foo" = 50 which would simulate the same as what LEFT would have done. When the Actions Editor support was added to ToolBook (version 7.1) a few new functions were added (left, top and width to name a few) to support the Actions Editor programming environment. These functions act just like properties, which is why you can get away with saying: Miriam Hofmann Bernd Frick Seite - 42 - Projektarbeit Sleeping Barber Nachtrag left of <obj> = <val> However since this LEFT function is really a supporting function of the Actions Editor you will need to ensure that you have the TB70ACTR.SBK system book bound to your .TBK file (use the File | Bound System Books menu option) in order to freely utilize the Top, Left and Width functions as you have. It works on your Authoring machine only because the TB70ACTR.SBK automatically loaded by the Authoring engine for Authoring purposes. is If this does not resolve your problem, please let me know. Denny Dedmore Click2Learn, Inc, Technical Support Ein Mitglied der Newsgroup mailte: Dear Bernd, There are Action Editor properties like 'left', 'top', and 'width', but they don't natively exist in OpenScript. You can create those properties with code like: to get top RETURN item 2 of position of target end Could this be related to your problem? Key Lawson Und schließlich, nachdem wir ihm die Antwort der Supportabteilung weitergeleitet hatten: You're welcome, Bernd. Glad to help. And thank you for sending Denny Dedmore's note. Whenever he or Tim Barham speaks, I listen. They are terrific. There are a bunch of those little OpenScript routines that can be quite handy. Here are some that I use frequently: to to to to to to to to get get get get get get get get xPos; yPos; width; height; lfEdge; top; rtEdge; bottom; to to to to to to to to set set set set set set set set xPos yPos width height lfEdge top rtEdge bottom RETURN RETURN RETURN RETURN RETURN RETURN RETURN RETURN to to to to to to to to INT INT INT INT INT INT INT INT pU;item pU;item pU;item pU;item pU;item pU;item pU;item pU;item item item item item item item item item 1 2 1 2 1 2 3 4 of of of of of of of of 1 2 1 2 1 2 3 4 of of of of of of of of position position size size bounds bounds bounds bounds position position size size bounds bounds bounds bounds Miriam Hofmann of of of of of of of of of of of of of of of of target; target; target; target; target; target; target; target; target target target target target target target target = = = = = = = = pU; pU; pU; pU; pU; pU; pU; pU; end end end end end end end end end end end end end end end end Bernd Frick Seite - 43 - Projektarbeit Sleeping Barber Nachtrag Once these routines are in a book script or sysBook, you can code: top of button "abc" = bottom of button "xyz" lfEdge of mainWindow = 150 increment width of selection by 15 ... anywhere you want. or or etc. They making coding life much easier. :-) Best, Key Das Systembuch TB70ACTR.SBK wurde dem Projekt hinzugefügt und in den Tests funktioniert nun auch die Animation. Miriam Hofmann Bernd Frick Seite - 44 - Projektarbeit Sleeping Barber Nachtrag Windows XP Wir fanden einen neuen Fehler: Auf einigen Windows XP-Installationen bricht die Ausführung schon gleich zu Beginn mit der Fehlermeldung einer allgemeinen Schutzverletzung (verursacht durch eine 16 Bit-Dll) ab. Auch hierzu einige Erkenntnisse aus der Newsgroup: You need to upgrade to a version above 8 then *most* of the problems with XP seem to be fixed (running as a non-admin user etc.) but there still seem tobe a few issues... Version 7.2 should work under XP but only when logged in as an administrator. "Marshall Newton" <[email protected]> wrote in message news:[email protected]... > Can toolbook 7.2 runtime work at all on the XP platform as I am having >all sorts of problems. > > > Thanks > > Marshall > > Schließlich versuchten wir unser Glück noch mit den Laufzeitbibliotheken einer Trial Version 8.5. Das Ergebnis des Versuches, das Buch zu Starten sah dann unter Windows XP so aus: Abbildung 14: - - - Miriam Hofmann Bernd Frick Seite - 45 - Projektarbeit Sleeping Barber Nachtrag Blockade Das Problem des blockierten Rechners hat wohl auch seine Ursache in der überholten Systemarchitektur des Entwicklungssystems: Nach Meinung eines Windows-Experten bei IXXAT laufen die blockierenden 16-Bit Prozesse sehr wohl als eigener Task und müssten „gesheduled“ werden wie die 32Bit Prozesse auch. Allerdings müssen beim Datenaustausch mit 32-Bit Modulen die Daten ständig in den 16-Bit Adressraum dieser Prozesse umgesetzt werden. Dies sei zeitaufwändig, umständlich (Mutexe seien im Spiel) und von Microsoft kaum dokumentiert. Hier könnten auch Prozesse beteiligt sein, die in der Liste des Task-Managers nicht auftauchen. Noch in diesem Jahr soll angeblich die Version 9 von Toolbook auf den Markt kommen, die dann durchgängig 32-bittig sein soll. Vielleicht löst ja ein Upgrade mit dieser Version unsere verbliebenen Probleme. Miriam Hofmann Bernd Frick Seite - 46 - Projektarbeit Sleeping Barber Anhang Anhang AutoPackager Das Setup-Tool des Instructors ist völlig unbrauchbar und wir verwendeten ein anderes(http://www.jrsoftware.org/isinfo.php) . In der ganzen Zeit hatten wir mit dem AutoPackager/InstallShield damit nur eine einzige funktionsfähige Setupdatei hinbekommen. Unter Version 7.1 kam regelmäßig dies, Abbildung 15: Setupfehler mit Version 8.5 dann auch mal das: Abbildung 16: Setupfehler Miriam Hofmann Bernd Frick Seite - 47 - Projektarbeit Sleeping Barber Anhang Dateinamen hätten sich also auf 8.3 Notation zu beschränken: Query Title: Fatal file copy error (-1) during install when setup deployed in zip archive Product: ToolBook Updated: 2001-07-26 Article: Q101571559428575 Category: Instructor/Assistant Answer PROBLEM ------A fatal file copy error (-1) can occur while installing an autopackaged project if the setup was transferred as a self- extracting zip archive. Older versions of WinZip did not support long filenames. Some versions did support long filenames, but not in the self-extracting zip archive on Windows NT 4.0. This will not happen with a newer version of WinZip. Self-extracting files created with WinZip Self-Extractor 2.1 and later have full long file name support. RESOLUTION ---------A. Update to a newer version of WinZip: http://www.winzip.com B. Do not use long filenames, use the 8.3 format (maximum 8 characters, plus 3 character file extension). Related articles: - Setup has encountered a fatal file copy error (-1) - when installing... http://kbsearch.click2learn.com/kbsearch/showart.html?article=4544 Miriam Hofmann Bernd Frick Seite - 48 -