\chapter{Tycoon}
\label{Tycoon}
%\comment{Dieser Abschnitt ist noch in Bearbeitung}
%Tycoon~\cite{Matt93} ist eine persistente Umgebung mit folgenden
%  Eigenschaften...
Im Rahmen der vorliegenden Arbeit werden Synchronisationsmechanismen
für langlebige, mobile Aktivitäten in persistenten Objektsystemen
untersucht. Diese Arbeit wird im Rahmen des am Arbeitsbereich DBIS der
Universität Hamburg laufenden Tycoon-Projekts durchgeführt. Das in
diesem Projekt entwickelte Tycoon-System bildet dabei die
technologische und implementatorische Basis dieser Arbeit.  Im
Tycoon-Projekt wird eine Verbesserung der Qualität persistenter
Objektsysteme angestrebt. Dieses Ziel wird erreicht durch die:
\begin{quote}
  ``spezielle sprachliche und architekturelle Unterstützung für die
  vollständig transparente Verwaltung langlebiger Daten- und
  Programmobjekte, die mengen\-orien\-tierte Verarbeitung
  (benutzerdefinierter) Kollektionen, die Implementierung generischer
  Bibliotheken und die typsichere Anbindung externer Systemsoftware
  (z.B.\ SQL Datenbanken oder Fenstersysteme)''~\cite{Matt93}.
\end{quote}
%\begin{figure}
%\begin{center}\leavevmode
%  \epsfxsize=0.5\textwidth \epsfbox{pictures/tycintop.ps}
%\end{center}
%\caption{Anbindung externer Dienste [Matthes et al. 95b]}
%\label{tycintop}
%\end{figure}


Im diesem Kapitel werden der Aufbau und die Eigenschaften der für
diese Arbeit relevanten Teile des Tycoon-Systems beschrieben.  Eine
Übersicht über die Organisation der funktionalen Schichten des
Tycoon-Systems wird in Abschnitt~\ref{Aufbau} gegeben. Daran
anschließend folgt eine Beschreibung der persistenten, polymorphen
Programmiersprache des Systems (Abschnitt~\ref{TL}). Als ein Ergebnis
dieser Arbeit werden für das Tycoon-System eine Reihe von Modulen zur
Thread-Synchronisation implementiert. Der Aufbau des zugrundeliegenden
Modulsystems wird in Abschnitt~\ref{Module} angesprochen.  Eine
weitere zentrale Systemkomponente bilden das Speicherprotokoll
TSP\footnote{Tycoon Store Protocol.} und die über dieses Protokoll
angesprochenen Objektspeicher (Abschnitt~\ref{STORE}).  Im letzten
Abschnitt dieses Kapitels folgt eine Darstellung der durch das
Tycoon-System gegebenen Möglichkeiten zur Formulierung langlebiger
Aktivitäten (Abschnitt~\ref{Aktivitaeten}).


Spezielle, weitere Eigenschaften des Tycoon-Systems werden im
nachfolgenden Kapitel intensiver behandelt. Eine ausführliche
Diskussion des Tycoon-Laufzeitsystems erfolgt in
Abschnitt~\ref{RUNTIME}, eine  Erläuterung der Übertragung
von TL-Objekten auf andere Systeme findet sich in
Kapitel~\ref{Migration}.


\section{Der Aufbau des Tycoon-Systems}
\label{Aufbau}
Der Aufbau des Tycoon-Systems gliedert sich in mehrere spezialisierte
Schichten.  Die in Abbildung~\ref{tycoon} sichtbaren, aufeinander
aufbauenden Schichten des Tycoon-Systems bestehen dabei aus den
Komponenten:
\begin{figure}
\begin{center}\leavevmode
  \epsfxsize=0.6\textwidth \epsfbox{pictures/TycoonSchicht.ps}
\end{center}
\caption{Schematischer Aufbau des Tycoon-Systems}
\label{tycoon}
\end{figure}
\begin{description}
\item[TL (Tycoon Language):] Die Programmiersprache TL stellt die
  Schnittstelle des Systems zu den Programmierern  dar. In
  dieser Sprache sind alle Bibliotheken und Anwendungen des
  Tycoon-Systems formuliert. Das Compiler-Front-End des Systems
  wandelt Ausdrücke der Sprache TL in eine Zwischenrepräsentation um.
  Diese besteht aus  mit Typinformationen versehenen,
  abstrakten Syntaxbäumen.  Diese Zwischenrepräsentation wird an das
  Compiler-Back-End weitergereicht.
\item[TML (Tycoon Machine Language):] TML ist die vom
  Compiler-Back-End erzeugte, ma\-schi\-nen\-un\-ab\-hängige
  Zwischenrepräsentation~\cite{GaMa94}.  Auf dieser untypisierten
  Zwischensprache können verschiedene maschinenunabhängige
  Optimierungen durchgeführt werden. Die Ausgabe des Compiler-Back-End
  besteht aus vom Tycoon-Byte\-code\-in\-ter\-pre\-ter~(TVM) direkt
  ausführbaren Code, dessen Befehlssatz an den der
  Transputer-Mikroprozessoren angelehnt ist~\cite{INMO87}.
\item[TVM (Tycoon Virtual Machine):] Der vom Compiler-Back-End
  erzeugte Bytecode wird von der TVM direkt ausgeführt. Die TVM
  bedient sich zur Ausführung des Bytecodes der Dienste des
  Tycoon-Laufzeitsystems, das vom Betriebssystem unabhängige
  Funktionalität zur Verfügung stellt (vgl.\ Abschnitt~\ref{RUNTIME}).
\item[TSP (Tycoon Store Protocol):] Die gesamte Kommunikation der TVM
  und des Laufzeitsystems mit dem Objektspeicher findet über das
  Speicherprotokoll TSP statt. Alle in der Programmiersprache TL
  erzeugten Daten, wie atomare Werte, Programmcode und Threads, werden
  in einem Objektspeicher persistent abgelegt. Der Objektspeicher
  dient weiterhin zur persistenten Speicherung verschiedener
  Datenstrukturen des Tycoon-Laufzeitsystems. Das Protokoll TSP
  gestattet die Anbindung verschiedener Objektspeicher über eine
  einheitliche Softwareschnittstelle.
\end{description}
Ein Ziel bei der Konzeption des Tycoon-Systems ist die
Austauschbarkeit der beschriebenen, verschiedenen Komponenten. So
existieren Konfigurationen des Systems, in denen verschiedene
Compilerkomponenten und TSP-Implementationen benutzt werden.



\section{Die Programmiersprache TL}
\label{TL}
Die Sprache TL~\cite{MaSc92a} ist eine polymorphe, funktionale
Programmiersprache mit Funktionen höherer Ordnung und wird im
Tycoon-System zur Entwicklung von Anwendungsprogrammen sowie zur
Datenmodellierung benutzt. Weiterhin wird diese Sprache als
Systemprogrammiersprache eingesetzt; der weitaus größte Teil des
Tycoon-Systems ist in TL programmiert. In diesem Abschnitt wird eine
kurze Einführung in die für diese Arbeit wesentlichen Elemente der
Programmiersprache TL gegeben. Für eine vollständige Beschreibung,
insbesondere zu den Gebieten Polymorphie und Subtypbeziehungen, wird
auf~\cite{Matt93} verwiesen.

\subparagraph{Auswertungsreihenfolge und Wertkonvertierung:} Für
Ausdrücke gilt in TL eine strikte Auswertungsreihenfolge: Ausdrücke
werden von ``links nach rechts'' bearbeitet. Diese Reihenfolge gilt
auch für alle arithmetischen Ausdrücke; Vorrangregeln wie in anderen
Programmiersprachen existieren nicht. Die Auswertung des ersten
Ausdrucks des folgenden Beispiels\footnote{Durch $\Rightarrow$ werden
  in den Beispielen die Ausgaben des Tycoon-Systems gekennzeichnet.}
ergibt den Wert $14$ und nicht, wie in Sprachen mit arithmetischen
Vorrangregeln, den Wert $11$. Die Auswertung eines Ausdrucks kann
durch Klammerung geändert werden.
\begin{xple}
$3+4*2$   
$\Rightarrow$ $14$ :Int
$3 + \{4*2\}$
$\Rightarrow$ $11$ :Int
\end{xple}

Eine automatische Wertekonvertierung und eine Überladung von
Bezeichnern, wie sie zum Beispiel in den Programmiersprachen  C++
und Ada möglich ist~\cite{ElSt90,I*83}, wird von TL nicht zur
Verfügung gestellt. Beispielsweise existiert keine automatische
Typkonvertierung von ganzzahligen Werte in Fließkommawerte.

\subparagraph{Werte- und Typbindungen:} TL verfügt über die folgenden
vordefinierten Datentypen: Bool, Integer, Real, Char und String.
Weitere Datentypen können mit Mitteln der Programmiersprache definiert
werden. Beispiele für Werte der genannten Basistypen sind:
\begin{xple}
\begin{tabular}{ll}
true false & (* Die beiden möglichen Werte des Typs Bool *) \\
4712  & (* Ein ganzzahliger Wert des Typs Int *) \\
2.71828 & (* Eine Fließkommazahl des Typs Real *) \\
``Große Worte, kleine Wirkung'' & (* Eine Zeichenkette des Typs String *) \\
\end{tabular}
\end{xple}
In der Programmiersprache TL sind statische, veränderliche und
dynamische Wertbindungen möglich. Eine statische Bindung wird zum
Beispiel durch den Ausdruck
\begin{xple}
\k{let} $x = 3.14$
\end{xple}
definiert. Nach der Auswertung dieses Ausdrucks ist der Bezeichner $x$
statisch an den Wert $3.14$ gebunden. 

Eine veränderliche Bindung einer Variable an einen Wert kann durch
einen Ausdruck der folgenden Form erreicht werden:
\begin{xple}
\k{let} \k{var} $x = 10.5$
\end{xple}
Der Wert der Variablen $x$ kann dann  durch eine Zuweisung
geändert werden:
\begin{xple}
$x := 3.33$
\end{xple}

Die Sichtbarkeit einer TL-Variablen kann durch die Schlüsselworte
\k{begin} und \k{end} eingeschränkt werden. Im folgenden Beispiel wird
zunächst der Wert $815$ an den Bezeichner $a$ gebunden. Innerhalb
des gekennzeichneten Blocks wird eine neue, lokale Bindung an den
Bezeichner $a$ vorgenommen. Die vorgenommene Bindung verschattet die
vorangegangene Bindung. Nach Verlassen des Blocks sind die lokalen
Bindungen an $a$ und $b$ nicht mehr sichtbar. Der Wert der Variablen
$c$ entspricht nach der Bindung dem Wert der globalen Bindung von $a$:
\begin{xple}
\k{let} $a = 815$
\k{begin}
  \k{let} $a = 3$
  \k{let} $b = 7$
\k{end}
\k{let} $c = a$    (* Der Bezeichner $c$ wird an den Wert 815 gebunden *)
\end{xple}

Jedes Tycoon-Objekt ist von einem bestimmten, unveränderlichen Typ.
Der Typ einer Variablen kann bei Bindung an einen Wert durch den
Compiler abgeleitet  oder als Zusicherung direkt angegeben
werden:
\begin{xple}
\k{let} s = ``Ein String''
\k{let} s :String = ``Ein String''
\end{xple}
Im ersten Beispiel wird der Typ der Variablen $a$ durch den
angegebenen Wert vom Compiler abgeleitet. Hier ist jeder Wert jeden
Typs zulässig.  Im zweiten Beispiel wird die Angabe eines Werts, der
nicht vom Typ {\em String} ist, einen Typfehler hervorrufen, da der
gewünschte Typ der Variablen $a$ durch die Typangabe {\em :String}
zugesichert wurde.

Die dynamische Bindung einer Variablen an einen Wert wird in TL durch
die Parameter von Funktionen dargestellt. Funktionsdefinitionen werden
durch das vorangestellte Schlüsselwort \k{fun} eingeleitet:
\begin{xple}
\k{let} inc = \k{fun}(n :Int) :Int \k{begin} $n + 1$ \k{end} (* Funktionsdefinition *)
inc(1)  (* Funktionsaufruf *)
$\Rightarrow$ $2$ :Int
\end{xple}
Durch den Aufruf einer Funktion werden die aktuellen Parameter
dynamisch an die formalen Parameter der Funktion gebunden. Im Rumpf
einer Funktion kann auf alle Variablen des globalen
Sichtbarkeitsbereichs, lokale Variablen der Funktion sowie die aktuellen
Werte der Formalparameter zugegriffen werden. Die Angabe des Typs
eines Funktionsparameters ist immer notwendig, während der Typ des
Ergebniswerts wiederum vom Compiler abgeleitet werden kann. Eine
verkürzte Schreibweise für obige Funktionsdefinition ist:
\begin{xple}
\k{let} inc(n :Int) =  $n + 1$
\end{xple}

Typbindungen werden in TL durch Voranstellung des Schlüsselwortes
\k{Let} angegeben. Im folgenden Beispiel werden die Typen {\em T} und
{\em Person} definiert sowie  Werte an Bezeichner dieser Typen
gebunden:
\begin{xple}
\k{Let} T = \k{Tuple} x :Real \k{end}             (* Typbindung *)
\k{let} t :T = \k{tuple} \k{let} $x = 3.14$ \k{end}   (* Wertbindung *)

\k{Let} Person = \k{Tuple}        (* Typbindung *)
   name :String
   age :Int
\k{end}
\k{let} p :Person = \k{tuple}      (* Wertbindung *)
  \k{let} name = ``Meier''
  \k{let} age = $44$
\k{end}
\end{xple}
Durch die im vorangegangenen Beispiel benutzten Schlüsselwörter
\k{Tuple} und \k{tuple} werden jeweils geordnete Mengen von
Bindungen formuliert. 
%Die Angabe von nicht geordneten Mengen ist durch
%die Schlüsselwörter \k{Record} für Typbindungen sowie \k{record} für
%Wertbindungen möglich.


\subparagraph{Polymorphismus:} In TL werden Subtyppolymorphismus sowie
parametrischer Polymorphismus unterstützt.  Für die genaue
Beschreibung von Typbeziehungen und Typisierungsregeln in TL sei hier
auf~\cite{Matt93} verwiesen. An dieser Stelle sollen lediglich einige
Beispiele dieser Arten von Polymorphismus folgen.

Die Angabe einer Signatur der Form {\em x :T1} stellt eine
partielle Typspezifikation dar, die besagt, daß {\em x} mindestens
{\em T1} erfüllt. Ein an den Bezeichner {\em x} gebundener Wert kann
aber auch eine genauere Spezifikation {\em T2} erfüllen. Eine
partielle Ordnung auf Typen wird in TL durch die Notation {\em
  T2~$<:$~T1} beschrieben. Diese  besagt, daß der Typ {\em T2}
eine präzisere Spezifikation des Typs {\em T1} darstellt. Der Typ {\em
  T1} wird auch als Supertyp des Typs {\em T2}, der Typ {\em T2} als
Subtyp des Typs {\em T1} bezeichnet. Der Supertyp aller
nichtparametrisierten Typen  in TL ist der Typ \k{Ok}.

Die folgenden Typen {\em Person} und {\em Student} stehen durch ihre
Struktur in der Subtypbeziehung {\em Student~$<:$~Person}. Die
Funktion {\em getAge} ist eine polymorphe Funktion, die als Argumente
Werte des Typs {\em Person} sowie aller Subtypen des Typs Person, also
beispielsweise Werte des Typs {\em Student}, akzeptiert.
\begin{xple}
\k{Let} Person = \k{Tuple}
   age :Int
   name :String
\k{end}
\k{Let} Student = \k{Tuple}
   age :Int
   name :String
   semestercount :Int
\k{end}

\k{let} getAge(P $<:$Person  p :P) = p.age
\end{xple}

Weiterhin wird in TL die Parametrisierung von Typen unterstützt. Das
folgende Beispiel zeigt das Prinzip der Definition eines
parametrisierten Typs {\em Queue} sowie einer polymorphen Funktion
{\em newQueue}, die die Erzeugung beliebig parametrisierter Elemente
des Typs {\em Queue} gestattet:
\begin{xple}
\k{Let} Queue(R $<:$\k{Ok}) $<:$\k{Ok} = \k{Tuple} \ldots \k{end}
\k{let} newQueue(R$ <:$\k{Ok}) :Queue(R) = \k{begin} \ldots \k{end}

\k{let} intQueue = newQueue(:Int)
\k{let} personQueue = newQueue(:Person)
\end{xple}


\subparagraph{Funktionsparameter und Funktionen höherer Ordnung:}
Funktionsdefinitionen liefern in TL Werte erster Klasse. Dies bedeutet
unter anderem, daß Funktionen wie andere TL Werte gespeichert und als
Argumente weiterer Funktionen benutzt werden können:
\begin{xple}
\k{let} sort(T $<:$\k{Ok}  a :Array(T)  greaterEqual(x,y :T) :Bool) :\k{Ok} =
  \k{begin} \ldots \k{end}

\k{let} a = \k{array} $3 8 40 1 0 7$ \ldots \k{end}
\k{let} greaterEqual(x,y :Int) = x $>=$ y

sort(a greater)
\end{xple}
In diesem Beispiel erwartet die Funktion {\em sort} als Argument ein
indizierbares Feld (Array) mit Elementen eines beliebigen, aber
einheitlichen Typs sowie eine auf dem Typ der Feldelemente
definierte Vergleichsfunktion {\em greaterEqual}. In der Funktion
{\em sort} kann dadurch ein typunabhängiger Sortieralgorithmus
formuliert werden.

Das folgende Beispiel zeigt die Definition der polymorphen Funktion
{\em makeFun}, die eine weitere Funktion {\em f} als Argument erwartet
und als Ergebnis eine anonyme Funktion liefert, die {\em f} zweimal
auf ihr Argument anwendet:
\begin{xple}
\k{let} makeFun(T$<:$\k{Ok}  f(x :T):T)(x :T) = f(f(x))

\k{let} f1 = makeFun(\k{fun}(x :Int) x + 1)
\k{let} f2 = makeFun(\k{fun}(x :Real) real.mul(x x))
f1($3$);
$\Rightarrow$ $5$ :Int
f2($2.0$);
$\Rightarrow$ $16.0000$ :Real
\end{xple}
%Der Aufruf der erzeugten Funktion {\em f1} mit einem Argumentwert $3$ liefert
%dann als Ergebnis den Wert $5$. 

\subparagraph{Kontrollstrukturen:} Die Sprache TL bietet weiterhin für
Fallunterscheidung, Iteration, unbedingte und bedingte Wiederholungen
sowie zur Ausnahmebehandlung die folgenden Kontrollstrukturen an:
\begin{xple}
\begin{tabular}{ll}
\k{if} $x > 7$ \k{then} \ldots \k{else} \ldots \k{end} & (* Fallunterscheidung *) \\
\k{for} $i = 0$ \k{upto} $10$ \k{do} \ldots \k{end} & (* Iteration *) \\
\k{loop} \ldots \k{end} & (* Unbedingte Wiederholung *) \\
\k{while} $x < 1000$ \k{do} \ldots \k{end} & (* Bedingte Wiederholung *) \\
\end{tabular}
\end{xple}
\begin{xple}
\k{try}       (* Ausnahmebehandlung *) 
  \ldots     (* Auszuführender Block *)
\k{when} {\em Ausnahme} \k{then} 
  \ldots     (* Auszuführender Block für eine bestimmte Ausnahme *)
\k{else} 
  \ldots     (* Auszuführender Block für andere Ausnahmen *)
\k{end}
\end{xple}

\section{Module und Schnittstellen}
\label{Module}
Module dienen im Tycoon-System der Organisation wiederverwendbarer
Programmteile. Ein Modul wird durch seine Schnittstelle und einen
Implementationsteil beschrieben. In der Schnittstelle zu einem Modul
werden die Signaturen der vom Modul exportierten Typen und Werte
spezifiziert. Ein Beispiel für die Schnittstelle eines Moduls {\em
  mutex} ist die folgende Definition:
\begin{xple}
\k{interface} Mutex
\k{import} thread
\k{export}
  T $<:$ \k{Ok}
  new() :T
  lock(m :T) :\k{Ok}
  unlock(m :T) :\k{Ok}
  getLocks(t :thread.T(\k{Ok})) :Array(T)
\k{end};
\end{xple}
Eine Schnittstelle zu einem Modul wird durch das Schlüsselwort
\k{interface} eingeleitet. Bezeichner aus anderen Modulen, die in der
Schnittstellendefinition benötigt werden, können über eine Importliste
(\k{import}) importiert werden. Nach dem Schlüsselwort \k{export}
folgen die vom Modul exportierten Bezeichner. Diese  stehen
dann zur Verwendung in Programmen und anderen Modulen zur Verfügung.
Um die durch ein Modul exportierten Typen, Funktionen und Werte
außerhalb des Moduls nutzen zu können, ist die Voranstellung des
Modulbezeichners notwendig.  Zum Beispiel kann die Funktion {\em lock}
aus der obigen Schnittstellendefinition durch {\em mutex.lock}
aufgerufen werden, wenn der Implementationsteil des Moduls den Namen
{\em mutex} hat.

Die  Kodierung der in einer Schnittstellendefinition
festgelegten Objekte erfolgt in der Modulimplementation:
\begin{xple}
\k{module} mutex
\k{import} thread
\k{export}
\k{Let} T = \k{Tuple} \ldots \k{end}
\k{let}  new() :T = \ldots
\k{let}  lock(m :T) :\k{Ok} = \dots
\k{let}  unlock(m :T) :\k{Ok} = \ldots
\k{let}  getLocks(t :thread.T(\k{Ok})) :Array(T) = \ldots
\k{end};
\end{xple}
Wiederum werden durch \k{import} und \k{export} die Import- und
Exportlisten der Modul\-implementation festgelegt. Die
Implementationsmodule enthalten mindestens die in einer entsprechenden
Schnittstellendefinition aufgeführten Komponenten.

Modul\-schnitt\-stellen werden im Tycoon-System durch Tupel-Typen
repräsentiert und bilden wie Funktionen und andere Typen Werte erster
Klasse.  Modulschnittstellen können daher wie alle anderen Typen des
Tycoon-Systems manipuliert werden. Werte eines solchen Tupel-Typen
werden durch den Import eines zugehörigen Implementationsmoduls
gebildet.

Im Gegensatz zu anderen Programmiersprachen, die über ein Modulsystem
verfügen, können im Tycoon-System zu einer Schnittstelle mehrere
Implementationsmodule vorhanden sein. Die konkret benutzte
Implementation zu einer Modulschnittstelle wird im Tycoon-System über
Bibliotheksdefinitionen spezifiziert. In einer solchen Spezifikation
werden Modulschnittstellen den Modulimplementationen zugeordnet:
\begin{xple}
\k{library} threadenv
\k{import}
  thread
\k{with}
  \k{interface}
    Mutex
  \k{module}
    mutex :Mutex
  \k{interface} 
    Rendezvous
  \k{module}
    rendezvous :Rendezvous
\k{end};
\end{xple}
In diesem Beispiel werden den Schnittstellen {\em Mutex} und {\em
  Rendezvous} die Implementationsmodule {\em mutex} und {\em
  rendezvous} zugeordnet. Der größte Teil der in einem Tycoon-System
vorhandenen Programme ist in  Modulen abgelegt. Module
verwandter Funktionalität werden  durch Bibliotheksdefinitionen
gruppiert. Beispielsweise stehen in der Bibliothek {\em bulkenv} eine
Reihe von Modulen zur Verarbeitung von Massendaten zur Verfügung. Die
in dieser Arbeit implementierten Funktionen zur Synchronisation werden
in der Bibliothek {\em threadenv} zusammengefaßt.

\section{Speicherprotokoll und persistenter Objektspeicher}
\label{STORE}
Alle mittels der Programmiersprache TL erzeugten Objekte und Bindungen
sind persistent. Diese Eigenschaft von TL-Objekten ist für Benutzer
des Systems transparent. Erreicht wird die Persistenz von TL-Objekten
durch eine automatische Speicherung der Objekte in einem
Objektspeicher, dessen Zustand auf einem nichtflüchtigen Medium
stabilisiert werden kann. Hierbei ist die Persistenz eines Objekts
durch die Erreichbarkeit dieses Objekts von dem bei der Erzeugung
eines Objektspeichers angelegten Wurzelobjekts definiert (siehe unten).
 
Die Kommunikation des Tycoon-Systems mit einem Objektspeicher wird über
das Speicherprotokoll TSP abgewickelt, das ein, im Sinne des
Typsystems der Programmiersprache TL, untypisiertes Speicherprotokoll
auf einer Abstraktionsebene unterhalb von TL-Objekten
darstellt~\cite{MMS95a}.  TL-Objekte werden auf der Ebene des TSP als
atomare oder zusammengesetzte Werte der Basistypen des TSP verwaltet.

Im einzelnen stellt das TSP dem Tycoon-Laufzeitsystem die folgende
Funktionalität zur Verfügung:

\subparagraph{Uniformen Zugriff auf verschiedene Objektspeicher:} Für
unterschiedliche Objektspeicher ist jeweils eine Implementation des
TSP für den Objektspeicher, ein TSP-Adapter, zu entwickeln, der die
Funktionalität des TSP auf Funktionalität des Objektspeichers
abbildet. Jeder TSP-Adapter stellt seinen Klienten einen einheitlichen
Satz von TSP-Funk\-tions\-auf\-rufen zur Verfügung.  TSP-Adapter
existieren für eine Reihe verschiedener Objektspeicher:
\begin{description}
\item[Tymem:] Ein portabler Einbenutzer-Objektspeicher, der
  vollständig im Hauptspeicher des Systems gehalten wird. Die
  Persistenz des Objektspeichers wird durch die Standarddateidienste
  des zugrundeliegenden Betriebssystems erreicht.
\item[Tysin:] Ein portabler Einbenutzer-Objektspeicher. Dieser
  Objektspeicher hält nur einen geringen Teil der genutzten Daten im
  Hauptspeicher des Systems. 
\item[Tyobject:] Ein TSP-Adapter für den kommerziellen
  Mehrbenutzer-Objektspeicher ObjectStore~\cite{LLOW92}.
\end{description}

\subparagraph{Programmierschnittstelle:} Die Programmierschnittstelle
des TSP beinhaltet eine Reihe von Funktionsaufrufen:
\begin{itemize}
\item Erzeugung, Modifikation und Löschen von Objektspeichern.
\item  Erzeugung, Modifikation von Objektspeicherwerten.
\item Abfragefunktionen, die Auskunft über Eigenschaften des
  zugrundeliegenden Objektspeichers geben. Hierzu gehören
  beispielsweise Eigenschaften wie die Verfügbarkeit von
  2-Phase-Commits und Sperrmöglichkeiten für einzelne Speicherobjekte.
\item Stabilisierung des Objektspeichers. Hierbei werden alle
  durchgeführten Änderungen an Objekten auf einem nichtflüchtigen
  Medium dauerhaft abgelegt ({\em Commit}).
\item Wiederherstellung des Zustands der letzten Stabilisierung. Alle
  seit der letzten Objektspeicherstabilisierung durchgeführten
  Änderungen werden wieder rückgängig gemacht ({\em Rollback}).
\item Export und Import von TL-Objekten in einem vom Objektspeicher
  unabhängigen Format. Hierdurch ist ein Objektaustausch zwischen
  verschiedenen Objekt\-speicher\-implementationen gewährleistet.
\end{itemize}
Eine vollständige Beschreibung der TSP-Programmierschnittstelle findet
sich in~\cite{MMS95a}.

\subparagraph{Automatische Freispeicherverwaltung:} Objekte der
Sprache TL können durch Benutzerintervention nicht explizit zerstört
werden. Statt dessen wird bei Bedarf, also zum Beispiel bei
Speichermangel oder durch Steuerung seitens des Benutzers, durch den
Objektspeicher eine Speicherbereinigung (Garbage Collection)
durchgeführt. Hierbei werden alle nicht länger erreichbaren Objekte
wieder dem freien Objektspeicherbereich zugeordnet. Die Erreichbarkeit
eines Objekts ist hierbei wie folgt definiert:
\begin{enumerate}
\item Das Wurzelobjekt des Objektspeichers ist erreichbar. Dieses
  Objekt wird bei der Erzeugung eines Objektspeichers angelegt.
\item Alle durch eine vom Benutzer definierte Aufzählungsfunktion
  angegebenen Objekte sind erreichbar.\footnote{Hierunter fallen unter
    anderem Datenstrukturen des Laufzeitsystems, die durch
    TSP-Aufrufe erzeugt worden, aber nicht vom Wurzelobjekt erreichbar
    sind.}
\item Alle transitiv von dem Wurzelobjekt erreichbaren Objekte sind
  erreichbar.
\end{enumerate}

\subparagraph{Transaktionsverwaltung:} Der Zustand eines
Objektspeichers kann durch Aufruf von TSP-Funktionen auf einem
nichtflüchtigen Medium stabilisiert werden. Alle seit der letzten
Stabilisierung geänderten oder erzeugten TL-Objekte werden dabei
dauerhaft abgelegt. Eine Stabilisierung des Objektspeichers entspricht
dabei einer abgeschlossenen Transaktion. Mittels Funktionalität des
TSP kann eine solche Transaktion nicht rückgängig gemacht werden.
Während der weiteren Arbeit mit dem System ist jedoch der Zustand des
Objektspeichers, der bei der letzten Objektspeicherstabilisierung
vorlag, jederzeit wieder erreichbar. 

\subparagraph{Erweiterbarkeit:} Das TSP wird durch verschiedene
Erweiterungen ergänzt. Derartige Erweiterungen bedienen sich der
Funktionalität einer vorliegenden TSP-Implementation und stellen
wiederum eine TSP-konforme Programmierschnittstelle zur Verfügung.
Die Funktionalität des TSP kann daher durch ``Stapelung'' von
TSP-konformen, zusätzlichen Protokollschichten erweitert werden.
Beispielsweise existieren Erweiterungen des TSP, die eine Definition
von mehreren Sicherungspunkten ermöglichen, zu denen der
Objektspeicherzustand im Verlauf einer Sitzung zurückgesetzt werden
kann~\cite{Korn95}. Zusätzliche Erweiterungen wie Dienste zur
Zugriffskontrolle~\cite{RMS95} stehen ebenfalls zur Verfügung.

%1. the root object is reachable
%2. all objects enumerated by the user-defined enumerator are reachable
%3. if an array of format tsp_Format_VAL is reachable, then all objects
%   with object identifier values stored in the array slots
%   are reachable.

%besteht aus einer Softwareschnittstelle,
%Jeder Zugriff auf ein TL-Objekt erfolgt über das TSP.

% Store-Paper \cite{MMS95a} \comment{Transitive
%  Erreichbarkeit, Transaktionen, ...}

\section{Langlebige Aktivitäten}
\label{Aktivitaeten}
Langlebige Aktivitäten werden im Tycoon-System durch persistente
Threads realisiert. Tycoon-Threads sind Objekte ``erster Klasse'', sie
können gespeichert werden, auf Identität verglichen werden und als
Funktionsargumente und Rückgabewerte fungieren.

Tycoon-Threads werden durch Aufruf der Funktionen {\em new} und {\em
  fork} des Standardmoduls {\em thread} erzeugt.\footnote{Die
  vollständige Schnittstellendefinition des Moduls {\em thread}
  befindet sich in Anhang~\ref{Thread}.} Ein Tycoon-Thread führt,
nebenläufig zu weiteren Threads, eine Funktion aus, die bei der
Erzeugung des Threads angegeben wird. Das folgende Beispiel zeigt die
Definition einer Funktion {\em func} und die Erzeugung eines Threads
{\em t}, der die Funktion {\em func} ausführt:
\begin{xple}
\k{let} func(self :thread.T(Int)) :Int =
  \k{begin}
    \ldots
    thread.kill(self)
    \ldots
  \k{end}

\k{let} t = thread.fork(func)
\end{xple}
Eine Funktion, die als Thread ausgeführt werden soll, weist stets
einen Parameter {\em self} auf, dessen Typ entsprechend dem
Rückgabewert der Funktion parametrisiert werden muß. Der Parameter
{\em self} wird einer Funktion bei der Erzeugung eines Threads für
diese Funktion übergeben. Dadurch ist es möglich, daß ein Thread
Operationen auf sich selbst durchführt. Beispielsweise beendet sich
der Thread {\em t} im obigen Programmfragment durch Aufruf der
Funktion {\em kill}. 

Der Rückgabewert eines Threads ist der Rückgabewert der durch den
Thread ausgeführten Funktion. Der Typ {\em R} des Rückgabewerts ergibt
sich aus dem für den Parameter {\em self} angegebenen,
parametrisierten Typ {\em thread.T(R)}. Durch den folgenden Aufruf
kann der Rückgabewert des obigen Threads {\em t} abgerufen werden:
\begin{xple}
\k{let} result :Int = thread.join(t)
\end{xple}
Durch diesen Aufruf wird der aufrufende Thread bis zur Beendigung des
Threads {\em t} blockiert. Nach Beendigung des Threads {\em t} werden
dessen Rückgabewert an den Bezeichner {\em result} gebunden und die
Ausführung des aufrufenden Threads fortgesetzt.

Tycoon-Threads sind wie alle Objekte des Tycoon-Systems persistent. So
ist auch der Ausführungszustand eines Threads persistent.
Beispielsweise werden aktive Threads, also Threads, die sich in
Ausführung befinden,  nach einem Neustart des Systems
automatisch wieder aktiviert.

Eine besondere Eigenschaft des Tycoon-Systems ist die 
Migration von Tycoon-Objekten in entfernte Tycoon-Systeme
beziehungsweise Objektspeicher~\cite{BM96}.  Diese in
Abschnitt~\ref{Migration} genauer beschriebene Eigenschaft gilt auch
für Tycoon-Threads.  Diese können einen Objektspeicher
verlassen und ihre Tätigkeit in einem anderen Objektspeicher
fortsetzen. Die Abbildung~\ref{threadmigration} zeigt die Migration
eines Threads aus dem System {\em Angestellter} über die Systeme {\em
  Sekretärin} und {\em Gruppenleiter} in das System {\em Buchhaltung}.
In jedem der  Systeme werden durch den  Thread
gewisse Aufgaben erfüllt, bevor dieser Thread in ein weiteres System
migriert. 


%\comment{Persistenz, Mobilität, ...}
\begin{figure}
\begin{center}\leavevmode
  \epsfxsize=0.6\textwidth \epsfbox{pictures/hospesen.ps}
\end{center}
\caption{Threadmigration}
\label{threadmigration}
\end{figure}

%Thread-Paper~\cite{MMS95}.
%Abbildung~\ref{threadmigration}~\cite{BM96}.

%\section{Das Laufzeitsystem}


%Historischer Abriß, Übergang zu Threads, daher Bedarf für Synchronisation,
%wie aus folgendem Kapitel hervorgeht.


% Local Variables:
% TeX-master: "da"
% TeX-parse-self: t
% TeX-auto-save: t
% End:
