Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-10

lnet sockets

33 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Antonio Fortuny

Hi List.

I'm fighting against a boring problem. Within a WinCE application I need to control a TCP/IP client connection. The lnet package is used and things are going well so far. The problem is the timeout. How to implement a timeout control with the TLTCPComponent in the classic sequence:

Connect to server
send the request
wait for answer <<<---------- this is the point
check answer OR timeout
disconnect

I can't firgure out where the check for a timeout as the component does not implement nor defines any property or method to deal with timeouts. The event (that I use) OnReceive does its job
The procedures Get and GetMessage appear to be blocking. Since the component appears to work asynchronously, I have a little procedure which uses a Sleep(50): main theard is made to sleep but socket code too !

Maybe I miss something too.
Do you know any beautiful solution ?
Thanks.

Antonio.

Reply by email

Bernd
to Antonio Fortuny

2012/10/24 Antonio Fortuny :

Show quoted text 9 lines
Connect to server send the request wait for answer <<<---------- this is the point check answer OR timeout disconnect I can't firgure out where the check for a timeout as the component does not implement nor defines any property or method to deal with timeouts. The event (that I use) OnReceive does its job

Its all meant to be used completely asynchronously. The easiest way would be to start a TTimer and when the timer event fires check whether you have received an answer already or otherwise close the connection.

Reply by email

Antonio Fortuny
to Bernd

Le 24/10/2012 14:47, Bernd a ?crit :

Show quoted text 5 lines
Its all meant to be used completely asynchronously. The easiest way would be to start a TTimer and when the timer event fires check whether you have received an answer already or otherwise close the connection.

Yeah. Got the same with my Sleep loop.
Not very clean.

Show quoted text 7 lines
-- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Michael Schnell
to Antonio Fortuny: Hi List. I'm fighting against a boring problem. Within a WinCE application I need to…

IHMO, the optimum way to handle waiting on sockets, pipes, asnyc interfaces and similar stuff is to do a blocking read in a thread, use QueueAsyncCall() to notify the main thread (i.e. throw an event) when something has arrived and use a TThreadList (or something similar) to transfer the data from the worker thread to the main thread.

I do know that this works fine with Windows and Linux.

I have no idea about CE (and never will).

-Michael

Reply by email

Bernd
to Antonio Fortuny: Le 24/10/2012 14:47, Bernd a ?crit : Yeah. Got the same with my Sleep loop. Not very…

2012/10/24 Antonio Fortuny :

Show quoted text 7 lines
> Its all meant to be used completely asynchronously. The easiest way > would be to start a TTimer and when the timer event fires check > whether you have received an answer already or otherwise close the > connection. Yeah. Got the same with my Sleep loop. Not very clean.

You can also run the lnet in some kind of blocking mode, for this you need to assign a different eventer. (select eventer or epoll eventer or TBestEventer to automatically chooe the most appropriate eventer) and then you make a separate thread that will just call the CallAction method in an infinite loop. CallAction will block until an event happens and then you call it again and again. Note that with this approach all your lnet event methods will be called from within this event thread.

You can either use only one eventer (and only one event thread) for all your sockets (if you have multiple connections going on simultanously) or alternatively you could also create a new separate eventer and a new separate thread for each new connection. The latter will give you the same functionality as with blocking sockets.

The eventer has a timeout property, if you set it to a non zero value in milliseconds the callaction call will block only up to that amount of time, this way you can also count time and trigger actions on timeout in the eventer thread (and if you make one separate eventer thread for every connection you can easily achieve what you are trying to do).

Reply by email

Michael Schnell
to Bernd
Bernd wrote
select eventer or epoll eventer or TBestEventer to automatically chooe the most appropriate eventer

AFAIK epoll (and "select()" is strictly Linux based and he wants top use CE.

Does the LCL / RTL provide a portable implementation of this "eventer" stuff ?

-Michael

Reply by email

Antonio Fortuny
to Michael Schnell

Le 24/10/2012 15:48, Michael Schnell a ?crit :

Show quoted text 5 lines
On 10/24/2012 03:29 PM, Bernd wrote: > select eventer or epoll eventer or TBestEventer to automatically chooe > the most appropriate eventer AFAIK epoll (and "select()" is strictly Linux based and he wants top use CE.

Yep. I've tried to compile Indy for WinCE but there are a lot of problems. But I use Indy 10.5.8 on a regular basis with Lazarus and it compiles (the package seems to have some problems that I didn't solve yet). And icing on the cake, it works on Win32, Win64 and Linux ! I'll have a look anyway

Does the LCL / RTL provide a portable implementation of this "eventer" stuff ?

Good question.

Show quoted text 9 lines
-Michael -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Bernd
to Michael Schnell: AFAIK epoll (and "select()" is strictly Linux based and he wants top use CE. Does the LCL…

2012/10/24 Michael Schnell :

AFAIK epoll (and "select()" is strictly Linux based and he wants top use CE.

select eventer works on windows too, this is what TBestEventer will choose on windows. There are problems when using more than 63 sockets with the select eventer on windows because the winsock unit has this hardcoded upper limit in it (while it would be configurable in the original C headers) but the svn version of lnet includes a patch that will change this number to 1023 to make it comparable to the unix implementations.

Reply by email

Antonio Fortuny
to Michael Schnell: IHMO, the optimum way to handle waiting on sockets, pipes, asnyc interfaces and similar…

Le 24/10/2012 15:14, Michael Schnell a ?crit :

Show quoted text 5 lines
IHMO, the optimum way to handle waiting on sockets, pipes, asnyc interfaces and similar stuff is to do a blocking read in a thread, use QueueAsyncCall() to notify the main thread (i.e. throw an event) when something has arrived and use a TThreadList (or something similar) to transfer the data from the worker thread to the main thread.

I know Indy does something like that too. But i'm afraid to go inside. In my vision, the wait with timeout problem is simply moved into a thread. The application has still to wait on something to happe. Because the client application can be blocked waiting for an answer from the TCP/IP server, it is acceptable that the user waits for something to happen.

I gonna try to use an Event tied to a timer and the socket receive event.

Event.ReSet;
Socket.SendMesssage;
Timer.Enabled := True;
WaitForSingleObject(Event);
On another hand, when the timer fires, it will execute in the event code:
Event.Set;
and when the socket has received all the message
Event.Set;

Question is: The two pieces of code for the timer(1) and the socket(2) will they be active when the main thread enters the wait state thru the WaitForSingleObject ?
No problem for the timer, it is the OS responsiblity to run, but the socket ?

The last idea is to move the socket into a thread so it can run independently of the application and set the Event when either all data has benn rea od the timer fires.

Show quoted text 13 lines
I do know that this works fine with Windows and Linux. I have no idea about CE (and never will). -Michael -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Michael Schnell
to Antonio Fortuny
Antonio Fortuny wrote
. In my vision, the wait with timeout problem is simply moved into a thread. The application has still to wait on something to happe.

Right, but it does not use up any CPU time while waiting, because same is done by the OS.

It is woken up immediately when the OS sees incoming data and so it will react without any delay and through the event.

The main thread's event queue is build in a way that it will handle all events in the order they appear and the main thread is woken up immediately when any event is thrown, so no delay here, as well, unless the man thread is busy with any other useful stuff.

-Michael

Reply by email

Paul Breneman
to Michael Schnell
Michael Schnell wrote 8 lines
On 10/24/2012 04:42 PM, Antonio Fortuny wrote: > I gonna try to use an Event tied to a timer and the socket receive event. > With this you will feature a possible delay (latency) as long as the timer period, and additionally the timer will use up CPU cycles even if nothing is to be done at all. -Michael

I think the timer was for a timeout so normally it wouldn't introduce any latency.

Reply by email

Bernd
to Antonio Fortuny: Le 24/10/2012 15:14, Michael Schnell a ?crit : I know Indy does something like that too.…

2012/10/24 Antonio Fortuny :

Question is: The two pieces of code for the timer(1) and the socket(2) will they be active when the main thread enters the wait state thru the WaitForSingleObject ?

Is this an LCL application? If yes then you may MOT block the main thread that way. Neither the timer nor the lnet event would be able to fire anymore, it would be frozen forever.

Why don't you just make it everything entirely evented and do not block anything?

Reply by email

Andrew Brunner
to Paul Breneman: I think the timer was for a timeout so normally it wouldn't introduce any latency.
Paul Breneman wrote
I think the timer was for a timeout so normally it wouldn't introduce any latency.

Yes, latency on an embedded device typically translates to diminished cpu performance and battery life. Asynchronous sockets and app logic methodology is best. Restful state is important especially for embedded apps. There should be a sample socket client with app logic developed to show how to do this stuff on embedded systems.

Andrew Brunner Aurawin LLC 512.574.6298 A safe new way to store and share your files, pictures, videos, and more. http://aurawin.com/

Reply by email

Bernd
to Michael Schnell: This is Windows stuff. -Michael

2012/10/24 Michael Schnell :

Show quoted text 5 lines
> WaitForSingleObject ? > Is this an LCL application? This is Windows stuff.

I assumed he is making an LCL appplication because LCL exits for win-CE too. Also there are platform independent locks and events in the RTL. (RTLEventWaitFor() and friends)

It is not clear to me what exactly "the application needs to wait" should exactly mean in this context. For example it could just as well pop up a modal dialog (with a cancel button) and the timer event (or the receive event, whichever comes first and both would come from the main thread) could close it again, maybe this would be "waiting" enough already?

Reply by email

Michael Schnell
to Bernd
Bernd wrote
It is not clear to me what exactly "the application needs to wait" should exactly mean in this context.

I think, in a socket-related application, it is rather obvious that the application needs to wait on data from the socket to arrive. (Same with Pipes, Async Interfaces, ...)
And while waiting, the application needs to be able to react on other "Events" (e.g. those that are generated by the LCL in the standard way (such as Mouse and Keyboard - generated, TTimer, ... ), and that it is important to reduce Latency and CPU overhead a much as possible, to me the obvious way top go is use a blocking read in a thread and have the thread insert (mix with the other events) a main thread event by QueueAsyncCall (which is platform independent and created exactly for that purpose).

Of course in this picture a TTimer can be use to manage receive timeouts (e.g. close the socket and kill the thread).

-Michael

Reply by email

Michael Schnell
to Bernd: 2012/10/24 Michael Schnell : select eventer works on windows too, this is what…

I understand that the "eventer" (like the "epoll()" Linux API call) can make the (main-)thread sleep (in the OS) and have it woke and without latency branch to the appropriate handler code as soon as one of the affiliated "events" (such as availability of incoming data from a Socket / Pipe / Async Interface) happens.

Some questions:

- Can such an "eventer" be used in the main thread and in worker threads ?
- If used in the main thread, can the "eventer" decently coexist with LCL based Events (such as TTimer, GIU, QueueAsyncCall, ...),
- If Yes: How ?
- If No: Is there a way to use a timer (obviously not a TTimer Object, but some other Object that might be provided by the library) ?
- If No: Same question regarding QueueAsyncCall.

Thanks,
-Michael

Reply by email

Antonio Fortuny
to Bernd: 2012/10/24 Antonio Fortuny : Is this an LCL application? If yes then you may MOT block…

Le 24/10/2012 17:27, Bernd a ?crit :

Show quoted text 9 lines
2012/10/24 Antonio Fortuny : > Question is: The two pieces of code for the timer(1) and the socket(2) will > they be active when the main thread enters the wait state thru the > WaitForSingleObject ? Is this an LCL application? If yes then you may MOT block the main thread that way. Neither the timer nor the lnet event would be able to fire anymore, it would be frozen forever.

This is what I suspected

Why don't you just make it everything entirely evented and do not block anything?

Because application processing does not permit shuch a way. It is a client TCP application and requests only one socket connected to one server. An entirely evented application is not manageable in this context

Reply by email

Antonio Fortuny
to Michael Schnell: I think, in a socket-related application, it is rather obvious that the application needs…

Le 25/10/2012 09:50, Michael Schnell a ?crit :

Show quoted text 6 lines
On 10/24/2012 05:43 PM, Bernd wrote: > It is not clear to me what exactly "the application needs to wait" > should exactly mean in this context. I think, in a socket-related application, it is rather obvious that the application needs to wait on data from the socket to arrive. (Same with Pipes, Async Interfaces, ...)

You got it. This is how the WinCE application runs: user reacts on a Form
the appropriate form event is lauched
some information is needed from the server before carry on any further processing
ask the net server:
open connection
send request
wait for answer
close connection
decide what to do next in case of any error
process answer and do whatever has to be done
this means that the application Q cannot be used: the user event method cannot be exited before the answer to the remote server. The application is freezed, ok.

And while waiting, the application needs to be able to react on other "Events" (e.g. those that are generated by the LCL in the standard way (such as Mouse and Keyboard - generated, TTimer, ... )

that's what I'm looking for
, and that it is

important to reduce Latency and CPU overhead a much as possible,

in my case it dosn't matter if some mili-seconds are spent. It is an application on hand help devices used in point of sales departments. to me

the obvious way top go is use a blocking read in a thread and have the thread insert (mix with the other events) a main thread event by QueueAsyncCall (which is platform independent and created exactly for that purpose).

Right, but does that mean that the lnet cpmponent should be into the thread range ? Otherwise I don't see how to have the component defined in the main thread scope and have an event active in an independent thread

Of course in this picture a TTimer can be use to manage receive timeouts (e.g. close the socket and kill the thread).

Sounds good for me:
wrapper around the TLTcp
includes the working thread
a Timer is set with tth timeout limit
an event is created and reset when request is started the application enters WaitForSingleObject(Event)
if Timer fires before the thread has terminated,
the event is set
some flag is set showing timeout
if thread terminates in time
data is moved to main thrad space
it sets the event
don't care for buffer share: thread writes it, main app reads only anf timer does not use it
don't care for event share: whichever comes first sets it whatever event occurred, thread is terminated and destroyed

Show quoted text 9 lines
-Michael -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Antonio Fortuny
to Bernd: 2012/10/24 Michael Schnell : I assumed he is making an LCL appplication because LCL exits…

Le 24/10/2012 17:43, Bernd a ?crit :

Show quoted text 14 lines
2012/10/24 Michael Schnell : >> WaitForSingleObject ? >> Is this an LCL application? > > > This is Windows stuff. I assumed he is making an LCL appplication because LCL exits for win-CE too. Also there are platform independent locks and events in the RTL. (RTLEventWaitFor() and friends) It is not clear to me what exactly "the application needs to wait" should exactly mean in this context.

Nothing else that waiting for information from the net server which will decide what to do on the user's request which fired the visual component event.
For example it could just as well

pop up a modal dialog (with a cancel button)

Response times from the server (depending on data amount and DB access) go between 0.5 and 2 secs. A classic wait modal window will be annoying. On a user point of view, click a button and see result within 2 or 3 seconds. With WinCE hand held devices (240 x 320) windows managing looks like the horror room.
and the timer event (or

the receive event, whichever comes first and both would come from the main thread) could close it again, maybe this would be "waiting" enough already?

Reply by email

Michael Schnell
to Antonio Fortuny: Le 25/10/2012 09:50, Michael Schnell a ?crit : You got it. This is how the WinCE…
Antonio Fortuny wrote
Right, but does that mean that the lnet cpmponent should be into the thread range ?

I don't really know in what way lnet can help you, but if it does not use LCL events or GUI stuff, it should be no problems to use it in a in thread. Or you could just extract the code pieces that might be useful for you and implant them in your own code.

Otherwise I don't see how to have the component defined in the main thread scope and have an event active in an independent thread

_Defining_ a component has nothing to do with the thread context is is going to _run_ in. (e.g. TThreadList.Create usually is called in the main thread while e.g. the Add procedure obviously is meant to be called in a worker thread. ) So I suppose you can Create an lnet instance wherever you want and call the function that results in a (blocking) read of the socket in a thread. (But as always with thread you need to be aware of stuff that can't be concurrently used and protect this with critical sections.)

Sounds good for me:

I hope for the best.

(But OTOH, I am not sure that things like QueueAsyncCall are correctly implemented with the CE version of the LCL. I did test them with Windows and KDE. I do have a testing project for this kind of thread communication.

data is moved to main thrad space

You don't actually need to _move_ the data, you just need to take care that mutual access is decently handled.

You can
Thread:
- create a buffer (e.g. creating a data holder object or using alloc() )
- fill the buffer
- push the pointer in a TThreadList
- create the event
- don't ever access this instance of the buffer
Main Thread

Event-Handler:

-->
- is TThread empty then exit
- pull the pointer from the TThreadList
- handle the Data
- free the buffer.
- loop to -->

-Michael

Reply by email

Bernd
to Michael Schnell: I understand that the "eventer" (like the "epoll()" Linux API call) can make the…

2012/10/25 Michael Schnell :

Show quoted text 6 lines
Some questions: - Can such an "eventer" be used in the main thread and in worker threads ? - If used in the main thread, can the "eventer" decently coexist with LCL based Events (such as TTimer, GIU, QueueAsyncCall, ...), - If Yes: How ?

The eventer that is used by default when putting an lnet component onto an LCL form is different from the other eventers that lnet provides. This one is tightly integrated into the LCL and fires its event from the main thread, just like button clicks and other GUI events. No sleeping and blocking is required here by your application and no worker threads.

All other eventers (select, epoll, kqueue) are only meant to be used when you explicitly not want the events to be generated by the LCL main thread, for example when there is no LCL at all because you are writing a command line program or using a different GUI framework for which no lnet eventer has been written (yet). These eventers always block. They have a timeout, so you can make them wake up every x milliseconds but still they block all of the time. So the usual way to use them is a separate thread that does nothing other than to wait in a CallAction() call. All the OnXxxx methods of your socket objects will then be called from within that thread and you need to take care of that fact when talking to the main thread. Thats the reason you should use the existing LCL eventers when you have LCL in your application, they will free you from all this trouble.

Reply by email

Michael Schnell
to Bernd
Bernd wrote 5 lines
The eventer that is used by default when putting an lnet component onto an LCL form is different from the other eventers that lnet provides. This one is tightly integrated into the LCL and fires its event from the main thread, just like button clicks and other GUI events.

Sounds nice.

No sleeping and blocking is required here by your application and no worker threads.

I suppose you mean "...is required by the user to be handled". That means that the waiting (here of course not "sleeping", as the "sleeping" is done in the LCL) is done in some "magical" way in the guts of the lnet code. This does sound nice. Could you explain how it is done and if it is done in a _decent_ way (i.e. not performing any polling which would introduce latency and CPU cycle overhead) ?

All other eventers (select, epoll, kqueue) are only meant to be used when you explicitly not want the events to be generated by the LCL main thread,

Good for applications that don't use the LCL and (maybe) for using it in worker Threads.

These eventers always block.

That is what I understand an "eventer" does: It blocks until one of the affiliated events is scheduled.

They have a timeout, so you can make them wake up every x milliseconds but still they block all of the time.

So the events that can be affiliated are generated by the socket in question plus a timeout. No more ?

Thats the reason you should use the existing LCL eventers when you have LCL in your application,

What do you mean by "LCL eventers" (in fact I already searched the LCL source code and "eventer" is nowhere to be found).

The only thing I see in the LCL that is an Eventer is the central Main thread event queue, that calls all event handlers attached to events generated by GUI, TTimer, TThread.Synchronize, QueueAsncCall, PostMessage, ...

-Michael

Reply by email

Bernd
to Antonio Fortuny: Le 25/10/2012 09:50, Michael Schnell a ?crit : You got it. This is how the WinCE…

2012/10/25 Antonio Fortuny :

Show quoted text 15 lines
You got it. This is how the WinCE application runs: user reacts on a Form the appropriate form event is lauched some information is needed from the server before carry on any further processing ask the net server: open connection send request wait for answer close connection decide what to do next in case of any error process answer and do whatever has to be done this means that the application Q cannot be used: the user event method cannot be exited before the answer to the remote server. The application is freezed, ok.

Here is an alternative way to implement it (this one can even reply and have a conversation of multiple commands going forth an back between the client and server):

pocedure OnEverythingGetsStarted;
begin
   if State = WAITING then exit;
   State := WAITING
   maybe also disable some buttons that might interfere
   open the connection
   send the request
   start the timeout timer
   // return from that event
end;
procedure OnTimer;
begin
  if State = WAITING then begin
    Disconnect
    State := IDLE
    enable the disabled buttons
  end;
end;
procedure OnReceive(S: TLSocket);
begin
  Answer := S.GetMessage()
  case Answer of
  'foo': begin
     DoThis();
     SendAnotherCommand();
  end
  'bar': begin
     DoThat();
     SendSomeThingDifferent();
  end
  else begin
     DoWhateverNeedsToBeDone();
     S.Disconnect;
     State := IDLE;
     enable the disabled buttons
  end;
end;

This will never block and never freeze and never eat any unneeded CPU cycles and it is les code than messing around with the eventers and CallAction directly and also less code than low level programming against sockets and/or winsock2 directly.

Reply by email

Michael Schnell
to Bernd
Bernd wrote 5 lines
This will never block and never freeze and never eat any unneeded CPU cycles and it is les code than messing around with the eventers and CallAction directly and also less code than low level programming against sockets and/or winsock2 directly.

Sounds good !
Of course the "ObjectPascalish" way to do things is handle everything in events.
If lnet really internally provides means to fire main-thread-events (such as "OnReceive"), that work fine concurrently with GUI events (I did not know that lnet can do this), of course just using what lnet provides is the way to go,

Now the next question is whether lnet integrates with the CE-flavor of the LCL as well as it seemingly does with the Windows and KDE-flavor. (The LCL "eventer" (aka Queue) implementation is different with any "flavor" (aka "Widget Type") ).

-Michael

Reply by email

Antonio Fortuny
to Bernd: 2012/10/25 Antonio Fortuny : Here is an alternative way to implement it (this one can…

Le 25/10/2012 13:07, Bernd a ?crit :
very nice indeed and readable even on pseudo-code, but ...

Show quoted text 13 lines
Here is an alternative way to implement it (this one can even reply and have a conversation of multiple commands going forth an back between the client and server): pocedure OnEverythingGetsStarted; begin if State = WAITING then exit; State := WAITING maybe also disable some buttons that might interfere open the connection send the request start the timeout timer // return from that event

this is exactly what I have to avoid: user gains control on screen. A workaround is to disable the window itself. But then another timer is needed to ensure that whatever happens or NOTHING happens, control will return back to the starting point.
Furthermore, all requests coded until now have to be moved outside of the procedures or events holding them: a lot of work What if:

pocedure OnEverythingGetsStarted;
*var
AHandles: PWOHandleArray;*
* **Res: DWORD;*
begin

    if State = WAITING then exit;
    State := WAITING
    maybe also disable some buttons that might interfere
    open the connection
    Event.ResetEvent;  // not signaled
    send the request
    start the timeout timer
    AHandles[0] := Timer.Handle;
    AHandles[1] := Event.Handle;	// posted by the OnReceive
  event
    Res:=WaitForMultipleObjects(2, @AHandles, False, Timeout);
    // wait for first reset, not interested for all
    case Res of
      ... continue processing depending of the answer or no answer
    end;
end;
Show quoted text 7 lines
end; procedure OnTimer; begin if State = WAITING then begin Disconnect State := IDLE
             Timer.enabled := False;
Show quoted text 7 lines
enable the disabled buttons end; end; procedure OnReceive(S: TLSocket); begin Answer := S.GetMessage()
forget about the rest of the procedure and do instead:
         DoWhatEverBeforeProcessData(Answer);
         Event.SetEvent;    // event signaled
Show quoted text 9 lines
case Answer of 'foo': begin DoThis(); SendAnotherCommand(); end 'bar': begin DoThat(); SendSomeThingDifferent(); end

.. I have dozens of messages to process in the internal protocol

Show quoted text 12 lines
else begin DoWhateverNeedsToBeDone(); S.Disconnect; State := IDLE; enable the disabled buttons end; end; This will never block and never freeze and never eat any unneeded CPU cycles and it is les code than messing around with the eventers and CallAction directly and also less code than low level programming against sockets and/or winsock2 directly.

Anyway, I can agree with this above.
But the application has to be re-engineered.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20121025/a5a97bdf/attachment.html>

Reply by email

Bernd
to Michael Schnell: Sounds nice. I suppose you mean "...is required by the user to be handled". That means…

2012/10/25 Michael Schnell :

Show quoted text 6 lines
I suppose you mean "...is required by the user to be handled". That means that the waiting (here of course not "sleeping", as the "sleeping" is done in the LCL) is done in some "magical" way in the guts of the lnet code. This does sound nice. Could you explain how it is done and if it is done in a _decent_ way (i.e. not performing any polling which would introduce latency and CPU cycle overhead) ?

On windows it is handled by existing windows API that fires windows messages on socket events, the recommended way to do networking on windows. On other widgetsets I have not yet deeply looked into the code how it is done but I guess it is using the recommended ways to do this with the help of the widgetset libs directly there too. The code for these LCL eventers is separate from the rest of the lnet code, its not in the lib folder, its in the folder that contains the lazarus packages.

Show quoted text 12 lines
> All other eventers (select, epoll, kqueue) are only meant to be used > when you explicitly not want the events to be generated by the LCL > main thread, Good for applications that don't use the LCL and (maybe) for using it in worker Threads. > > These eventers always > block. That is what I understand an "eventer" does: It blocks until one of the affiliated events is scheduled.

exactly. The select eventer for example is just a thin wrapper around the unix select() function, the TEventer object maintains a list of sockets it is responsible for and when you call CallAction() it calls a blocking select() with this list of sockets and after that returns it loops through all affected sockets and calls their appropriate OnXxx methods and then CallAction() returns (and you are supposed to call it again and again).

Show quoted text 5 lines
> They have a timeout, so you can make them wake up every x > milliseconds but still they block all of the time. So the events that can be affiliated are generated by the socket in question plus a timeout. No more ?

See above, the select is called with this timeout parameter to make it return after some time even if no evens have happened but only meant to check some things (maybe the program wants to end) and then you are supposed to immediately call it again. If select() returns because an event has happened the eventer goes through all affected sockets in its list and calls the OnRead, OnWrite or OnError methods and the socket objects themselves (depending on what type they are or which state they are in) then call their appropriate OnConnect, OnDisconnect, OnReceive, OnAccept handlers, all that ultimately happens from the eventer thread and originates from within this CallAction() call. In the LCL eventer thee calls originate from the receiving of a windows message sent from the system.

What do you mean by "LCL eventers" (in fact I already searched the LCL source code and "eventer" is nowhere to be found).

Its part of the Lazarus package in lnet (a separate folder in the lnet download) there you find code that derives from TEventer base class and implements all the stuff needed to hooks into the LCL and the widgetset. These eventers do not have this blocking CallAction() method because they are supposed to somehow register and react to windows messages on windows (and some similar magic on other widgetsets, I am not very familiar with this part of lnet becaue I have spent most of my time with lnet using it inside a non-gui library and there I have used the select eventer and one dedicated eventer thread and my own homegrown message pump to communicate between threads.

Reply by email

Michael Schnell
Bernd wrote
. If it does not work then it is worth to provide patches to make it work

Yep.

I only think that if it does not work, it's more likely that a patch for the LCL is necessary than for lnet. In fact CallAsyncQueue and PostMessage did not work with the KDE WidgetType (but did work in Windows) until some years ago I filed a bug report and someone kindly did a patch. (That is why I offered m<y testing program to check the CE Widget Set.)

Show quoted text 5 lines
(the author of lnet is very responsive), IMHO lnet is such a nice little piece of code (at least the really *small* networking core, the few essential units that make up all the eventer and socket mechanism) it really deserves to be supported by all widgetsets and deserves more attention.

Yep.

Some years ago, with Delphi I used to use AsyncPro (that can do Sockets and ComPorts and provides a common high-Level encapsulation (providing said main thread events) for both.

Is there an lnet variant for ComPorts as well ? Here and in other forums I often see the same questions we just discussed also regarding ComPorts.

Obviously the eventing mechanism can be implemented identically for any type of Byte-stream.

-Michael

Reply by email

Michael Schnell
to Antonio Fortuny: Le 25/10/2012 13:07, Bernd a ?crit : very nice indeed and readable even on pseudo-code,…
Antonio Fortuny wrote
this is exactly what I have to avoid: user gains control on screen. A workaround is to disable the window itself.

Maybe better: do the calculation in the background (maybe in a thread) and only when ready update the screen and react on any user actions.

-Michael
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20121025/0ce177f1/attachment.html>

Reply by email

Michael Schnell
Bernd wrote
In my example I mentioned a modal dialog

Regarding the latest message by Antonio this seems like a good idea: a Modal dialogue blocks the GUI while not eating CPU time.

So he can fire same to prevent user interaction. Now the user can do nothing but "cancel". When one of the lnet events results in the appropriate state (ready), it can remove the modal dialogue.

-Michael

Reply by email