Difference between revisions of "Main Loop Hooks/fr"

From Lazarus wiki
Jump to navigationJump to search
Line 5: Line 5:
 
Vous devez attendre un événement (sur le socket[http://www.dicofr.com/cgi-bin/n.pl/dicofr/definition/20010101004807] ou pipe ou ...) qui arrive, mais vous voulez faire cela dans le processus principal (GUI) et vous ne voulez pas bloquer le GUI et aussi vous ne voulez pas faire du multi-threading. La solution à ce problème est la possibilité d'ajouter des "handles" [http://www.dicofr.com/cgi-bin/n.pl/dicofr/definition/20010101002342] supplémentaires pour être observés dans la boucle d'événement principale.
 
Vous devez attendre un événement (sur le socket[http://www.dicofr.com/cgi-bin/n.pl/dicofr/definition/20010101004807] ou pipe ou ...) qui arrive, mais vous voulez faire cela dans le processus principal (GUI) et vous ne voulez pas bloquer le GUI et aussi vous ne voulez pas faire du multi-threading. La solution à ce problème est la possibilité d'ajouter des "handles" [http://www.dicofr.com/cgi-bin/n.pl/dicofr/definition/20010101002342] supplémentaires pour être observés dans la boucle d'événement principale.
  
== Solution details ==
+
== Les détails de la Solution ==
  
In unit [[doc:lcl/lclintf|LCLIntf]] two functions have been added to provide for this functionality, they are:
+
Dans l'unité [[doc:lcl/lclintf|LCLIntf]] deux fonctions ont été ajoutées typour tenir compte de cette fonctionnalité, ils sont :
  
 
  AddEventHandler(AHandle: THandle; AFlags: dword;  
 
  AddEventHandler(AHandle: THandle; AFlags: dword;  
Line 14: Line 14:
 
  SetEventHandlerFlags(AHandler: PEventHandler; NewFlags: dword);
 
  SetEventHandlerFlags(AHandler: PEventHandler; NewFlags: dword);
  
The [[doc:lcl/interfacebase/twaithandleevent.html | TWaitHandleEvent]] type is declared in unit InterfaceBase as:
+
Le [[doc:lcl/interfacebase/twaithandleevent.html | TWaitHandleEvent]] est déclaré dans l'unité InterfaceBase comme :
  
 
   TWaitHandleEvent = procedure(AData: PtrInt; AFlags: dword) of object;
 
   TWaitHandleEvent = procedure(AData: PtrInt; AFlags: dword) of object;

Revision as of 13:43, 8 June 2007

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

Enoncé du problème

Vous devez attendre un événement (sur le socket[1] ou pipe ou ...) qui arrive, mais vous voulez faire cela dans le processus principal (GUI) et vous ne voulez pas bloquer le GUI et aussi vous ne voulez pas faire du multi-threading. La solution à ce problème est la possibilité d'ajouter des "handles" [2] supplémentaires pour être observés dans la boucle d'événement principale.

Les détails de la Solution

Dans l'unité LCLIntf deux fonctions ont été ajoutées typour tenir compte de cette fonctionnalité, ils sont :

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

Le TWaitHandleEvent est déclaré dans l'unité InterfaceBase comme :

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

AddEventHandler adds a handle to be watched to the main event loop. When the handle is "signalled", then the procedure specified in ACallback will be called with as a parameter the AData that was passed when registering the event handler, and any Flags, which are OS specific. The flags passed to AddEventHandler can be modified using SetEventHandlerFlags. The returned handler (a pointer) by AddEventHandler should be passed to RemoveEventHandler to stop watching the associated handle.

RemoveEventHandler stops watching the specified handle. RemoveEventHandler will set AHandler to nil before returning. Its argument is a pointer returned by AddEventHandler.

Windows

The AFlags parameter in AddEventHandler is unused, and the AFlags in TWaitHandleEvent will be 0, in the current implementation.

Win32 supports the following handle types, basically the things supported by MsgWaitForMultipleObjects:

  • change notifications (for files and directories)
  • console input
  • events: signalled with SetEvent winapi function
  • mutexes: signalled when it is not owned anymore
  • processes: signalled when they terminate
  • semaphore: signalled when it's count is greater than zero
  • threads: signalled when they terminate
  • timers: signalled when expired, see SetWaitableTimer

Gtk/Unix

The AFlags parameter in AddEventHandler specifies the condition in which the handle should be signalled, with the possible values being the ones documented in the GIOCondition type in the glib reference.

In the callback, the AFlags will contain the condition, of the above referenced GIOCondition type, that was satisfied.

Gtk/unix supports the following handle types:

  • files
  • sockets
  • pipes

Note that win32 does not support sockets or pipes (at least, their use is "discouraged" by MSDN). Suggestion: use WSAEventSelect to create an event associated with a socket and pass the event handle.

Pipes and Process Termination

To provide a cross-platform solution for pipes (not well supported on win32) and processes (not well supported on gtk/unix) additional functions have been added:

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);

When a process terminates the event handler specified will be called. AInfo will contain the exit code if AReason is cerExit, or (on unix only) the termination signal if AReason is cerSignal. For gtk/unix, use the PID to watch as AHandle. Internally, a signal handler is installed to catch the SIGCHLD signal. On win32, AddEventHandler is used to watch process termination.

To watch a pipe for incoming data, pass the file descriptor (unix) or the pipe read-end handle to AddPipeEventHandler with a custom chosen event handler method as AEventHandler. On gtk/unix, AddEventHandler is called to watch the file descriptor for traffic. On win32, the message loop will timeout every 100 msecs to check all watched pipes for available data; if data is available, the event handler is called.