Main Loop Hooks/sk

From Free Pascal wiki

English (en) français (fr) 日本語 (ja) slovenčina (sk) 中文(中国大陆)‎ (zh_CN)

Prehľad problému

Potrebujete čakať kým nastane nejaká udalosť (v sokete alebo rúre ...), ale chcete to urobiť v základnom (GUI) vlákne a neblokovať GUI a tiež nechcete viacero vlákien? Riešenie tohoto problému je schopnosť pridať extra obsluhy, ktoré čakjú v hlavnej slučke udalostí.

Detaily riešenia

Pre poskytnutie tejto schopnosti boli do jednotky LCLIntf pridané dve funkcie:

AddEventHandler(AHandle: THandle; AFlags: dword; 
    AEventHandler: TWaitHandleEvent; AData: PtrInt): PEventHandler;
RemoveEventHandler(var AHandler: PEventHandler);
SetEventHandlerFlags(AHandler: PEventHandler; NewFlags: dword);

Typ TWaitHandleEvent je deklarovaný v jednotke InterfaceBase ako:

 TWaitHandleEvent = procedure(AData: PtrInt; AFlags: dword) of object;

AddEventHandler pridáva obsluhu čakajúcu v hlavnej slučke udalostí.

Keď je signalizovaná obsluha, potom je volaná procedúra zadaná v ACallback s parametrom AData, ktorý je poslaný pri registrovaní obsluhy udalosti, a príznakmi, ktoré sú špecifické pre OS. Príznaky, poslané do AddEventHandler, môžu byť upravené pomocou SetEventHandlerFlags. Handler (ukazovateľ) vrátený AddEventHandler musí byť poslaný do RemoveEventHandler pre zastavenie očakávania priradenej obsluhe.

RemoveEventHandler zastavuje očakávanie zadanej obluhy. RemoveEventHandler nastaví, pred ukončením, AHandler na nil. Jeho argumentom je ukazovateľ vrátený z AddEventHandler.

Windows

V aktuálnej implementácii nie je parameter AFlags v AddEventHandler použitý a AFlags v TWaitHandleEvent bude 0.

Win32 podporuje nasledujúce typy handle, v podstate veci podporované MsgWaitForMultipleObjects:

  • oznamovania zmeny (pre súbory a adresáre)
  • konzolový vstup
  • udalosti: signalizované WinAPI funkciou SetEvent
  • mutexy: signalizované keď ich nikto nevlastní
  • procesy: signalizované keď sú skončené
  • semfóry: signalizované keď je ich počet väčší ako nula
  • vlákna: signalizované keď sú skončené
  • časovače: signalizované keď vyprší, viz SetWaitableTimer

Gtk/Unix

Parameter AFlags v AddEventHandler udáva podmienky, za ktorých má byť signalizovaná obsluha, s možnýmy hodnotami dokuemntovanými v type GIOCondition v použití glib.

V spätnom volaní bude AFlags obsahovať podmienky vyššie odkazovaného typu GIOCondition, ktoré boli splnené.

Gtk/unix podporuje nasledujúce typy obsluhy:

  • súbory
  • sokety
  • rúry

Všimnite si, že Win32 nepodporuje sokety a rúry (prinajmenšom ich použitie je "odradzované" v MSDN). Návrh: použite WSAEventSelect na vytvorenie udalosti spojenej so soketom a pošlite obsluhu udalosti.

Rúry a ukončovanie procesu

Pre poskytnutie viac-platformného riešenia pre rúry (neveľmi podporované na Win32) a procesy (nie veľmi podporované na GTK/Unix) boli pridané ďalšie funkcie:

TChildExitReason = (cerExit, cerSignal);
TPipeReason = (prDataAvailable, prBroken, prCanWrite);
TPipeReasons = set of TPipeReason;

TChildExitEvent = procedure(AData: PtrInt; AReason: TChildExitReason; AInfo: dword) of object;
TPipeEvent = procedure(AData: PtrInt; AReasons: TPipeReasons) of object;
function  AddProcessEventHandler(AHandle: THandle; 
    AEventHandler: TChildExitEvent; AData: PtrInt): PProcessEventHandler;
procedure RemoveProcessEventHandler(var AHandler: PProcessEventHandler);

function  AddPipeEventHandler(AHandle: THandle; 
    AEventHandler: TPipeEvent; AData: PtrInt): PPipeEventHandler;
procedure RemovePipeEventHandler(var AHandler: PPipeEventHandler);

Keď proces končí, bude volaná zadaná obsluha udalosti. AInfo bude obsahovať ukončovací kód, ak AReason je cerExit, alebo (len Unix) ukončovací signál, ak AReason je cerSignal. Pre GTK/Unix, použite PID ako AHandle pre sledovanie. Interne, je nainštalovaný popisovač signálu pre pochopenie signálu SIGCHLD. Na Win32, je na čakanie ukončenia procesu použitý AddEventHandler.

Pre sledovanie rúry na prichádzajúce dáta, pošlite do AddPipeEventHandler popisovač súboru (unix) alebo handle konca čítania rúry, so zvolenou metódou obsluhy udalosti ako AEventHandler. Na GTK/Unix, je volaná AddEventHandler na čakanie prevádzky popisovača súboru. Na Win32, slučka správ vyprší každých 100 ms, na kontrolu všetkých čakaných rúr na dostupná dáta, ak sú dostupné dáta, je volaná obsluha udalosti.