Proactor-Entwurfsmuster (Proactor Pattern)
Proactor-Entwurfsmuster (Proactor Pattern)
Das Proactor-Entwurfsmuster ist ein Verhaltensmuster für asynchrone Systeme. Es dient der effizienten Verarbeitung von I/O-Operationen, die vom Betriebssystem asynchron ausgeführt werden – im Gegensatz zum Reactor-Entwurfsmuster, das auf synchronen, nicht-blockierenden I/O basiert.
Grundidee
Beim Proactor-Muster startet die Anwendung eine asynchrone Operation (z. B. Lesen oder Schreiben auf einem Socket) und übergibt eine Completion Handler-Funktion. Sobald die Operation abgeschlossen ist, meldet das Betriebssystem (oder eine I/O-Bibliothek) das Ergebnis zurück, und der Proactor ruft den entsprechenden Handler auf.
Damit verschiebt sich die Verantwortung:
- Der Reactor reagiert auf **Ereignisse** („es gibt Daten“)
- Der Proactor reagiert auf **Fertigstellungen** („die Daten wurden gelesen“)
Struktur
| Komponente | Aufgabe |
|---|---|
| Asynchronous Operation Processor | Führt die I/O-Operationen im Hintergrund aus (z. B. Betriebssystem) |
| Proactor | Empfängt Fertigstellungsbenachrichtigungen und ruft den passenden Completion Handler auf |
| Completion Handler | Wird nach Abschluss einer Operation aufgerufen, um das Ergebnis zu verarbeiten |
| Asynchronous Operation | Repräsentiert eine gestartete I/O-Operation (z. B. async_read) |
| Initiator | Startet asynchrone Operationen und registriert die Completion Handler |
Ablaufdiagramm
+-----------------------+
| Initiator |
+-----------+-----------+
|
v
[Start async I/O]
|
v
+-----------------------+
| Asynchronous Processor|
| (z. B. OS, IOCP) |
+-----------+-----------+
|
v
[Operation abgeschlossen]
|
v
+-----------------------+
| Proactor |
| ruft CompletionHandler|
+-----------+-----------+
|
v
+-----------------------+
| Completion Handler |
+-----------------------+
Beispiel (Pseudo-C++)
Ein vereinfachtes Beispiel für asynchrone Leseoperationen:
// Pseudocode für asynchrone Dateioperationen
void onReadComplete(const char* data, size_t bytesRead) {
std::cout << "Daten empfangen: " << std::string(data, bytesRead) << std::endl;
}
void startAsyncRead(int fd) {
AsyncRead(fd, buffer, sizeof(buffer), onReadComplete);
}
int main() {
int fd = open("data.txt", O_RDONLY);
startAsyncRead(fd);
// Event loop wartet auf asynchrone Fertigstellungen
Proactor::run();
}
Hier ruft das Programm nicht selbst read() auf, sondern startet eine asynchrone Operation.
Sobald das Betriebssystem die Operation beendet hat, wird onReadComplete() automatisch aufgerufen.
Unterschiede zum Reactor-Muster
| Merkmal | Reactor | Proactor |
|---|---|---|
| Ereignisart | Reagiert auf Ereignisse (z. B. "Socket ist lesbar") | Reagiert auf abgeschlossene Operationen ("Lesen beendet") |
| I/O-Typ | Nicht-blockierendes, synchrones I/O | Echte asynchrone I/O (durch OS) |
| Steuerung | Anwendung fragt aktiv nach Ereignissen | Betriebssystem benachrichtigt nach Abschluss |
| Beispielsysteme | select(), epoll(), poll() |
Windows I/O Completion Ports (IOCP), POSIX AIO |
Vorteile
- Hohe Effizienz bei asynchronem I/O
- Weniger Blockierung und Kontextwechsel
- Gute Skalierbarkeit bei vielen parallelen Operationen
Nachteile
- Komplexer zu implementieren
- Betriebssystemabhängig (unter Linux eingeschränkt, unter Windows durch IOCP gut unterstützt)
- Schwerer zu debuggen
Beispielhafte Verwendung
- Hochperformante Netzwerkserver (z. B. Webserver, Game-Server)
- Asynchrone Dateiverarbeitung
- Frameworks wie:
* Boost.Asio (C++) – abstrahiert Reactor und Proactor * Windows IOCP (C/C++) * .NET Async/Await (C#)
Vergleich: Reactor vs. Proactor
Reactor: "Es gibt etwas zu tun" → Anwendung reagiert
Proactor: "Es wurde etwas getan" → Anwendung wird benachrichtigt
Siehe auch
- Reactor-Entwurfsmuster
- Asynchrone Ein-/Ausgabe
- Event-Driven Architecture
- Boost.Asio
- IOCP (Windows)
- Observer-Entwurfsmuster
Quellen
- Douglas C. Schmidt: *Proactor: An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Asynchronous Events*
- POSA2 – *Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects*
- Wikipedia: Proactor Pattern
- Boost.Asio Dokumentation