Proactor-Entwurfsmuster (Proactor Pattern)

Aus dev.kaibel.net
Zur Navigation springen Zur Suche springen

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

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